webpack通过Link标签注入自定义Bootstrap样式报SassError问题
按需定制Bootstrap并通过webpack分离注入样式的问题排查
已安装依赖
- webpack
- mini-css-extract-plugin
- sass
- node-sass
- sass-loader
- css-loader
初始配置逻辑
目标是将src/scss/custom-bootstrap.scss中引入的Bootstrap样式提取为独立CSS文件,通过link标签注入页面;项目其余scss/css文件走常规处理,通过style标签注入DOM。
1. Bootstrap样式单独处理规则
// 期望提取custom-bootstrap内容为独立CSS,通过link标签注入 { include: resolve('src/scss/custom-bootstrap.scss'), use: [ MiniCssExtractPlugin.loader, // 提取CSS为独立文件 "css-loader", // 解析CSS为JS模块 "sass-loader", // 编译SCSS为CSS ] }
对应custom-bootstrap.scss初始内容:
@import "~bootstrap/scss/bootstrap";
2. 通用样式处理规则
{ test: /\.(sc|c)ss$/i, exclude: resolve('src/scss/custom-bootstrap.scss'), use: [ "style-loader", // 将样式通过style标签注入DOM "css-loader", "sass-loader", ] }
报错信息
执行webpack构建时抛出sass编译错误:
Module build failed (from ./node_modules/sass-loader/dist/cjs.js): SassError: expected "{". ╷ 2 │ import API from "!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js"; .
尝试将scss中~路径替换为node_modules直接路径后,问题仍然存在。
问题原因
报错核心是webpack loader规则匹配逻辑问题:
单独处理Bootstrap样式的规则没有配置test属性,webpack在匹配loader时,无test的规则优先级低于带test的通用规则,导致custom-bootstrap.scss同时被两个规则命中,最终被style-loader的处理链处理——sass-loader接收到的内容已经被注入了style-loader的JS运行时代码,这类JS代码不符合SCSS语法规范,因此抛出"expected {"的语法错误。
可行修复方案
- 调整loader规则顺序,给特殊规则补充
test属性
将Bootstrap单独处理的规则放在通用规则之前(webpack按数组顺序从上到下匹配规则,命中后不再继续匹配后续规则),同时补充test属性保证匹配逻辑生效;另外必须在plugins数组中注册MiniCssExtractPlugin,否则无法正常输出提取的CSS文件。
修复后的完整配置片段:
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); const { resolve } = require('path'); module.exports = { // 其余entry、output等配置保持原有逻辑即可 module: { rules: [ // Bootstrap单独处理规则放最前面,优先匹配 { test: /\.scss$/i, include: resolve('src/scss/custom-bootstrap.scss'), use: [ MiniCssExtractPlugin.loader, "css-loader", "sass-loader" ] }, // 通用样式规则放后面 { test: /\.(sc|c)ss$/i, exclude: resolve('src/scss/custom-bootstrap.scss'), use: [ "style-loader", "css-loader", "sass-loader" ] } ] }, plugins: [ // 注册提取CSS的插件,可自定义输出文件路径和命名规则 new MiniCssExtractPlugin({ filename: 'css/[name].[contenthash:8].css' }) ] }
- 修正SCSS文件的依赖引入路径
如果你使用的是v10及以上版本的sass-loader,默认已支持直接从node_modules查找依赖,不需要加~前缀,将custom-bootstrap.scss中的引入语句修改为:
@import "bootstrap/scss/bootstrap";
- 移除冗余依赖避免冲突
你同时安装了sass(官方推荐的dart-sass实现)和node-sass(已停止维护的旧实现),建议直接卸载node-sass避免编译冲突:
npm uninstall node-sass
完成以上修改后重新执行构建,即可正常将Bootstrap样式提取为独立CSS文件通过link标签注入,其余业务样式仍通过style标签注入,不会再出现上述语法报错。
内容的提问来源于stack exchange,提问作者gglasses
相关产品推荐
相关产品推荐

