cssnano需置于autoprefixer之后并显式配置preset: 'default',避免与构建工具双重压缩;禁用mergeRules、sortSelectors等激进规则以防样式失效。

cssnano 本身不压缩 CSS——它只是 PostCSS 流水线中一个插件;真正起效的是你把它放在正确位置、用对参数、并避开构建工具的隐式压缩干扰。
cssnano 必须放在 autoprefixer 之后
顺序错了,前缀就没了。cssnano 会把带前缀的重复声明(比如 -webkit-transform 和 transform)当成冗余删掉。如果它在 autoprefixer 前运行,那连前缀都还没加,压缩器就直接干掉“看似重复”的规则了。
-
postcss.config.js中plugins数组顺序必须是:require('autoprefixer')→ 其他转换类插件(如postcss-preset-env)→require('cssnano')({ preset: 'default' }) - 验证方法:临时注释掉
cssnano,跑一次构建,用浏览器开发者工具检查元素是否还有-ms-或-webkit-前缀;再放开,确认压缩后前缀仍在
cssnano v6+ 必须显式传 preset: 'default'
只写 require('cssnano') 会报错 Invalid CSS after ""——这不是配置语法错,而是 v6+ 废弃了默认 preset,必须手动指定。
- 正确写法:
require('cssnano')({ preset: 'default' }) - 不要用
{ preset: 'advanced' }或{ preset: 'safe' },前者已在 v5 后移除,后者是旧版 alias,v6+ 不识别 - 若需禁用某项优化(比如保留
@keyframes名称),得单独配选项:reduceIdents: false,而不是靠 preset 切换
避免和构建工具的内置压缩打架
Webpack、Vite、Meteor 都自带 CSS 压缩逻辑,硬塞 cssnano 进 postcss.config.js 很可能触发双重压缩,结果是 rem 被转成 px、@supports 被整个删掉、甚至输出空文件。
- Webpack:关掉
css-loader的minimize选项(设为false),让压缩只由css-minimizer-webpack-plugin控制 - Vite:默认不用 PostCSS 压缩,需手动在
vite.config.ts的css.postcss.plugins里加cssnano,且仅在build.minify !== 'esbuild'时生效 - Meteor:用
standard-minifier-css就够了,它内部已集成cssnano并自动对齐 PostCSS 配置;自己再配反而会让@import提升失效
压缩后样式失效?先查这几项激进规则
常见现象是本地开发一切正常,上线后按钮没颜色、布局错乱、display: none 意外生效。这不是 bug,而是 cssnano 默认启用了 aggressive 的转换规则。
- 禁用
mergeRules和sortSelectors:它们会重排伪类顺序(如把a:hover:focus变成a:focus:hover),破坏层叠优先级 - IE11 兼容项目必须禁用
normalizeWhitespace和reduceTransforms,这两项在旧引擎里易触发渲染异常 - 若用了
postcss-custom-properties,需在它的配置里加preserve: true,否则变量未被替换就压缩,导致值丢失
真正影响体积的不是 preset 名字,而是你有没有关掉那些会破坏运行时行为的规则;最容易被忽略的是构建链路中谁在真正执行压缩——很多时候你以为 cssnano 在干活,其实只是 css-minimizer-webpack-plugin 自带的 esbuild 引擎在默默折叠 calc()。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











