PostCSS架構大致如下圖:
通過PostCSS將CSS轉換成AST(抽象語法樹),對應的是JavaScript對象;然後通過插件遍歷AST,進行增加,刪除,修改;最後再生成CSS文件,這就是整個流程,跟babel的架構非常相似。
其中的CSS解析成AST及AST序列化生成CSS,PostCSS都幫我們做好了,我們只需要關注在插件開發,及如何操作AST。
所以下面我們用一個簡單的例子來說明如何開發PostCSS的插件。有這麼一個樣式:
.content{
color: red;
}
如果我們檢測到某個樣式中有"color: red"這樣一條樣式規則,需要自動增加"background-color: red"這樣一條規則。
PostCSS官方提供插件編寫的模板,只需要將其下載下來:
git clone [email protected]:postcss/postcss-plugin-boilerplate.git
然後進入該文件夾的目錄下,輸入命令:
node start
這個時候會需要你輸入一些信息,然後就會自動生成一個插件的模板文件夾,還是進入到這個對應的文件夾下,這個時候就能看到熟悉的package.json,index.js等文件,使用npm安裝了依賴之後就可以在index.js文件中編寫插件的邏輯了。同樣的,我們可以在項目中通過npm安裝任意依賴,然後在index.js中通過require引入,這就是背靠JavaScript的優勢。
index.js默認的內容是這樣的:
var postcss = require('postcss');
module.exports = postcss.plugin('postcss-practice', function (opts) {
opts = opts || {};
// Work with options here
return function (root, result) {
// Transform CSS AST here
};
});
編寫出來的插件代碼是這樣的:
const postcss = require('postcss');
const postcss = require('postcss');
module.exports = postcss.plugin('postcss-practice', function (opts) {
opts = opts || {};
console.log(opts);
// Work with options here
return function (root) {
root.walkRules(rule => {
console.log(rule.selector);
rule.walkDecls(decl => {
if (
decl.prop === 'color' &&
decl.value === 'red'
) {
rule.append({
prop: 'background-color',
value: 'red'
});
}
});
});
};
});
非常簡單,解釋一下:root.walkRules會遍歷每一個CSS規則,可以通過rule.selector拿到每一組規則中的選擇器,然後通過rule.walkDecls遍歷每一組規則中的樣式聲明, 通過decl.prop,decl.value拿到樣式聲明中的屬性和值。上面判斷屬性是否為'background-color'、值是否為'red',如果滿足條件則向規則中插入一條新的樣式聲明(這裡為了簡單,沒有考慮是否已經存在background-color聲明)。
插件編寫完了,樣板項目中還包含index.test.js來測試是否插件是否合理,下面是編寫的index.test.js中的測試代碼:
var postcss = require('postcss');
var plugin = require('./index.js');
function run(input, output, opts) {
return postcss([ plugin(opts) ]).process(input)
.then(result => {
expect(result.css).toEqual(output);
expect(result.warnings().length).toBe(0);
});
}
// Write tests here
it('does something', () => {
return run('a{color: red;}',
'a{color: red;background-color: red;}', {});
});
然後是運行: "npm run test"的結果:
接下來就可以打包發佈,然後在項目中安裝使用了,就像其他插件那樣。PostCSS還提供了許多有用的函數,幫助你操作AST,輕鬆完成開發。
閱讀更多 前端小學生 的文章