一、PostCSS 是什么?

PostCSS 将 CSS 转换为 JavaScript 可以操作的数据结构,这些数据可以由插件理解和转换,然后处理成各种需要的格式。

PostCSS并不是一门语言,而是一个类似于webpack的工具,它支持很多插件,来达到便捷的编译效果,组成一个CSS编译/lint/autoprefixer的生态圈。

PostCSS 本身是一个功能比较单一的工具。它提供了一种方式用 JavaScript 代码来处理 CSS。它负责把 CSS 代码解析成抽象语法树结构(Abstract Syntax Tree,AST),再交由插件来进行处理。

插件基于 CSS 代码的 AST 所能进行的操作是多种多样的,比如可以支持变量和混入(mixin),增加浏览器相关的声明前缀,或是把使用将来的 CSS 规范的样式规则转译(transpile)成当前的 CSS 规范支持的格式。从这个角度来说,PostCSS 的强大之处在于其不断发展的插件体系。

目前 PostCSS 已经有 200 多个功能各异的插件。开发人员也可以根据项目的需要,开发出自己的 PostCSS 插件。

实际上,PostCSS 的主要功能只有两个:

第一个就是前面提到的把 CSS 解析成 JavaScript 可以操作的 AST。

第二个就是调用插件来处理 AST 并得到结果。

因此,不能简单的把 PostCSS 归类成 CSS 预处理或后处理工具。PostCSS 所能执行的任务非常多,同时涵盖了传统意义上的预处理和后处理。

二、PostCSS 和 CSS预处理器的区别

PostCSS的一大特点是,具体的编译插件甚至是CSS书写风格,可以根据自己的需要进行安装,选择自己需要的特性:嵌套,函数,变量。自动补全,CSS新特性等等,而不是像less或者scss一样的大型全家桶。因此,不需要再专门去学习less或者scss的语法,只要选择自己喜欢的特性,可以只写 CSS 文件,但依旧可以写嵌套或者函数,然后选择合适的插件编译它就行了。

三、有什么用?

  • 可以检查(lint)你的 CSS
  • 支持 CSS Variables 和 Mixins
  • 编译尚未被浏览器广泛支持的先进的 CSS 语法
  • 内联图片
  • 模块化css
  • css in js

四、webpack 中怎么使用 PostCSS

  1. 依赖于 node.js
  2. 引入 postcss
1
2
npm install postcss -D
npm install postcss-loader -D
  1. 引入一些需要的插件
1
2
# eg:添加浏览器CSS兼容性前缀(如-webkit、-moz)的插件
npm install autoprefixer -D
  1. webpack 配置 loader(ps:可以直接在配置loader的地方配置options,也可以添加postcss.config.js配置文件配置options)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
// autoprefixer插件:添加了 vendor 浏览器前缀。
autoprefixer({
// 适配99%的浏览器,最新两个版本
overrideBrowserslist: ['> 1%', 'last 2 versions', 'not ie <= 8'],
}),
]
},
},
};

五、常见 PostCSS 插件

  • autoprefixer: 给css属性添加兼容性前缀
  • postcss-import: 合并样式
  • cssnano: 压缩css代码
  • postcss-preset-env: 允许你使用一些新的的css特性
  • postcss-html:它可以将html文件中的样式块中的CSS代码提取出来进行处理,这样可以使CSS代码更加集中、维护更简单

六、自定义一个 PostCSS 插件

  • Root:PostCss处理过的Css,整个处理过程基本上都在围绕着Root。Commont,AtRule,Rule都是它的子节点。
  • AtRule:为带@标识的部分,name为标识名称,params为标识参数。nodes为内部包含的其他子节点,可以是Commont,AtRule,Rule,这让我们可以自定义更多的规则
  • Rule:选择器样式部分,一个选择器代表一个Rule,选择器对应的样式列表nodes为Declaration构造函数
  • Declaration:为CSS样式属性,prop为样式属性,value为样式值。可给Rule手动添加样式属性,也可以修改prop,value。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
module.exports = (opts = { }) => {
// 此处可对插件配置opts进行处理
return {
postcssPlugin: 'postcss-test', // 插件名字,以postcss-开头
Once (root, postcss) {
// 此处root即为转换后的AST,此方法转换一次css将调用一次
},
Declaration (decl, postcss) {
// postcss遍历css样式时调用,在这里可以快速获得type为decl的节点(请参考第二节的AST对象)
},

Declaration: {
color(decl, postcss) {
// 可以进一步获得decl节点指定的属性值,这里是获得属性为color的值
// 下面的内容是把字体颜色替换了
if (decl.value === 'white') {
decl.value = 'green'
}
if (decl.value === 'red') {
decl.value = 'yellow'
}
}
},
Comment (comment, postcss) {
// 可以快速访问AST注释节点(type为comment)
},

AtRule(atRule, postcss) {
// 可以快速访问css如@media,@import等@定义的节点(type为atRule)
}
}
}
module.exports.postcss = true

将插件使用到 postcss 配置中?

1
2
3
4
5
6
7
8
9
plugins: [
// autoprefixer插件:添加了 vendor 浏览器前缀,它使用 Can I Use 上面的数据。
autoprefixer({
// 适配99%的浏览器,最新两个版本
overrideBrowserslist: ['> 1%', 'last 2 versions', 'not ie <= 8'],
}),
// 这里的url是自定义的插件的路径,{}是传入插件的参数
require('../src/tools/test-plugin')({})
]