[心得] 什麼是 postcss?

Posted by Huli on 2015-04-30

今天早上在facebook的前端開發社團看到了這則twitter

Oh, btw—Bootstrap 4 will be in SCSS. And if you care, v5 will likely be in PostCSS because holy crap that sounds cool

postcss?那是什麼東西?
好奇心的驅使下,開始拜google大神,開始研讀一些我找到的滿有用的資料
以下是一些我的心得跟理解,如果有錯誤的話還麻煩各位大大幫我指出<(_ _)>

#先來談談 preprocessor 吧
在以前寫純css的時候,常常會碰到許多問題,像是變數
假如我寫了一份css是

1
2
3
4
5
6
7
8
9
h1{
color:red;
}
.title{
color:red;
}
.special{
color:red;
}

若是有一天,我想要把顏色改成用藍色怎麼辦?
尋找->red->取代->blue
那如果我title這個class想要維持原有的顏色怎麼辦?手動改回來
於是你的時間就在這樣尋找、取代等等的事情上消耗掉了

這就像是你在寫程式或寫網頁的時候
你不會把每個頁面的footer都寫死在裡面,而是會用類似include footer.php的方式
這樣才能確保你想改footer的時候,只要改一個地方就好
但偏偏css就沒有這種功能,那怎麼辦呢?

於是scss/sass/less就出現了
他們都是css的預處理器(pre-processor)
先直接來看範例

1
2
3
4
5
6
7
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
}

這就是變數的功能,以後想要修改資料直接改變數內容就好,不用在每一個地方都改了
所以像scss這些預處理器,你要學一些新的語法,學一些新的表示方式
你就可以用這些新的語法寫好一些看起來很像css但不是css的東西,然後把它compiler成css

#再來看看 postprocessor
了解什麼是pre-processor以後,來看看什麼是post-processor
看範例最快了
直接來看這個 CSS Prefixer
在寫css的時候,會針對瀏覽器加上一些prefix,但是每次都這樣寫實在是很麻煩
官方範例,原本的css長這樣

1
2
3
4
5
.my-class, #my-id {
border-radius: 1em;
transition: all 1s ease;
box-shadow: #123456 0 0 10px;
}

處理過後的css長這樣

1
2
3
4
5
6
7
8
9
10
11
12
.my-class, #my-id {
-moz-border-radius: 1em;
-webkit-border-radius: 1em;
border-radius: 1em;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
-webkit-transition: all 1s ease;
transition: all 1s ease;
-moz-box-shadow: #123456 0 0 10px;
-webkit-box-shadow: #123456 0 0 10px;
box-shadow: #123456 0 0 10px
}

將將將將~全部都幫你加好了
這就是後處理器(post-processor)

簡單來說,預處理器是你把一些長得很像css但不是css的東西丟給它,處理過後會給你編譯過後的css
而css再經過後處理器,透過一些規則幫它加上一些東西,最後產生出完成品!

$a = red;
h1{ color:$a } -> preprocessor -> h1{color:red;} -> postprocessor -> h1{webkit-color:red;}
這邊的webkit-color純粹是亂舉例,但差不多就是這樣的意思

##但是你舉的例子,preprocessor也可以做到啊

1
2
3
4
5
6
7
8
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
-ms-border-radius: $radius;
border-radius: $radius;
}
.box { @include border-radius(10px); }

沒錯,在scss裡面,用mixin也可以達成加上前綴這樣的目的

##那為什麼要用postprocessor?

後處理器有幾個優點:
1.你可以寫自己的plugin
如果你選了SCSS,你就必須接受SCSS的一切,接受他的語法,要用就要用一整套SCSS,你不能只選擇你要的某些功能
但是如果你用了postcss,你可以選擇你自己想要的功能
舉例來說,加上prefix就是一個功能,或是讓你可以用變數也是一個功能,你可以自己選擇你想要的功能加入,而不是一用就要用一整套完整的方案,當然,你也可以用javascript寫自己的plugin,解析css語法並且加入一些自己想要的東西

2.用標準的css語法
前面有提過預處理器跟後處理器的差別,一個是寫好SCSS(或其他的)丟進去,一個是把CSS加上一些東西之類丟出來
有些人相信將來的某一天,所有瀏覽器都會支援標準的css,例如說你不必再加上webkit-之類的prefix
到了那一天,如果你是用postcss,你可以不做任何動作,直接拿原有的css就好,但如果你用的是scss就沒有辦法這樣
像是 http://www.myth.io/ 這套,就提倡用「未來的css標準」寫css,在現代先用後處理器的方式去產生可以跑的css,但是在未來的某一天,把那些plugin拔掉以後,你的css還是可以正常地跑出結果。

最後,回到原來的主題:什麼是postcss?

PostCSS is a tool for transforming CSS with JS plugins. These plugins can support variables and mixins, transpile future CSS syntax, inline images, and more.

就是一套很方便的工具,你可以自己寫plugin整合進去,或是挑選你要的plugin
然後把原來的css處理過後,讓它變成你想要的樣子。
總之就是後處理器的集大成者就是了

還有一點要特別說明的是,預處理器跟後處理器這兩種概念不是互斥的,他們是可以互相融合的
你可以先用scss寫一段code,編譯成css,再用postcss加上一些你想要的東西,最後產生出完成品
有興趣深入研究的可以參考下面的連結

最後有一點想特別提,最早提出這個概念的人似乎是 TJ Holowaychuk
他實在是太猛了…

參考資料:
What Will Save Us from the Dark Side of CSS Pre-Processors?
myth.io
PostCSS: the Future after Sass and Less
Modular CSS preprocessing with rework
Compare PostCSS with other Frontend tool
Postprocessors CSS An efficient workflow CSS
pleeease.io
postcss–预处理器与后处理器
I’m Excited About PostCSS But I’m Scared to Leave Sass
Breaking up with Sass: it’s not you, it’s me