为什么CSS Nano压缩后动画名称发生冲突

作者:袖梨 2026-09-10

CSS Nano 默认启用 identifiers 优化导致动画名冲突,因其将不同文件中同名 @keyframes 统一压缩为短标识符(如 a),需显式配置 identifiers: { keyframes: false } 禁用。

CSS Nano 压缩后动画名称冲突,根本原因不是“压缩错了”,而是它默认启用 reduceIdents(或新版中的 identifiers)优化项,会把不同文件里同名的 @keyframes 名字统一替换成更短的标识符(比如都缩成 a),导致浏览器只认最后一个——这和手写重复 @keyframes rotate 的效果一样,但更隐蔽。

为什么 CSS Nano 会把 keyframes 名称改掉

CSS Nano 的 identifiers 功能本意是减少体积:把 @keyframes fadeIn@keyframes slideIn 这类长名字压缩成 @keyframes a@keyframes b。但它默认不区分作用域,只要名字相同(哪怕在不同文件)、或生成哈希后碰撞,就可能被映射到同一个短名。

  1. 多个组件各自定义了 @keyframes bounce,压缩后全变成 @keyframes a
  2. 第三方库 CSS 和业务 CSS 都含 @keyframes spin,压缩时被合并为单个声明
  3. Vite / Webpack 构建中若未禁用该优化,即使用了 CSS Modules,@keyframes 仍可能被全局重命名(因为 @keyframes 是全局规则,不受模块化类名哈希保护)

如何关闭 CSS Nano 的 keyframes 名称压缩

必须显式配置,不能靠“不写就默认关”——新版 CSS Nano 默认开启 identifiers,且对 @keyframes 无例外逻辑。

  1. Vite 用户:在 vite.config.tsbuild.cssMinifyOptions 中传入 { identifiers: { keyframes: false } }
  2. Webpack + css-minimizer-webpack-plugin:配置 minimizerOptionsidentifiers: { keyframes: false }
  3. 直接调用 CLI:加参数 --identifiers.keyframes=false

注意:keyframes: false 只禁用动画名压缩,不影响类名或选择器;其他 identifier 类型(如 values)可保留以节省体积。

为什么加 ::global() 或 :global() 还是冲突

在 CSS Modules 文件里写 :global(@keyframes bounce) { ... },只是告诉构建工具“这段不要哈希类名”,但不阻止 CSS Nano 对 @keyframes 名本身做压缩。也就是说::global() 解决的是选择器作用域问题,不是名称碰撞问题。

  1. :global()@keyframes 能被外部引用,但名字仍会被 identifiers 改掉
  2. 真正要保名,必须关掉 CSS Nano 的 identifiers.keyframes,二者不互斥但职责不同
  3. 如果同时用多个 CSS-in-JS 库(如 styled-components + 全局 keyframes),也要确认它们没自己做 name mangling

最易被忽略的一点:即使你本地开发没复现,CI 构建环境也可能用更高版本的 CSS Nano(比如 v7+),默认行为更激进——别只测 dev 模式,务必验证 production 构建后的 CSS 文件里 @keyframes 名是否真实保留。

相关文章

精彩推荐