3
头图

problem found

Recently, when using the shuttle frame component in the company's component library, it was found that the icon icons were all garbled.

image-20211017142911623.png

analyse problem

After the investigation found that the component style file ( scss ) introduced iconfont vector font icons, build, \e601 such Unicode characters after sass compiled, it becomes a literal characters (double-byte characters), resulting in garbled

.icon-ok:before {
  content: "\e601";
}

Sass after compilation

.icon-ok:before {
  content: "";
}

Solve the problem

(1) Upgrade sass version

image-20211017151101980.png

This problem has been fixed in the Sass@1.38.0 version. The version used in the project can be 1.38.0+ to 0616e891fda1b4. For details, see Sass update log

// index.scss
.icon-ok:before {
  content: "\e601";
}

Execute npx sass@1.38.0 index.scss index.css

// index.css
.icon-ok:before {
  content: "\e601";
}

/*# sourceMappingURL=index.css.map */

(2) Custom webpack loader

When it comes to building the analysis of the above problems Sass will Unicode characters compiled into a text character, then we can in loader queue sass-loader after adding our custom loader , the CSS text characters in translated Unicode characters? Of course it is possible

const CONTENT_MATCH_REG = /(?<!-)content\s*:\s*([^;\}]+)/g; // 找出伪元素里content那块内容
const UNICODE_MATCH_REG = /[^\x00-\xff]/g; // 找出非单字节符
function fun(source) {
  this.cacheable(); // 利用缓存来提高编译效率
  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;
}

test

let test = `.el-icon-ice-cream-square:before {
    content: "";
  }
`;
console.log(fun(test));
// 打印结果
// .el-icon-ice-cream-square:before {
//     content: "\e6da";
// }

You can refer to: https://github.com/styzhang/css-unicode-loader

(3) Custom webpack plugin

Several necessary conditions for developing the webpack

  • Obtain the compiler object, through which you can obtain information including config configuration, resource files, compilation information, hook functions, etc.
  • Compile the life cycle function of the phase, find a suitable hook function to handle the corresponding logic
  • The returned result supports both synchronous and asynchronous methods
/**
 * 编码unicode字符串
 * encodeUnicodeChar('•') // 等价于 '\\2022';
 */
module.exports.encodeUnicodeChar = function (str) {
  let content = "";
  for (let i = 0; i < str.length; i++) {
    const codePoint = str.codePointAt(i);
    if (codePoint > 127) {
      content += "\\" + str.codePointAt(i).toString(16);
    } else {
      content += str.charAt(i);
    }
  }
  return content;
};

module.exports.encodeCssContentUnicodeChar = function (css) {
  return css.replace(
    /([{\s;]content:\s?['"])(.+?)(['"][;\s}])/g,
    (match, p1, p2, p3, offset, str) => {
      return p1 + module.exports.encodeUnicodeChar(p2) + p3;
    }
  );
};

Execute before outputting the generated resource file after the build to the target directory, emit is an asynchronous series of hooks

const { encodeCssContentUnicodeChar } = require("./utils");

class CssContentUnicodePlugin {
  apply(compiler) {
    compiler.hooks.emit.tap("CssUnicodePlugin", function (compilation) {
      Object.keys(compilation.assets)
        .filter((filename) => /\.css$/.test(filename))
        .forEach((filename) => {
          const asset = compilation.assets[filename];
          let fileContent = asset.source();
          fileContent = encodeCssContentUnicodeChar(fileContent);
          asset.source = () => fileContent;
          asset.size = () => fileContent.length;
        });
    });
  }
}

module.exports = CssContentUnicodePlugin;

refer to:

Sass update log

sass unicode character encoding problem

Sass: Unicode escape is not saved in the .css file

webpack articles-plugin development

How to develop a webpack loader

webpack loader development


记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。