问题描述

最近发现项目在测试环境下icon偶尔会出现乱码的情况,我自己本地一直没能复现,在测试环境复现的话就需要打开控制台,然后按键刷新,一次不行就多刷新几次,就可以复现这个问题。
在这里插入图片描述

原因分析

这个问题可能是因为项目中有用到element-ui库,而项目中安装的sass和element-ui源码中的sass(node-sass)安装版本不一致造成的。

  • 项目中的sass
    在这里插入图片描述

具体:

  • 一般使用不会出现这个问题,因为一般引入的是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: “”},“”便是一个双字节字符,导致出现乱码。
  • https://www.cnblogs.com/shandou/p/14867943.html

解决方法

  • 直接uninstall项目中的sass,然后安装node-sass(因为是公司项目,不好做修改)
    • node-sass 是用 node(调用 cpp 编写的 libsass)来编译 sass;node-sass是自动编译实时的
    • dart-sass 是用 drat VM 来编译 sass;dart-sass需要保存后才会生效
    • node-sass 因为国情问题经常装不上
    • sass官方已经将dart-sass作为未来主要的的开发方向了,有任何新功能它会优先支持
  • 和后端商量下,让css资源请求的响应头的Content-Type增加"charset=utf-8"声明。(没做尝试)
  • 看到大佬写的一个方法 https://github.com/styzhang/css-unicode-loader
    • 安装大佬写的loader
      yarn add css-unicode-loader --dev
      
    • 对应的配置
      if use vue-cli 4+ and scss(sass), add the loader in the vue config file .
      // vue.config.js
      module.exports = {
        configureWebpack: config => {
          const sassLoader = require.resolve('sass-loader');
          config.module.rules.filter(rule => {
            return rule.test.toString().indexOf("scss") !== -1;
          })
            .forEach(rule => {
              rule.oneOf.forEach(oneOfRule => {
                const sassLoaderIndex = oneOfRule.use.findIndex(item => item.loader === sassLoader);
                oneOfRule.use.splice(sassLoaderIndex, 0,
                	{ loader: require.resolve("css-unicode-loader") });
              });
            });
          }
      }
      

vue.config.js具体配置

const path = require('path');
const webpack = require('webpack');
const buildDate = JSON.stringify(new Date().toLocaleString());
let devServer = null;

try {
   devServer = require('./devServer');
}
catch (e) {
   devServer = {};
}

function resolve(dir) {
   return path.join(__dirname, dir);
}

// 将之前的plugins提出来封装成一个函数
function getPlugins() {
   const plugins = [
      // Ignore all locale files of moment.js
      new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
      new webpack.DefinePlugin({
         APP_VERSION: `"${require('./package.json').version}"`,
         BUILD_DATE: buildDate,
      }),
   ];

   return plugins;
}

const vueConfig = {
  // configureWebpack: {
  //    // webpack plugins
  //    plugins: [
  //       // Ignore all locale files of moment.js
  //       new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
  //       new webpack.DefinePlugin({
  //          APP_VERSION: `"${require('./package.json').version}"`,
  //          BUILD_DATE: buildDate,
  //       }),
  //    ],
  // },

   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') });
            });
         });
	  // 获取plugins函数的内容
      const plugins = getPlugins();
      //这里要返回一个对象
      return { plugins };
   },

   chainWebpack: (config) => {
      config.plugin('html')
         .tap(args => {
            args[0].title = process.env.VUE_APP_TITLE;
            return args;
         });
      config.module
         .rule('svg')
         .exclude.add(resolve('./src/assets/icons'))
         .end();
      config.module
         .rule('icons')
         .test(/\.svg$/)
         .include.add(resolve('./src/assets/icons'))
         .end()
         .use('svg-sprite-loader')
         .loader('svg-sprite-loader');
   },

   css: {
      loaderOptions: {
         less: {
            // DO NOT REMOVE THIS LINE
            javascriptEnabled: true,
         },
      },
   },

   devServer,

   // disable source map in production
   productionSourceMap: false,
   lintOnSave: true,
   // babel-loader no-ignore node_modules/*
   transpileDependencies: [],
};

module.exports = vueConfig;

验证方法

修改前yarn build,检查dist/css/app.xxx.css文件中的emp-icon-xxx:before{content:""}
在这里插入图片描述

修改后 yarn build ,检查dist/css/app.xxx.css文件中的emp-icon-xxx:before{content: '\xxx'}

在这里插入图片描述

Logo

前往低代码交流专区

更多推荐