你好,我是本文作者南一。如果有发现错误或者可完善的地方,恳请斧正,万分感谢!!
背景
为缩短前端工程的构建时长,决定将构建工具 webpack4 替换为 rspack。rspack最低要求的node版本为16,而工程中使用的 node-sass 却不支持,因此不得不将 node-sass 替换为 dart-sass。
实现步骤
1.依赖更新
sass 使用 1.78.0 版本,因为高版本有很多break更新,解析不了当前代码使用的语法
tnpm uninstall node-sass;
tnpm install sass-loader sass@1.78.0 -D;
2. 配置更新
sass 无法解析深度选择器/deep/需要替换成::v-deep。sass-loader 有一个配置项additionalData 可以在编译过程修改文件内容,利用其将完成替换。
{
test: /\.(sass|scss)$/,
use: [
isProd ? rspack.CssExtractRspackPlugin.loader : 'vue-style-loader',
'css-loader',
{
loader: 'sass-loader',
options: {
additionalData: async (content, loaderContext) => {
return content.replaceAll('/deep/', '::v-deep');
},
}
},
],
type: 'javascript/auto',
},
npm run build 后发现还是报错了,原来被引入的.scss文件不会经过sass-loader解析,sass-loader仅作用于.vue文件style块内的代码。只能单独处理了...
3. 替换 .scss 文件的内容
编写脚本遍历src所有文件,将后缀为.scss的文件替换深度选择器;在build时执行脚本。
{
"scripts": {
"build": "node ./replaceDeep.js && rspack build"
},
}
const fs = require('fs');
const path = require('path');
// 递归遍历文件夹内的所有文件
function walkDir(dirPath) {
const files = fs.readdirSync(dirPath);
files.forEach(file => {
if(['node_modules', 'dist'].includes(file)) return;
const filePath = path.join(dirPath, file);
const stat = fs.lstatSync(filePath);
if (stat.isDirectory()) {
walkDir(filePath);
} else if (file.endsWith('.scss')) {
replaceDeep(filePath);
}
});
}
// 替换文件内的'/deep/'为'::v-deep'
function replaceDeep(filePath) {
fs.readFile(filePath, 'utf8', function (err, data) {
if (err) {
return console.log(err);
}
const result = data.replaceAll(/\/deep\//g, '::v-deep');
fs.writeFile(filePath, result, 'utf8', function (err) {
if (err) return console.log(err);
});
});
}
walkDir(__dirname);
总结
node-sass已经不再维护了,官方也推荐使用dart-sass解析sass代码。在替换之后,需要同步组内同学使用新语法::v-deep。