写在前面的话
前端工程化日益成熟今天,我们对于工具越来越深的封装。不管是从 vue-cli 的 3.0 版本起,还是 umi、bigfish 等前端脚手架,对于 webpack 都封装在内,对于工程化无疑是高效的,但也在一定程度上让新手们者失去了从零配置一个项目的机会,所以很多时候还是希望能透过大神们的框架,研究一下底层结构。
简介
PostCSS 是一个通过 JS 插件转换样式表的工具,它本身并不是一门新的 CSS 语言,而是一个平台或者是生态心态,提供插件扩展服务即 JS API,开发者可以根据这些接口,定制开发插件,目前比较流行的插件工具如:Autoprefixer、Stylelint、CSSnano。
工作流
大致步骤:
将 CSS 解析成抽象语法树 (AST 树)
将 AST 树”传递”给任意数量的插件处理
将处理完毕的 AST 树重新转换成字符串
在 PostCSS 中有几个关键的处理机制:
Source string → Tokenizer → Parser → AST → Processor → Stringifier
Tokenizer
将源 css 字符串进行分词
举个例子:
.className {color: #FFF;}
通过 Tokenizer 后结果如下:
[
[“word”, “.className”, 1, 1, 1, 10]
[“space”, ” “]
[“{“, “{“, 1, 12]
[“space”, ” “]
[“word”, “color”, 1, 14, 1, 18]
[“:”, “:”, 1, 19]
[“space”, ” “]
[“word”, “#FFF” , 1, 21, 1, 23]
[“;”, “;”, 1, 24]
[“space”, ” “]
[“}”, “}”, 1, 26]
]
以 word 类型为例,参数如下:
const token = [
// token 的类型,如 word、space、comment
‘word’,
// 匹配到的词名称
‘.className’,
// 代表该词开始位置的 row 以及 column,但像 type 为 `space` 的属性没有该值
1, 1,
// 代表该词结束位置的 row 以及 column,
1, 10
]
Parser
经过 Tokenizer 之后,需要 Parser 将结果初始化为 AST
this.root = {
type: ‘root’,
source: {input: {css: “.className { color: #FFF;}”, hasBOM: false, id: “<input css 1>”},
start: {line: 1, column: 1} ,
end: {line: 1, column: 27}
},
raws:{after: “”, semicolon: false}
nodes // 子元素
}
Processor
经过 AST 之后,PostCSS 提供了大量 JS API 给插件用
Stringifier
插件处理后,比如加浏览器前缀,会被重新 Stringifier.stringify 为一般 CSS。
结语
PostCSS 更多的是提供平台能力,赋能 js 的处理。