DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
PanstarCloud:部署应用,接入 AI,云服务器与 AI 网关
OnlineSIM:在线接收短信,虚拟号码租用

esbuild 压缩嵌套 CSS 后,选择器多匹配了元素

esbuild 0.28.1 可能删掉嵌套选择器前的 &,改变内部 :not() 中 & 的含义。0.28.2 已修复;不能只看压缩后的样式仍是合法 CSS。

开发时样式只应用到内层元素,压缩后外层也被命中;输出仍是合法 CSS,构建也没有报错。若嵌套选择器的开头和内部 :not() 都用了 &,检查压缩器是否删掉了前面的那个。

esbuild 0.28.1 的 CSS 压缩存在这条误改,正式 0.28.2 已修复。问题不在于 & 总是不能省略,而在于省略后隐式嵌套规则可能改变内部 & 的含义。

删掉一个符号,匹配范围却扩大了

例如原样式:

.a .b {
  & .b:not(& .c) {
    color: red;
  }
}

旧压缩会生成相当于下面的结构:

.a .b {
  .b:not(& .c) {
    color: red;
  }
}

这两段不能在这里视为等价。原规则应匹配 .a 内第二层 .b,不应因此命中只有一层 .b 的元素;多层嵌套时,错误还能让本应逐层不同的自定义属性值变成同一个结果。

先保留源码、压缩输出与真实 DOM,比较具体元素的匹配和 computed style。不要因为输出能被浏览器解析,就只去查优先级、加载顺序或组件状态。源码本来就写错选择器、后续插件又改了规则时,则要分别处理。

使用保留必要 & 的正式版本

项目直接使用 esbuild 时,可在兼容范围内采用 0.28.2,更新锁文件并确认真正处理 CSS 的那份依赖已变化。框架可能内置另一份 esbuild,也可能实际使用 Lightning CSS;只升级顶层包不一定改变失败的压缩步骤。

暂不能更新时,可在受控分支中关闭相关 esbuild CSS 压缩再比较产物。若使用 JavaScript API,完整的 minify: false 只能在没有其他独立 minify 开关继续启用的条件下作为隔离;已有配置还需核对 minifySyntax 等细项。关闭压缩会增大产物,也不能消除其他处理器独立做出的改写。

不要为了恢复视觉效果,机械删除 :not() 条件,或把复杂嵌套手工展开成一长串猜测的选择器。展开时同样需要保持原有匹配范围和优先级。

验收保留一层与多层 .b 的对照,检查该匹配和不该匹配的元素,以及原先用于区分层级的自定义属性。还要按项目真实浏览器支持范围检查;修复压缩器不会给不支持 CSS 嵌套的浏览器补上实现。