cssnano是postcss构建阶段的压缩插件,不参与html运行时;必须在webpack/vite等工具中配置,置于autoprefixer之后,通过preset显式设置并禁用危险优化项以避免样式错乱。

cssnano 不会出现在 HTML 里,也不会在浏览器中运行——它只在构建阶段起作用。你看到的压缩效果,是构建工具(如 Webpack、Vite)调用 postcss + cssnano 处理源 CSS 后输出的结果。直接在 <link> 中引用未处理的源文件,cssnano 完全无感。
为什么 cssnano 配置写了却没压缩?
常见失效不是因为插件没装,而是构建链路断了或顺序错了:
-
postcss-loader的postcssOptions.plugins数组里没写require('cssnano')({ preset: 'default' })(注意不是旧版的options.plugins) -
autoprefixer和cssnano顺序颠倒:必须autoprefixer在前,否则cssnano可能误删-webkit-flex等前缀,导致 iOS 12 崩溃 - 用了
MiniCssExtractPlugin却还配了minimize: true—— 这个选项已废弃,会跳过 PostCSS 管道,退化成仅删空格的弱压缩 - 源 CSS 分散在多个
@import文件中,但没配postcss-import插件,cssnano只看到单个文件,无法做跨文件合并
默认 preset 导致样式错乱怎么办?
preset: 'default' 开了很多激进优化,默认启用 mergeRules、sortSelectors、reduceTransforms。这些会重排伪类顺序、合并看似重复的选择器,极易破坏行为逻辑:
-
a:hover被合并到a规则后,可能被a:focus覆盖 - 运行时动态插入的
.is-active类被提前合并,丢失 specificity -
display: -ms-flexbox在 IE11 项目中被normalizeWhitespace格式化成非法值 -
postcss-custom-properties处理的变量,若没设preserve: true,会被cssnano当作无效声明删掉
紧急修复配置:require('cssnano')({ preset: ['default', { mergeRules: false, sortSelectors: false, reduceTransforms: false }] })
如何验证 cssnano 真正生效?
别只看文件体积变小——那可能是其他工具干的。确认 cssnano 在工作,得看三件事:
- 构建日志里有没有
cssnano相关输出(Webpack 5+ 默认不打,可加stats: 'verbose'查看插件执行顺序) - 对比构建前后 CSS 源码:
/* comment */是否消失、#ff0000是否变成red、margin: 0px 0px 0px 0px是否缩为margin: 0 - 检查最终产出的
.css文件是否仍含未处理内容:比如@custom-media或color-mix()—— 若存在,说明postcss-preset-env或其他转换插件位置不对,压在了cssnano后面
真正容易被忽略的是:压缩效果高度依赖输入 CSS 的“完整性”。cssnano 不会主动解析 @import、不读取外部文件、不理解 JS 动态样式注入。它只处理传给它的那一坨字符串。所以,构建前确保所有样式已被 postcss-import 或构建工具内联完毕,才是压缩有效的前提。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











