dart-sass编译element-ui打包出来的icon乱码的解决方案
最近负责的项目用的是element-ui库,sass编译用的是官网推荐的dart-sass,但是项目上线后会出现偶尔乱码的情况
通过检查发现,icon那里的content变成奇怪的字符了
原因
分析了一下这个问题出现的原因,如果一般使用不会出现这个问题,因为一般引入的是element-ui的css文件,问题出在于为了主题色变化啊,需要用到scss变量引入了scss文件
@import "~element-ui/packages/theme-chalk/src/index";
而dart-sass在编译element-ui里icon伪元素的content unicode编码时会转换成对应unicode明文,所以通过伪元素来展示的图标如el-icon-arrow:before{ content: "\e6df"},编译之后就变成了el-icon-arrow:before{ content: ""},“”便是一个双字节字符,导致出现乱码
解决方法
1、element-ui采用的时node-sass编译,可以把dart-sass换成node-sass,但是官网主推dart-sass,dart-sass会是未来主流
2、查网上资料发现可以和后端商量下,让css资源请求的响应头的Content-Type增加"charset=utf-8"声明,因为涉及到后端,所以具体笔者没试验过,不知道可不可行。
3、这个方法是网上查来的 https://github.com/styzhang/css-unicode-loader
对scss文件增加一层loader来将dart-scss编译成的css文件里面的双字节字符再转回16进制码
const CONTENT_MATCH_REG = /(?<!-)content\s*:\s*([^;\}]+)/g; // 找出伪元素里content那块内容
const UNICODE_MATCH_REG = /[^\x00-\xff]/g; // 找出非单字节符
function fun(source) {
source = source.replace(CONTENT_MATCH_REG, function (m, p1) {
return m.replace(UNICODE_MATCH_REG, function (m) {
return "\\" + m.charCodeAt(0).toString(16); // m.charCodeAt(0)返回字符串第一个字符的 Unicode 编码,后面再转16进制,前面加一斜杠
});
});
return source;
}
let test = `.el-icon-ice-cream-square:before {
content: "";
}
`;
console.log(fun(test));
// 打印结果
// .el-icon-ice-cream-square:before {
// content: "\e6da";
// }
可以通过安装大牛写的loader
npm install --save-dev css-unicode-loader
如果是vuecli3+ 则可以按如下配置
// vue.config.js
module.exports = {
configureWebpack: config => {
config.module.rules.filter(rule => {
return rule.test.toString().indexOf("scss") !== -1;
})
.forEach(rule => {
rule.oneOf.forEach(oneOfRule => {
oneOfRule.use.splice(oneOfRule.use.indexOf(require.resolve('sass-loader')), 0,
{ loader: require.resolve("css-unicode-loader")})
})
})
}
}