vue项目中icon乱码的问题及解决

问题描述

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

vue项目中icon乱码的问题及解决_第1张图片

原因分析

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

项目中的sass

vue项目中icon乱码的问题及解决_第2张图片

具体:

一般使用不会出现这个问题,因为一般引入的是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: “”},“”便是一个双字节字符,导致出现乱码。

解决方法

直接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:""}

vue项目中icon乱码的问题及解决_第3张图片

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

vue项目中icon乱码的问题及解决_第4张图片

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

你可能感兴趣的:(vue项目中icon乱码的问题及解决)