必须按 style-loader → css-loader → sass-loader 顺序配置,且 css-loader 要显式启用 modules 才能支持 .module.scss;否则只当普通全局样式处理。

必须按 style-loader → css-loader → sass-loader 顺序配置,且 css-loader 要显式启用 modules 才能支持 .module.scss;否则只当普通全局样式处理。
loader 执行顺序不能错
sass-loader 输出 CSS 字符串,css-loader 需要它来解析类名和 @import,style-loader 或 MiniCssExtractPlugin.loader 再把结果注入 DOM 或提取成文件。顺序颠倒会导致 css-loader 收到 JS 字符串而非 CSS,直接失效或报错。
- 正确顺序(开发环境):
['style-loader', 'css-loader', 'sass-loader'] - 生产环境用提取插件:
[MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] - 千万别写成
['sass-loader', 'style-loader', 'css-loader']——css-loader拿不到 CSS,模块化、@import、url()全崩
css-loader 的 modules 必须显式开启
Webpack 默认对 /\.module\.(scss|sass)$/ 启用模块化是启发式行为,不可靠。一旦你自定义了 rules 或用了 oneOf,这个自动匹配大概率被绕过。
- 推荐写法:
{ loader: 'css-loader', options: { modules: true } } - 语义更清:
{ modules: { mode: 'local' } }(等价于true) - 导出 JS 变量用:
{ modules: { mode: 'icss' } },配合 SCSS 中的:export块 - 禁用旧写法:
{ modules: { auto: true } }在 Webpack 5+ 已废弃,会被忽略
sass-loader 本身不决定模块化,只负责编译
sass-loader 对 .module.scss 文件没有任何特殊逻辑。它只按后缀匹配执行编译,输出仍是标准 CSS 文本。模块化是否生效,完全取决于 css-loader 是否启用了 modules,以及 loader 链是否完整。
-
sass-loader的additionalData(如注入全局变量)会进入编译上下文,但不影响模块作用域 - 若要用 Dart Sass,必须显式指定:
{ implementation: require('sass') },否则可能 fallback 到 Node Sass(已废弃) -
importLoaders: 1应设在css-loader的options里,确保它知道前面有 1 个 loader(即sass-loader)需回溯处理@import
常见错误现象与定位点
类名没哈希、import styles from './Button.module.scss' 返回空对象、:export 变量无法在 JS 中访问——这些问题 90% 出在 css-loader 配置缺失或 loader 顺序错乱。
- 检查打包后生成的 JS:如果
styles是空对象,说明css-loader没启用modules或根本没走到它那步 - 终端报错
Module parse failed: Unexpected character '@'?多半是sass-loader没在css-loader右侧,导致css-loader直接去解析 SCSS 语法 - 使用
MiniCssExtractPlugin时仍想调试样式热更新?得配style-loader的hmr选项,或开发环境单独用style-loader
真正容易被忽略的是 importLoaders 和 modules 的绑定关系:它不是 sass-loader 的参数,也不是 Webpack 全局开关,而是 css-loader 里一个极轻但极关键的数值型配置——少设这一项,所有 @import 的 SCSS 文件都会被当成普通 CSS 加载,变量、mixin 全失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











