CSS Nano 默认启用 identifiers 优化导致动画名冲突,因其将不同文件中同名 @keyframes 统一压缩为短标识符(如 a),需显式配置 identifiers: { keyframes: false } 禁用。
CSS Nano 压缩后动画名称冲突,根本原因不是“压缩错了”,而是它默认启用 reduceIdents(或新版中的 identifiers)优化项,会把不同文件里同名的 @keyframes 名字统一替换成更短的标识符(比如都缩成 a),导致浏览器只认最后一个——这和手写重复 @keyframes rotate 的效果一样,但更隐蔽。
CSS Nano 的 identifiers 功能本意是减少体积:把 @keyframes fadeIn、@keyframes slideIn 这类长名字压缩成 @keyframes a、@keyframes b。但它默认不区分作用域,只要名字相同(哪怕在不同文件)、或生成哈希后碰撞,就可能被映射到同一个短名。
@keyframes bounce,压缩后全变成 @keyframes a
@keyframes spin,压缩时被合并为单个声明@keyframes 仍可能被全局重命名(因为 @keyframes 是全局规则,不受模块化类名哈希保护)必须显式配置,不能靠“不写就默认关”——新版 CSS Nano 默认开启 identifiers,且对 @keyframes 无例外逻辑。
vite.config.ts 的 build.cssMinifyOptions 中传入 { identifiers: { keyframes: false } }
minimizerOptions → identifiers: { keyframes: false }
--identifiers.keyframes=false
注意:keyframes: false 只禁用动画名压缩,不影响类名或选择器;其他 identifier 类型(如 values)可保留以节省体积。
在 CSS Modules 文件里写 :global(@keyframes bounce) { ... },只是告诉构建工具“这段不要哈希类名”,但不阻止 CSS Nano 对 @keyframes 名本身做压缩。也就是说::global() 解决的是选择器作用域问题,不是名称碰撞问题。
:global() 让 @keyframes 能被外部引用,但名字仍会被 identifiers 改掉identifiers.keyframes,二者不互斥但职责不同最易被忽略的一点:即使你本地开发没复现,CI 构建环境也可能用更高版本的 CSS Nano(比如 v7+),默认行为更激进——别只测 dev 模式,务必验证 production 构建后的 CSS 文件里 @keyframes 名是否真实保留。