cssnano压缩需严格按postcss-import→autoprefixer→cssnano顺序配置,v6+须显式传参并禁用mergerules、sortselectors、discardempty、normalizewhitespace等高风险项,否则导致@supports消失、伪元素内容被删、fallback链断裂等线上事故。

压缩 CSS 本身不难,难的是压缩完样式还对——cssnano 默认行为太激进,@supports 消失、::before 内容被删、font-family fallback 链断裂、动态类名(如 text-${color})直接消失,都是真实线上事故。
cssnano 必须放在 autoprefixer 和 postcss-import 之后
顺序错了,压缩就等于破坏。常见错误配置是把 require('cssnano') 写在 postcss-import 前面,结果 @import "base.css" 根本没展开,产出文件直接缺依赖;或者写在 autoprefixer 前面,导致 -webkit-flex 还没加就被当成冗余干掉。
-
postcss.config.js中插件数组必须严格按此顺序:postcss-import→autoprefixer→cssnano - v6+ 版本不能只写
require('cssnano'),必须显式传参:require('cssnano')({ preset: 'default' }),否则报Invalid CSS after "" - Webpack 用户注意:
MiniCssExtractPlugin.loader的minimize: true已废弃,它会绕过 PostCSS 管道,退化成弱压缩
禁用 cssnano 中易误删的默认规则
cssnano 的 preset: 'default' 启用了 mergeRules、sortSelectors、reduceTransforms 等高风险转换,它们不看语义,只看字面重复或结构相似性。
- 关闭
mergeRules:防止.btn:hover和.link:hover被合并,导致 hover 效果失效 - 关闭
sortSelectors:避免伪类顺序被重排,a:focus:hover变成a:hover:focus后覆盖逻辑错乱 - 关闭
discardEmpty:保留::before { content: " "; }类空规则,字体图标不消失 - 关闭
normalizeWhitespace:IE11 下display: -ms-flexbox可能被格式化成非法值
推荐最小安全配置:{ preset: ['default', { mergeRules: false, sortSelectors: false, discardEmpty: false, normalizeWhitespace: false }] }
PurgeCSS 和 cssnano 的协作边界要划清
PurgeCSS 负责删未用规则,cssnano 负责压已有规则——但两者都可能删东西,叠在一起容易删过头。
- PurgeCSS 必须在
cssnano前执行,否则它分析的是已压缩过的“扁平化”代码,类名提取不准(比如bg-red-500被缩成br5就认不出了) - 动态类名必须进
safelist:正则/bg-(red|blue)-[0-9]+/比写死['bg-red-500']更可靠 - 如果用了
postcss-custom-properties,务必加preserve: true,否则变量还没替换就被cssnano当无效声明删了 - 多个
@import文件必须由postcss-import提前内联,否则cssnano只看到单个文件,跨文件重复规则压不动
上线前必须验证的三件事
压缩配置再对,也不代表线上一定稳。最终输出得人工过一遍。
- 打开浏览器开发者工具,逐个检查关键交互状态:hover / focus / active / disabled / is-active(动态插入的类)是否生效
- 搜索输出 CSS 中是否存在
@supports、content:、transform:等易被删的关键字,确认没被清空 - 比对压缩前后文件的
!important规则位置——合并后层叠顺序可能改变,后写的规则未必“后加载”
最容易被忽略的是:压缩效果完全依赖输入 CSS 的完整性。如果你的源文件分散在多个 @import 中,又没配 postcss-import,那 cssnano 就只是在给碎片做美容,体积压不动,还可能漏删。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











