PostCSS 通过插件系统驱动 AST 转换实现 CSS 兼容性处理,核心只做解析、执行插件、输出三件事;插件顺序、stage 配置、解析器选择和 AST 协作逻辑共同决定最终样式正确性。

PostCSS 不是 Babel,但它在 CSS 领域承担了和 Babel 类似的角色:把「写起来爽、但浏览器还不认」的语法,变成「现在就能跑」的兼容代码。关键不在名字像不像,而在它怎么做到——靠插件系统驱动的 AST 转换,而不是硬编码语法支持。
PostCSS 本身不解析新语法,插件才决定它能处理什么
PostCSS 核心只做三件事:解析 CSS 成 AST、按顺序执行插件、把改完的 AST 输出为 CSS。它连 nesting 或 :has() 都不认识,除非你装了对应插件。
-
postcss-preset-env是目前最常用的“未来语法包”,它内部集成了对嵌套规则、自定义媒体查询、color-mix()、relative-color-syntax等的支持 -
postcss-nested只管嵌套,不管变量;postcss-custom-properties只管:root变量降级,不碰选择器逻辑 - 如果你用
postcss-scss解析器,PostCSS就能读 SCSS 文件(但依然需要postcss-nested等插件来转换嵌套)
为什么不能直接用 postcss-preset-env 代替所有插件
看似省事,实际容易踩坑。比如:
-
postcss-preset-env默认启用的特性受stage控制(stage: 2表示草案已较稳定),但nesting在 stage 3 才默认开启,不显式配置就写嵌套会报错或静默忽略 - 它对
@layer的支持依赖浏览器目标版本,如果browserslist设得太宽(如包含 IE11),整个插件可能跳过该特性转换 - 和
autoprefixer共存时,必须确保autoprefixer在postcss-preset-env之后执行——否则嵌套规则生成的子选择器可能没被加前缀
插件顺序直接影响输出结果,不是随便列个数组就行
在 postcss.config.js 中,插件执行顺序就是数组索引顺序。常见错误配置:
module.exports = {
plugins: [
'autoprefixer', // ❌ 错:嵌套生成的选择器还没出来,就提前加前缀
'postcss-preset-env'
]
}
正确顺序应为:
立即学习“前端免费学习笔记(深入)”;
module.exports = {
plugins: [
'postcss-preset-env',
'autoprefixer' // ✅ 对转换后的真实选择器加前缀
]
}
- 变量类插件(如
postcss-simple-vars)通常要放在最前面,因为后续插件可能依赖变量展开后的值 - 压缩类插件(如
cssnano)必须放最后,否则其他插件无法操作原始声明结构 - 某些插件(如
stylelint)建议只在开发时启用,避免干扰构建流程
AST 是插件协作的基础,但也是调试盲区
你写的 div { & .child { color: red } } 经过 postcss-nested 后,AST 节点里已经多出一条 div .child 规则;autoprefixer 拿到的就是这个新节点,不是原始嵌套结构。
- 没有 SourceMap 支持的插件(如老版本
postcss-preset-env)会让开发者难以定位编译后样式对应的源位置 - 多个插件同时修改同一节点(例如两个插件都重写
background声明),结果取决于谁后执行,且无明确冲突提示 - 用
postcss-cli --verbose或postcss-reporter可打印 AST 变化过程,但需手动开启,多数人跳过这步就直接上线了


















