一場由postcss-bem引起的血案

緣起

樓主最近搭建了一套先後端開發環境用於開發本身的網站並嘗試一些有趣的前端技術,在整個環境運行正常以後,樓主某天心血來潮想將以前的less文件用pcss代替,使用bem的方式去編寫css,而後用postcss-bem插件去處理樣式規則的轉換。在一切配置準備就緒後,正當我興致勃勃的運行webpack編譯打包時,使人驚奇的事情發生了
源代碼: javascript


postcss處理後結果:

很明顯的是在component聲明中的樣式規則能夠正常輸出,可是在子聲明中的規則就被幹掉了,儘管class能夠正常解析。
這強烈的刺激到了樓主的好奇之心,因而我便開始扒這個插件的源碼,終於發現了問題所在

postcss-bem插件在處理modifier和descendent類型聲明的過程當中將當前規則的子節點移植到newRule時用的是moveTo方法,因爲我以前升級了webpack4,併爲了適配webpack4將其餘的loader等也升級到了最新版,而在最新版的postcss中,由css源字符串解析成的抽象語法樹已經廢棄了該方法,致使當前規則的子節點不能移植到新建的規則newRule中,從而使子聲明中的樣式規則丟失。
明白了這一點以後我準備給該項目的開發者提issue,卻發現npm網站中該項目連接到的Github地址404了,對,你沒看錯,就是404了

此刻的心裏:開發者你出來,我保證不打死你

拓展

基於上述緣由,我決定本身開發一個postcss-bem插件,能夠幫助到那些和我遇到相同問題的開發者,順便也幫助你們瞭解怎樣去開發一個postcss插件。css

@mozheng-neal/postcss-bem

由於舊項目的代碼無人維護並且有可能會有其餘坑,因此我選擇了從新造輪子,這就是@mozheng-neal/postcss-bem,與此同時經過緩存父級元素選擇器的方式,它在元素選擇器的生成上擁有更快的速度。你們能夠在github上看到該項目的源代碼和使用方式(您的star是對我最大的鼓勵)。
html

接下來我會用一個簡單的示例向你們介紹如何寫一個postcss插件,以便你們之後在開發過程當中能夠利用本身的奇思妙想創造更多有趣的東西。

如何寫一個postcss插件

假設咱們要實現這樣一個功能:在css的每一個樣式聲明中添加一個color屬性,值爲#666,若是當前聲明中已經存在color屬性但值不爲#666,那麼就將其設置爲#666。
首先咱們來看下一個postcss插件的基本結構前端

const postcss = require('postcss')
postcss.plugin(pluginName, function (opts) {
  return function (root, result) {
    // root is the root node object
    // this is where your plugin process logic should be placed
  }  
})
複製代碼

postcss會將獲取到的css源碼字符串轉換爲js表示的抽象語法樹,上述的root就表示該語法樹的根節點。要實現咱們以前想要的功能,在插件邏輯中咱們須要藉助一些postcss爲節點對象提供的API。java

return function (root, result) {
  root.walkRules(function (rule) {
    // rule爲樣式文件中的聲明塊
    let hasColorProp = false
    rule.walkDecls(function (decl) {
      /* * decl表示聲明塊中的每條css屬性節點 * 好比color:#fff會被解析成decl.prop === color,decl.value === #fff */
      if (decl.prop === 'color') {
        hasColorProp = true
        if (decl.value !== '#666') {
          decl.value = '#666'
        }
      }
    })
    if (!hasColorProp) {
      rule.append({prop: 'color', value: '#666'})
    }
  })
}
複製代碼

經過如此簡單的一個插件就能完成以往咱們須要付出不少手力勞動才能作到的事是否是開心到爆炸
node

在這個過程當中咱們改動的只是抽象語法樹結構,在插件處理完成後postcss會利用轉換後的抽象語法樹生成新的css源碼字符串。而這還只是咱們對於postcssAPI的簡單應用,postcss爲節點對象提供了更加豐富的能力,若是想了解更多,你能夠參考 postcssAPI詳情

結語

postcss是一個很是便利的css開發工具,使用得當也能夠極大提高你的開發效率,並且postcss插件的編寫也並不複雜,它絕對是你在前端開發的學習過程當中值得去掌握的一個技能。最後再囉嗦一句,歡迎你們使用個人postcss-bem插件,有任何問題歡迎提issue, 我會一直維護這個項目的。webpack

插播一條廣告

蘑菇街前端開發團隊持續招聘高級/資深前端開發工程師,歡迎各位大佬砸簡歷給我哦,郵箱m13710224694@163.comgit

相關文章
相關標籤/搜索