Webpack sass loader无法识别全局变量文件

23

我有这个Sass目录:

- _vars.scss
- main.scss

//vars.scss

$base-container: 1400px;

//主要的样式文件.scss

@import './vars';

在其他的 JS 文件中我有以下代码:

require('./some-module-sass-file');

//some-module-sass-file.scss

.container {
  width: $base-container;
}

问题是我在变量文件中有全局变量,但某个Sass模块文件无法识别它们并抛出错误:

解决方案是将这些全局变量导入到你的Sass模块文件中:

undefined variable $base-container

什么错误?顺便说一下,您导入vars文件的方式并不明显,但是却有一个带有下划线前缀_vars文件。 - zerkms
这不是完整的错误信息。为了有帮助性,提供完整的错误信息并将其格式化为问题的一部分。 - zerkms
所以 some-module-sass-file.scss 没有导入全局变量文件。 - zerkms
不,main.scss并没有。 - user233232
可能是重复问题:https://dev59.com/r2Ml5IYBdhLWcg3w96-L - cimmanon
显示剩余2条评论
6个回答

17

不使用sass-resources-loader:

感谢@Arseniy-II与这个帖子的帮助: https://github.com/webpack-contrib/sass-loader/issues/218

通过在你的webpack模块规则中使用loader选项,你可以给sass-loader指定一个数据属性,然后像预期的那样使用所有sass函数:

module: {
  rules: [
    // Apply loader
    {
      test: /\.scss$/,
      use: [
        'style-loader',
        'css-loader',
        {
          loader: 'sass-loader',
          options: {
            data: '@import "path/to/global.scss";',
            includePaths:[__dirname, 'src']
          },
        },
      ],
    },
  ],
}

这为什么不是被接受的答案呢?谢谢您先生。 - Adam McKenna
2
我猜这不是一个被接受的答案,因为提供给数据的全局变量会创建重复。 - maniteja
使用重写Bulma的CSS变量,对我很有效。 - Denis L
2
使用这种方法要小心,因为它会注入代码,从而破坏你的源映射。 - Rico Ocepek
2
在webpack 4中,数据和文件等选项不可用且将被忽略。 - Anton Matiash

12

您需要在使用这些变量的每个Sass局部文件中导入vars文件,因为每个局部文件都是独立编译的;除非您特别导入它们,否则它们将不会“知道”其他文件的存在。

如果您不想在每个Sass文件中键入import,您可以查看baggage-loader,它将自动为您添加这些内容。


第三方库怎么办?我遇到了麻烦,因为一些深层次的依赖项无法解析其内置变量... - tutuca
2
@tutuca 如果没有更多信息,我不能确定我能帮到你。这里的要点是,使用webpack时,每个Sass文件都是独立编译的。我想,如果你包含第三方的Sass文件,并且在使用它的地方都进行了引入,那么它应该如预期般工作,没有任何问题。 - Brendan Gannon
这种方法的问题在于,您可能会无意中打破基于加载顺序的优先规则。例如,如果您在一个文件中覆盖了 Twitter Bootstrap 中的某些内容,然后在另一个 scss 文件中覆盖了 Twitter Bootstrap 中的其他内容,现在您的第一个覆盖将被第二个 scss 文件顶部导入 Bootstrap 覆盖。至少这是我在自己的应用程序中看到的情况。 - cdmo
1
值得注意的是,模块化/组件化架构往往避免那些基于顺序的行为。例如,给每个元素一个描述性的类名(而不是ID),并针对特定元素进行定位,而不是依赖级联和继承样式。虽然你会失去CSS的某些"优雅",但是能够开发和重复使用独立模块是一种很好的权衡,我认为这很值得。 - Brendan Gannon
公正的观点,这是���的事情,“语义类�通常是更平滑的路径。💯 - cdmo

11

请注意,您需要在结尾处使用";

{
    loader: 'sass-loader',
    options: {
        additionalData:'@import "path/to/general.sass";',
    },
},

我必须使用path.resolve而不仅仅是一个字符串:resources: [path.resolve(__dirname, './../vars.scss')] - Alex

8
如果你使用的是Webpack 5,现在必须使用 additionalData,其他选项不再有效:
  {
      loader: 'sass-loader',
      options: {
        additionalData: '@import path/to/general.sass',
      }
  },

如果您这样做,您的一般 sass 或 scss 文件将会被预处理。

2
请将您的答案更新为正确的语法: additionalData: '@import "path/to/general.sass";', - Safwat Fathi

1

Webpack 4解决方案:

{
    loader: 'sass-loader', options: {
        sourceMap: true,
        prependData: '@import "pathto/vars";'
    },
}

为了让@import "pathto/vars";能够正常工作,你需要配置Webpack来解析这样的导入。因此,它只是在行首添加了这一行代码。

这个解决方案很好,因为你不会像使用sass-resources-loader那样遇到sourcemaps的问题。


0
你可以使用 text-transform-loader 包。
{
  test: /\.scss$/,
  use: [
      'style-loader',
      'css-loader',
      'sass-loader', 
      {
        loader: 'text-transform-loader',
        options: {
          prependText: `@import "${path.resolve(__dirname, './base.scss')}";`,
        }
      }
    ]
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接