關於程式碼靜態質量檢查,在大佛的上一篇文章 《JavaScript 程式碼靜態質量檢查》中已經說得很明白了,雖然主要講的是 JavaScript 方面,但程式碼靜態質量檢查的本質是不變的,今天我們來介紹一下 CSS 方面的靜態質量檢查。
CSS 中也有一些 Lint 工具,例如 CSSLint,PrettyCSS,recess,CKStyle,stylelint,當然還有百度 EFE 出品的 CSS 程式碼風格檢查工具 CSSHint。本文將從功能、效能、適用範圍、規則實現、個性化幾個方面對這幾個 Lint 工具進行對比。
CSSLint
CSSLint
和它底層所使用的解析器 parserlib
都是 Nicholas C. Zakas 的作品(當然,ESLint
也是他的作品)。它適用於瀏覽器以及 CLI 環境,在瀏覽器端和 CLI 環境中分別是兩套程式碼,這麼做的原因是它的底層庫 parserlib
在瀏覽器和 CLI 環境分別是兩套。
功能上,CSSLint
提供了對 CSS 的解析、檢查等功能。在規則實現方面,無法通過 JSON 配置來管理,預設的規則全部在src/rules/
目錄中,要新增自定義規則,必須通過全域性的 CSSLint.addRule 方法來實現。
實現上,CSSLint
主要是利用事件監聽,在底層 parse CSS 過程中觸發事件,例如startstylesheet、endstylesheet、charset、import、namespace、startmedia、endmedia、startpage、endpage、startrul 和endrule 等,事件回撥中會返回當前 AST 的資訊,開發者根據這些資訊來進行規則檢測。
效能上,如果不新增自定義的規則,效能還是不錯的,但是一旦新增自定義規則,效能就會打些折扣。這是底層解析器 parserlib
的原因,parserlib
功能比較單一,而且返回的 AST 上資訊不是很豐富,也不支援外掛機制,因此要實現一些自定義的規則,基本只能靠正則匹配來實現。
CSSLint
開發時間比較早,同時也因為大神的影響力,因此現在周邊配套非常豐富,支援各種編輯器例如:Textmate
, Sublime Text
, Atom
, Vim
, Emacs
等等。
PrettyCSS
PrettyCSS
是一個比較出色的 Lint 工具,但它並不算是一個純粹的 Linter,更應該把它稱作一個 Parser,這也是它出色的原因。在 Parser 裡面實現的 Linter 以及 Pretty,這樣可以最大程度的保證 Linter 的精確度。它適用於瀏覽器端、作為 Node.js 模組以及 CLI 工具。
實現上來說,在 Parser 中整合 Linter 即在 Parse 階段就把 Linter 的規則給檢測了,因此效能較好。當然缺點也比較明顯,就是無法自定義規則。
如果 PrettyCSS
未來能夠提供外掛機制,允許自定義規則,會更有吸引力。
recess
Twitter 出品的 CSS 程式碼質量檢查工具,可以作為 Node.js 模組和 CLI 工具來使用,不知道是什麼原因,master 分支已經兩年沒有維護了,v2.0.0 分支也有將近半年沒有更新了。
比較有特點的是,recess
沒有用任何 CSS 解析器,而是直接用 Less 解析器來做的,因此也就預設了一個編譯 Less 的功能,但其他方面的功能就比較弱了,可能是時間比較早的原因吧。所有預設規則都在 lib/lint/ 目錄下,沒有外掛機制,無法擴充套件。
實現上,結合 Less parse 出來的 AST 進行規則分析檢查,效能上表現一般,因為 Less parse 後還會有 toCSS 這麼一步,本質上就會比純 CSS 解析器要多一個步驟。在規則的實現程度上也比較一般,只實現了八個規則,這可能也是因為底層是 Less 解析器的原因。
就目前來看,v2.0.0 相對於 master 來說並沒有改動太多,整體結構沒有變化,底層還是使用 Less 解析器,區別僅僅是增加了一個data-uri 的規則以及修改了一些 codestyle。
CKStyle
CKStyle
是國產的 CSS 程式碼檢查工具,定位是一脈相承的 CSS 檢查、美化、修復、壓縮工具
。適用範圍包括在瀏覽器端使用、作為 Node.js 模組以及 CLI 工具。這個工具最開始是 python 版本的,大約一年前改成 Node.js 版本了。這個版本和之前的 python 版本比較起來,增加了一些預設的規則實現以及提供了瀏覽器端的支援。
CKStyle
在功能上還是比較豐富的,它提供了對 CSS 的解析、檢查、fix 和壓縮。但是它同樣無法通過配置檔案來管理規則,預設的規則全部在 ckstyle/plugins/ 目錄中,要新增自定義規則,只能在全域性 global
上掛載一個 RuleChecker
的子類。
實現上,CKStyle
直接解析 CSS 檔案,然後結合返回的 AST 物件做一些規則的檢測。效能比較不錯,這是因為底層 CSS 解析器是自己根據預設的規則來定製的,很少有正則上的一些匹配。這就好像是坑是自己挖的,那麼自己總能想到一個簡單快速的方法把坑填滿一樣。
CKStyle
整體規模上看起來比較大,但是不知道什麼原因,並沒有在社群流行。亮點是功能很豐富,檢查、美化、修復和壓縮全都有,甚至提供了一個服務 CKService
,幫助檢查網站的 CSS。
stylelint
stylelint
本質上和下面將要介紹的 CSSHint
是一樣的,都是基於 postcss
解析器實現的,除了規則實現的數量不一樣,最大的區別就是 stylelint
是用 ES6 寫的。所以這裡就不介紹了,直接看下面的 CSSHint
了。
CSSHint
CSSHint
是百度 EFE 出品的 CSS 程式碼風格檢查工具,在 2014 年底應公司內部全面推行程式碼規範檢查的需求而產生的。目前CSSHint
支援 Node.js 模組以及 CLI 方式使用,提供對 CSS 的解析和檢查等功能,通過 JSON 檔案來管理規則的配置。
在專案剛開始設計階段,我們曾考慮使用大神的 CSSLint
,但在經過調研後發現,CSSLint
在針對我們自己的規範做規則檢測的時候,發現一些問題:首先 CSSLint
預設實現的規則裡面並不能完全覆蓋我們自己的規範,其次,在單條規則上,對規則匹配度也不夠,最後,基於 CSSLint
來寫外掛不太方便。因此,我們決定基於 CSSLint
解析器 parserlib
重新實現一套 CSS 程式碼檢查工具。這就是 0.1.0 版本之前的 CSSHint
,經過一段時間的使用我們發現這個解析器返回的 AST 上資訊太少,而且針對解析器來寫外掛也不方便。因此在 0.1.0 版本的重構中,我們把底層解析器換成了 postcss
(postcss
和 parserlib
相比,最大的優點是優秀的外掛機制,而且 AST 上的資訊也更完整),同時改變了實現的方式,在效能和功能上較 0.1.0 之前版本有較大的提升。
得益於 postcss
優秀的外掛機制,CSSHint
提供了較為豐富的規則實現,每個規則實際上就是一個 postcss
的外掛,擴充套件新規則比較方便,只需註冊到 postcss.plugin 上即可。
在實現上,也是直接解析 CSS 檔案,然後在每個外掛裡面呼叫 node.eachRule 或者 rule.eachDecl 來實現對選擇器或者屬性的遍歷,回撥函式中返回的是 AST,然後根據這些資訊做規則的檢測。同時針對我們的需求,CSSHint
提供了行內註釋的方式來動態的配置規則。
CSSHint
目前還不支援瀏覽器端使用,相對於 CKStyle
的大而全,CSSHint
更加專注於 Lint 本身。覆蓋更多的規則(包括CSSLint的規則)、提供更易用擴充套件方式、提供更加靈活的行內註釋指令匹配方式(開啟、關閉、巢狀)等功能才是 CSSHint
的專注方向。
總結
CSSLint
中規中矩,各個方面比較均衡,如果你是大神Nicholas C. Zakas的粉絲,那麼 CSSLint
是你的必選項。
PrettyCSS
效能比較好,如果 PrettyCSS
預設實現的規則可以滿足你並且你不會有自定義規則的需求的話,那麼 PrettyCSS
就是你的不二之選。
recess
雖然師出名門,但是維護跟不上,在功能上已經不能滿足如今的需求了,只能當做程式碼學習來使用了。
CKStyle
功能豐富,但是精細程度不是太高,如果你要求不太高,對功能的豐富程度更加在意,那麼推薦使用 CKStyle
,而且是國人出品,中文文件,看起來也比較方便。
stylelint
本質上和 CSSHint
一樣,可以作為一個 ES6 的學習專案。
CSSHint
已經發布了 0.2.0
版本,在擴充套件性、規則的自定義上表現不錯,同時,除了滿足我們自己的規範,還覆蓋了 CSSLint
的規則。目前來看,CSSHint
是覆蓋規則最全的一個 CSS 程式碼風格檢查工具了,而且擴充套件起來也比較方便,另外,行內註釋指令的功能在其他 Lint 工具上也是沒有的,個人來看,未來的潛力比較大。