自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解剖postCSS- 向前端架構師邁出一小步

開發(fā) 前端
最近很火的TailwindCSS有一個功能,可以將項目未使用的css選擇器從編譯后css文件中移除。

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

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


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

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

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

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

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

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

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

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

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

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

什么是postCSS

postCSS是一款css編譯器。

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

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


從這點就能看出其與Less這樣的「css預處理器」的不同 —— 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解析為如下樹結構的AST:


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

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

實現(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在控制臺看到結果:

  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, { fromto }).then(result => { 
  11.     console.log(result.css) 
  12.   }) 
  13.    
  14. }) 

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

  1. postCSS將輸入的css解析為AST
  2. 遍歷AST中所有Rule類型節(jié)點
  3. 維護一個數(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.   Rulerule => { 
  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提供了詳細的插件創(chuàng)建文檔[6]。甚至提供了create-postcss-plugin[7]用來創(chuàng)建插件的模版代碼。

更多可能性

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

postcss-functions

上文介紹了Declaration節(jié)點表達「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]

總結

當前postCSS插件按功能劃分大體有如下幾類:

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

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

參考資料

[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

 

責任編輯:姜華 來源: 魔術師卡頌
相關推薦

2021-02-25 16:58:38

Babel前端JavaScript

2013-10-09 09:32:58

2024-10-24 23:40:34

2016-11-07 13:31:24

2017-09-22 11:18:19

2009-12-17 17:40:45

架構師

2017-03-30 16:41:07

互聯(lián)網(wǎng)

2020-06-28 14:15:52

前端架構師互聯(lián)網(wǎng)

2018-03-15 13:14:59

思科網(wǎng)絡技術智慧系統(tǒng)

2018-02-10 11:24:39

Python數(shù)據(jù)程序

2020-07-22 22:10:34

互聯(lián)網(wǎng)物聯(lián)網(wǎng)IOT

2012-09-06 13:12:41

架構師ArchSummit

2021-05-14 05:26:25

前端架構開發(fā)

2012-06-17 12:58:04

架構師架構

2012-10-22 10:01:45

TD-LTETD-LTE頻譜TDD頻譜

2020-11-11 09:37:56

芯片

2022-01-04 10:19:23

架構運維技術

2020-08-24 08:50:12

架構師TL技術

2009-12-18 10:22:50

Ray Ozzie架構師

2013-04-27 13:36:52

Chrome
點贊
收藏

51CTO技術棧公眾號