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")})
        })
      })
    }
}
posted @ 2021-06-09 17:47  陈山豆  阅读(4600)  评论(7编辑  收藏  举报