为了兼容antd [兼容ie] 的代码而出的前端bug,麻了

531 阅读2分钟

bug表现

由于兼容ie的一段css代码,某一个文件的样式全部丢失。

微信截图_20241010135055.png

场景

我先说一下我们的场景,我们目前有一个主包 A。主包 A 使用 webpack 的 cssnano 进行压缩。然后有一个子包 A-1(神奇流程)。子包 A-1 是主包 A 的依赖。这个子包使用 vite 的 esbuild 进行压缩。其中子包A-1中依赖了antdv4.10

里面有 \9 这样一句兼容ie的代码

image.png

原因

  1. 最根本的原因在于 样式压缩库对于ie兼容代码的解析异常。A-1包中存在着ie的兼容代码,但是 cssnano 和 esbuild的解析同时有异常的情况。cssnano在 压缩的时候 会将无效的转义符进行压缩,而esbuild在解析的时候并没有将ie的兼容代码作为合法的字符。这会产出a{display:none \}这样的代码。最后把大括号的后半段转义了,导致整段css样式文件都会失效。具体可以参考我向esbuild提的issue:github.com/evanw/esbui…

最小复现bug源码

index.less

.ant-container{
    display: none \9;
}

esbuild.js

import fs from 'fs'
import { transform } from 'esbuild'
import postcss from 'postcss';
import cssnanoPlugin from 'cssnano';
let input = fs.readFileSync('./index.less','utf-8');

transform(input, { loader: 'css',minify: true }).then(({
    code
 })=>{
    // 写入文件
    postcss([cssnanoPlugin]).process(code).then(({ css }) => {
        console.log("css:", css)
        fs.writeFileSync('./index.css',css)
     })
 })

经过了上方的操作后,会生成如下代码

.ant-container{display:none \}

这段代码最后的那个转义符会毁了这个css文件。。

解决方案

  1. 解决方案:

    1. 方案1:子包取消压缩
    2. 方案2:统一用cssnano或者esbuild就不会有这个问题,因为尽管两个包都存在问题,但只有混用才会触发
    3. 方案3:子包采用 lightcssing进行压缩
  2. 后续: 向esbuild提mr,github.com/evanw/esbui…。 添加esbuild css解析器 关于ie代码的兼容识别。这个仓库采用go编写,因此需要重复 go build 才能进行发包,因此不能够作为hack patch添加进仓库中 ,然后evanw似乎认为是cssnano的问题更大一点,一个issue直接提到cssnano上去了(github.com/cssnano/css…)。嗨嗨嗨,虽然目前前端已经不再需要兼容ie,但是需要兼容对 兼容ie代码 的兼容。。。。心路历程是有点复杂的