PostCSS 插件系统 #
PostCSS 的核心是一个插件系统,所有功能都通过插件实现。理解插件系统是掌握 PostCSS 的关键。
插件工作原理 #
处理流程 #
text
┌─────────────────────────────────────────────────────────────┐
│ PostCSS 处理流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ CSS 源码 │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Parser │ ─── 解析 CSS 为 AST │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Plugin 1 │ ─── 处理 AST(如 Autoprefixer) │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ Plugin 2 │ ─── 处理 AST(如 cssnano) │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │Plugin N │ ─── 更多插件... │
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌────────────┐ │
│ │Stringifier │ ─── 将 AST 转换回 CSS │
│ └─────┬──────┘ │
│ │ │
│ ▼ │
│ CSS 输出 │
│ │
└─────────────────────────────────────────────────────────────┘
插件访问 AST #
每个插件可以访问和修改 AST:
javascript
// 插件结构
const plugin = () => {
return {
postcssPlugin: 'my-plugin',
// 访问整个 AST
Once(root) {
// 在所有节点处理前执行一次
},
// 访问特定节点类型
Rule(rule) {
// 处理每个规则
},
Declaration(decl) {
// 处理每个声明
},
AtRule(atRule) {
// 处理每个 @ 规则
},
Comment(comment) {
// 处理每个注释
}
}
}
plugin.postcss = true
插件加载顺序 #
顺序的重要性 #
插件按配置顺序依次执行:
javascript
// postcss.config.js
module.exports = {
plugins: [
// 1. 首先处理导入
require('postcss-import'),
// 2. 然后处理嵌套
require('postcss-nested'),
// 3. 接着处理变量
require('postcss-simple-vars'),
// 4. 添加浏览器前缀
require('autoprefixer'),
// 5. 最后压缩(必须在最后)
require('cssnano')
]
}
推荐顺序 #
text
1. 导入处理
└── postcss-import
2. 语法扩展
├── postcss-nested
├── postcss-simple-vars
├── postcss-mixins
└── postcss-functions
3. 未来特性
└── postcss-preset-env
4. 兼容性处理
└── autoprefixer
5. 优化压缩
└── cssnano
错误顺序示例 #
javascript
// ❌ 错误:cssnano 在前会导致其他插件无法正常工作
module.exports = {
plugins: [
require('cssnano'), // 压缩后无法处理嵌套
require('postcss-nested'), // 无法正常工作
require('autoprefixer')
]
}
// ✅ 正确:cssnano 在最后
module.exports = {
plugins: [
require('postcss-nested'),
require('autoprefixer'),
require('cssnano') // 最后压缩
]
}
插件配置方式 #
数组配置 #
javascript
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer'),
require('cssnano')
]
}
对象配置 #
javascript
// postcss.config.js
module.exports = {
plugins: {
autoprefixer: {
overrideBrowserslist: ['> 1%']
},
cssnano: {
preset: 'default'
}
}
}
带参数配置 #
javascript
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')({
overrideBrowserslist: ['> 1%', 'last 2 versions'],
grid: true
}),
require('cssnano')({
preset: ['default', {
discardComments: { removeAll: true }
}]
})
]
}
条件配置 #
javascript
// postcss.config.js
const isProduction = process.env.NODE_ENV === 'production'
module.exports = {
plugins: [
require('autoprefixer'),
// 只在生产环境压缩
isProduction && require('cssnano')({
preset: 'default'
})
].filter(Boolean) // 过滤掉 false 值
}
函数式配置 #
javascript
// postcss.config.js
module.exports = (ctx) => {
return {
plugins: [
require('autoprefixer')({
overrideBrowserslist: ctx.env === 'production'
? ['> 1%', 'last 2 versions']
: ['last 1 chrome version']
}),
ctx.env === 'production' && require('cssnano')
].filter(Boolean)
}
}
插件分类 #
按功能分类 #
text
PostCSS 插件分类:
├── 1. 预处理功能
│ ├── postcss-import # @import 处理
│ ├── postcss-nested # 嵌套语法
│ ├── postcss-simple-vars # 变量支持
│ ├── postcss-mixins # Mixin 支持
│ └── postcss-functions # 自定义函数
│
├── 2. 兼容性处理
│ ├── autoprefixer # 自动前缀
│ ├── postcss-preset-env # 未来特性
│ └── postcss-color-hex-alpha # 颜色处理
│
├── 3. 代码优化
│ ├── cssnano # CSS 压缩
│ ├── postcss-discard-comments # 删除注释
│ ├── postcss-merge-rules # 合并规则
│ └── postcss-normalize # 标准化
│
├── 4. 代码检查
│ ├── stylelint # CSS Lint
│ ├── postcss-bem-linter # BEM 检查
│ └── doiuse # 兼容性检查
│
├── 5. 特殊功能
│ ├── postcss-pxtorem # px 转 rem
│ ├── postcss-sprites # 雪碧图
│ ├── rtlcss # RTL 支持
│ └── postcss-write-svg # SVG 内联
│
└── 6. 框架/预设
├── tailwindcss # Tailwind CSS
├── postcss-cssnext # CSS Next
└── precss # 类 Sass 语法
按处理阶段分类 #
| 阶段 | 插件示例 | 说明 |
|---|---|---|
| 解析前 | postcss-import | 处理导入,合并文件 |
| 语法转换 | postcss-nested | 转换语法扩展 |
| 功能增强 | postcss-mixins | 添加编程特性 |
| 兼容处理 | autoprefixer | 添加浏览器前缀 |
| 优化压缩 | cssnano | 压缩和优化 |
常用插件详解 #
postcss-import #
处理 CSS 中的 @import 规则:
javascript
// postcss.config.js
module.exports = {
plugins: [
require('postcss-import')({
path: ['src/styles'], // 导入路径
plugins: [] // 对导入文件应用的插件
})
]
}
css
/* 输入 */
@import 'variables.css';
@import 'mixins.css';
.button {
color: var(--primary);
}
/* 输出(variables.css 和 mixins.css 内容被内联) */
:root {
--primary: #007bff;
}
.button {
color: var(--primary);
}
postcss-nested #
支持嵌套语法:
javascript
// postcss.config.js
module.exports = {
plugins: [
require('postcss-nested')
]
}
css
/* 输入 */
.button {
color: blue;
&:hover {
color: darkblue;
}
.icon {
margin-right: 8px;
}
}
/* 输出 */
.button {
color: blue;
}
.button:hover {
color: darkblue;
}
.button .icon {
margin-right: 8px;
}
postcss-simple-vars #
支持变量:
javascript
// postcss.config.js
module.exports = {
plugins: [
require('postcss-simple-vars')({
variables: {
primary: '#007bff',
secondary: '#6c757d'
}
})
]
}
css
/* 输入 */
$primary: #007bff;
.button {
color: $primary;
}
/* 输出 */
.button {
color: #007bff;
}
postcss-mixins #
支持 Mixin:
javascript
// postcss.config.js
module.exports = {
plugins: [
require('postcss-mixins')({
mixins: {
clearfix: {
'&::after': {
content: '""',
display: 'table',
clear: 'both'
}
}
}
})
]
}
css
/* 输入 */
@define-mixin button $color {
background: $color;
padding: 10px 20px;
border-radius: 4px;
}
.primary {
@mixin button blue;
}
/* 输出 */
.primary {
background: blue;
padding: 10px 20px;
border-radius: 4px;
}
postcss-preset-env #
使用未来 CSS 特性:
javascript
// postcss.config.js
module.exports = {
plugins: [
require('postcss-preset-env')({
stage: 2, // 0-4,数字越小越稳定
features: {
'nesting-rules': true,
'custom-properties': true
}
})
]
}
css
/* 输入 */
:root {
--primary: #007bff;
}
.button {
color: var(--primary);
&:hover {
color: color(var(--primary) blackness(+20%));
}
}
/* 输出 */
:root {
--primary: #007bff;
}
.button {
color: var(--primary);
}
.button:hover {
color: rgb(0, 94.8, 191);
}
cssnano #
CSS 压缩优化:
javascript
// postcss.config.js
module.exports = {
plugins: [
require('cssnano')({
preset: ['default', {
discardComments: { removeAll: true },
normalizeWhitespace: true,
colormin: true,
reduceIdents: false
}]
})
]
}
css
/* 输入 */
.container {
margin: 10px 10px 10px 10px;
padding: 0px;
}
.button {
color: #ff0000;
}
/* 输出 */
.container{margin:10px;padding:0}.button{color:red}
插件预设 #
使用预设 #
预设是一组预配置的插件:
javascript
// postcss.config.js
module.exports = {
plugins: [
// 使用预设
require('postcss-preset-env')({
stage: 2
}),
// 可以添加更多插件
require('cssnano')
]
}
创建自定义预设 #
javascript
// my-postcss-preset.js
const autoprefixer = require('autoprefixer')
const cssnano = require('cssnano')
const postcssNested = require('postcss-nested')
module.exports = (options = {}) => {
const plugins = [
postcssNested,
autoprefixer(options.autoprefixer || {})
]
if (options.minify) {
plugins.push(cssnano({ preset: 'default' }))
}
return plugins
}
javascript
// postcss.config.js
const myPreset = require('./my-postcss-preset')
module.exports = {
plugins: myPreset({
minify: process.env.NODE_ENV === 'production'
})
}
插件开发基础 #
简单插件 #
javascript
const postcss = require('postcss')
const myPlugin = postcss.plugin('my-plugin', (options = {}) => {
return root => {
root.walkDecls('color', decl => {
if (decl.value === 'red') {
decl.value = options.color || 'blue'
}
})
}
})
module.exports = myPlugin
使用新 API(PostCSS 8+) #
javascript
const plugin = () => {
return {
postcssPlugin: 'my-plugin',
Declaration(decl) {
if (decl.prop === 'color' && decl.value === 'red') {
decl.value = 'blue'
}
}
}
}
plugin.postcss = true
module.exports = plugin
插件调试 #
查看插件执行 #
javascript
const postcss = require('postcss')
const autoprefixer = require('autoprefixer')
const css = '.button { display: flex; }'
const result = await postcss([autoprefixer])
.process(css, { from: undefined })
// 查看消息
result.messages.forEach(msg => {
console.log(msg.type, msg.plugin, msg.text)
})
插件性能分析 #
javascript
const postcss = require('postcss')
const css = '/* 你的 CSS */'
console.time('postcss')
const result = await postcss([
require('postcss-import'),
require('postcss-nested'),
require('autoprefixer'),
require('cssnano')
]).process(css, { from: undefined })
console.timeEnd('postcss')
console.log(result.css)
插件生态 #
查找插件 #
插件质量判断 #
| 指标 | 说明 |
|---|---|
| 周下载量 | 越高越好 |
| GitHub Stars | 社区认可度 |
| 更新频率 | 是否积极维护 |
| 文档质量 | 是否有清晰文档 |
| TypeScript 支持 | 类型定义 |
下一步 #
现在你已经深入了解了 PostCSS 插件系统,接下来学习 常用插件 掌握更多实用插件!
最后更新:2026-03-28