原文連接javascript
CSS全稱Cascading Style Sheets(層疊樣式表),用來爲HTML添加樣式,本質上是一種標記類語言。CSS前期發展很是迅速,1994年哈肯·維姆·萊首次提出CSS,1996年12月W3C推出了第一個正式版本。隨後不到兩年的時間,1998年5月便推出了第二個版本,一直沿用至今。可是CSS3的制訂工做卻遲遲沒有完成。CSS3最初的草案在1999年便被提出,可是直到今日CSS3規範仍然有部分特性沒有完成。若是說ES6與ES5相隔的6年時間讓開發者們熬盡了心肝,那麼從提案到發佈相隔近20年光陰的CSS3能夠說是千呼萬喚始出來,並且猶抱琵琶半遮面。css
CSS的初衷是爲了彌補HTML原生樣式的不足,早期對樣式要求並不複雜的web網站僅僅須要少許的CSS代碼便可。在現在web應用程序追求極致用戶體驗的潮流下,對CSS的要求也不斷加強。複雜CSS開發是一件很是痛苦的事情,最主要的緣由是受限於瀏覽器的實現以及CSS自身的弱編程能力:html
cal()
以及處於草案階段的var()
能夠隱約看出W3C有意增強CSS的編程能力;開發者們不斷探索着可以彌補這些缺陷的解決方案,CSS預編譯器是第一種順勢而生的革命性方案。前端
CSS預編譯的工做原理是提供便捷的語法和特性供開發者編寫源代碼,隨後通過專門的編譯工具將源碼轉化爲CSS語法。最先的CSS預編譯器是2007年起源於Ruby on Rails社區的SASS,目前比較流行的其餘CSS預編譯器如Less、Stylus的誕生都必定程度上受到了SASS的影響和啓發。java
CSS預編譯器幾乎成爲現現在開發CSS的標配,它從如下幾個方面提高了CSS開發的效率:webpack
不一樣的預編譯器特性雖然有所差別,但核心功能均圍繞這些目標打造,好比:web
嵌套是全部預編譯器都支持的語法特性,也是原生CSS最讓開發者頭疼的問題之一;mixin/繼承是爲了解決hack和代碼複用;變量和運算加強了源碼的可編程能力;模塊化的支持不只更利於代碼複用,同時也提升了源碼的可維護性。編程
CSS預編譯的理念與Babel有必定相通之處,最重要的區別是:預編譯語法並不是規範的CSS,而是各成一派。由預編譯語法編寫的源代碼不能在任何宿主瀏覽器中運行。從這個角度考慮,CSS預編譯更像CoffeeScript、TypeScript等JavaScript子集。能夠預見的是,若是將來CSS規範推出了預編譯相似的特性和語法,這些預編譯器都將成爲歷史的塵埃。PostCSS則反其道而行之,從理念上更加接近Babel,業內也有人將其稱爲「CSS的Babel」。瀏覽器
PostCSS鼓勵開發者使用規範的CSS原生語法編寫源代碼,而後配置編譯器須要兼容的瀏覽器版本,最後通過編譯將源碼轉化爲目標瀏覽器可用的CSS代碼。PostCSS提供了豐富的插件用於實現不一樣場景的編譯需求,最經常使用的好比autoprefixer、sprites等,編譯流程以下圖所示:
前端工程師
PostCSS並非另外一種CSS預編譯器,與SASS、Less等預編譯器也並不衝突。PostCSS與Babel的不一樣之處在於,它所支持的所謂「將來CSS語法」並非嚴格的CSS規範,其中大部分語法和特性目前只是CSS4的草案而已。不少人將PostCSS稱爲「CSS後編譯器」,這個稱謂能夠必定程度上說明目前業界對PostCSS的廣泛使用方案,請看下圖:
即便是PostCSS支持的「將來CSS語法」也並不能徹底彌補CSS的缺陷,因此目前廣泛的方案是將CSS預編譯與PostCSS綜合在一塊兒:
經過Webpack配置項中的use
指定的loader是按照索引反向執行,好比存在下述配置方案:
{ test: /\.less$/, use: [ 'style-loader', 'css-loader', 'less-loader' ] }
.less
後綴類型的文件依次通過less-loader
、css-loader
和style-loader
編譯。在這種工做模式的基礎上,結合圖3-4所示的編譯流程,使用Webpack結合CSS預編譯與PostCSS的編譯方案便一目瞭然了:
{ test: /\.less$/, use: [{ loader: 'style-loader', options: {} // style-loader options },{ loader: 'css-loader', options: { importLoaders: 2 // css-loader options } },{ loader: 'postcss-loader', options: {} // postcss-loader options },{ loader: 'less-loader', options: {} // less-loader options }] }
上述配置中有如下須要注意的細節:
importLoaders
選項的做用是用於配置css-loader做用於 @import
的資源以前須要通過其餘loader的個數。@import
用於css源碼中引用其餘模塊的關鍵字,若是你的項目中肯定不會涉及模塊化能夠忽略此配置項;{ test: /\.less$/, use: ExtractTextPlugin.extract({ filename: './dest/[name].[contenthash].css' use: [{ loader: 'css-loader', options: { importLoaders: 2 // css-loader options } },{ loader: 'postcss-loader', options: {} // postcss-loader options },{ loader: 'less-loader', options: {} // less-loader options }], publicPath: '/' }) }
注:不少開發者容易混淆css-loader和style-loader的做用。css-loader的做用是解析css源文件並獲取其引用的資源,好比
@import
引用的模塊、url()
引用的圖片等,而後根據Webpack配置編譯這些資源。style-loader負責將css代碼經過<style>
標籤插入html文檔中,因此若是獨立導出css文件就再也不須要style-loader。css-loader必須在style-loader以前執行。