日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
解剖postCSS-向前端架構(gòu)師邁出一小步

 最近很火的TailwindCSS有一個功能:

可以將項目未使用的css選擇器從編譯后css文件中移除。

這個功能是PurgeCSS實現(xiàn)的。

鏈接TailwindCSS與PurgeCSS的,則是一個postCSS插件@fullhuman/postcss-purgecss。

不僅TailwindCSS,還有很多知名項目中使用了postCSS插件。比如:

很多人在項目中使用autoprefixer插件,為css選擇器增加不同的「瀏覽器前綴」。

在其內(nèi)部會根據(jù)browserslist[1]指定瀏覽器版本。

再去caniuse[2]查找該瀏覽器版本兼容性支持情況。

最后通過postCSS的能力改寫不支持的css屬性。

可以看到,postCSS正越來越成為前端項目必不可少的依賴。

同時也有很多關(guān)于postCSS的誤區(qū),比如認(rèn)為他是和Less、Sass一樣的「css預(yù)處理器」。

本文會自底向上介紹postCSS,希望通過此文讓你對這款大殺器有更深的認(rèn)識。

什么是postCSS

postCSS是一款css編譯器。

類比Babel家族的@babel/parser可以將js代碼解析為AST(抽象語法樹),再利用眾多插件(@babel/plugin-xx)的能力改寫AST,最終輸出改寫后的js代碼。

postCSS利用自身的parser可以將css代碼解析為AST,再利用眾多插件(上文介紹的autoprefixer就是一種)改寫AST,最終輸出改寫后的css代碼。

從這點就能看出其與Less這樣的「css預(yù)處理器」的不同 —— postCSS的輸入與輸出產(chǎn)物都是css文件。

因此,postCSS也被成為「后處理器」,因為其通常在css處理鏈條的最后端。

postCSS的AST

你可以在astexplorer[3]中選擇:

  • 語言:css
  • parser:postCSS

來了解postCSS如何解析css。

比如,對于如下css代碼:

 
 
 
 
  1. /** 
  2.  * I am KaSong 
  3.  */ 
  4.  
  5. @media screen and (min-width: 900px) { 
  6.   article { 
  7.     padding: 1rem 3rem; 
  8.   } 
  9.  
  10.  
  11. ul { 
  12.  margin: 3rem; 
  13.  
  14. ul li { 
  15.  padding: 5px; 

會被postCSS解析為如下樹結(jié)構(gòu)的AST:

節(jié)點有如下幾種類型:

  • Root:根節(jié)點,代表一個css文件
  • AtRule:以@開頭的申明,比如@charset "UTF-8"或@media (screen) {}
  • Rule:內(nèi)部包含定義的選擇器,比如input, button {}
  • Declaration:key-value鍵值對,比如color: black;
  • Comment:單獨的注釋。selectors、at-rule的參數(shù)以及value的注釋在節(jié)點的node屬性內(nèi)

實現(xiàn)一個簡單的插件

接下來我們從一個插件的實現(xiàn)來了解開發(fā)者如何介入postCSS編譯流程。

postcss-focus[4]會為所有:hover選擇器增加:focus以提高鍵盤操作的可用性。

對于如下代碼:

 
 
 
 
  1. .a:hover, .b:hover, .c:hover { 
  2.   opacity: .5; 

經(jīng)過該插件處理后會輸出:

 
 
 
 
  1. .a:hover, .b:hover, .c:hover, .a:focus, .b:focus, .c:focus { 
  2.   opacity: .5; 

你可以安裝postcss、postcss-focus后通過如下demo在控制臺看到結(jié)果:

 
 
 
 
  1. const postcssFocus = require('postcss-focus'); 
  2. const postcss = require('postcss'); 
  3. const fs = require('fs'); 
  4.  
  5. // 輸入的css文件地址 
  6. const from = 'src/a.css'; 
  7. const to = 'output/a.css'; 
  8.  
  9. fs.readFile(from, (err, css) => { 
  10.   postcss(postcssFocus).process(css, { from, to }).then(result => { 
  11.     console.log(result.css) 
  12.   }) 
  13.    
  14. }) 

接下來我們分析postcss-focus源碼[5]的實現(xiàn)邏輯:

  1. postCSS將輸入的css解析為AST
  2. 遍歷AST中所有Rule類型節(jié)點
  3. 維護(hù)一個數(shù)組,遍歷這個節(jié)點的所有selector,每遍歷到一個包含:hover的selector就往數(shù)組中push一個:focus的selector
  4. 將2中得到的數(shù)組concat到該節(jié)點已有的selectors后
  5. 根據(jù)改變后的AST輸出新的css

核心源碼如下:

 
 
 
 
  1.   postcssPlugin: 'postcss-focus', 
  2.   // 步驟1 
  3.   Rule: rule => { 
  4.     // 步驟2 
  5.     if (rule.selector.includes(':hover')) { 
  6.       let focuses = [] 
  7.       for (let selector of rule.selectors) { 
  8.         if (selector.includes(':hover')) { 
  9.           let replaced = selector.replace(/:hover/g, ':focus') 
  10.           if (!hasAlready(rule.parent, replaced)) { 
  11.             focuses.push(replaced) 
  12.           } 
  13.         } 
  14.       } 
  15.       // 步驟3 
  16.       if (focuses.length) { 
  17.         rule.selectors = rule.selectors.concat(focuses) 
  18.       } 
  19.     } 
  20.   } 

這個插件只是為了演示插件的基本工作方法,實際上該插件實現(xiàn)的比較粗糙。

postCSS提供了詳細(xì)的插件創(chuàng)建文檔[6]。甚至提供了create-postcss-plugin[7]用來創(chuàng)建插件的模版代碼。

更多可能性

由于提供了表達(dá)、改寫css AST的能力,postCSS的插件可以實現(xiàn)非常多功能。比如:

postcss-functions

上文介紹了Declaration節(jié)點表達(dá)「css屬性」的鍵值對,其中值為「字符串」類型。

那么完全可以自定義值的解析規(guī)則。

 
 
 
 
  1. body { 
  2.   color: getColor(); 

通過定義getColor函數(shù),并在AST中將其解析為函數(shù)執(zhí)行,就能在css文件中用js寫邏輯代碼。

這就是postcss-functions[8]

stylelint

配置不同的lint規(guī)則,實現(xiàn)css的靜態(tài)語法檢測。這就是stylelint[9]

總結(jié)

當(dāng)前postCSS插件按功能劃分大體有如下幾類:

  • 解決全局css問題,比如提供css module[10]支持
  • 使用未全面兼容的css特性,比如autoprefixer[11]
  • 格式化,提高css可讀性
  • 圖片和文字處理
  • linters,比如stylelint
  • 不同語法的css支持,比如postcss-html[12]可以解析類html文件中 

讀到這里,相信你會同意:相比Less、Sass,postCSS才是css處理領(lǐng)域的大殺器。

參考資料

[1]browserslist:

https://github.com/browserslist/browserslist[2]caniuse:

https://caniuse.com/#search=[3]astexplorer:

https://astexplorer.net/[4]postcss-focus:

https://www.npmjs.com/package/postcss-focus[5]postcss-focus源碼:

https://github.com/postcss/postcss-focus/blob/master/index.js[6]插件創(chuàng)建文檔:

https://github.com/postcss/postcss/blob/main/docs/writing-a-plugin.md[7]create-postcss-plugin:

https://github.com/csstools/create-postcss-plugin[8]postcss-functions:

https://www.npmjs.com/package/postcss-functions[9]stylelint:

https://github.com/stylelint/stylelint[10]css module:

https://github.com/madyankin/postcss-modules[11]autoprefixer:

https://github.com/postcss/autoprefixer[12]postcss-html:

https://github.com/gucong3000/postcss-html


當(dāng)前標(biāo)題:解剖postCSS-向前端架構(gòu)師邁出一小步
路徑分享:http://www.dlmjj.cn/article/dhpioei.html