webpack做爲前端最火的構建工具,是前端自動化工具鏈最重要的部分,使用門檻較高。本系列是筆者本身的學習記錄,比較基礎,但願經過問題 + 解決方式的模式,之前端構建中遇到的具體需求爲出發點,學習webpack工具中相應的處理辦法。(本篇中的參數配置及使用方式均基於webpack4.0版本)css
假設項目中的CSS文件均採用預編譯語言編寫,那麼在打包中須要處理的基本問題包括:html
舊的解決方案:預編譯語言 + 命名方法論前端
在不使用構建工具的時代,開發者使用預編譯語言來實現變量定義,選擇器嵌套等一些剛需,再使用函數功能來實現一些更爲複雜的需求,例如編寫簡單的@mixin px2rem( )函數來將開發中使用的px單位轉換爲rem單位,達到移動端自適應的目的,或是編寫一些處理兼容性的函數來處理瀏覽器兼容性。node
命名的方法論很是多,最爲流行的當屬BEM,也就是採用block__Element-Modifier這樣的命名方式來進行模塊劃分,還有提倡碎片化樣式的Aotm-CSS及面向對象的OOCSS等,都是一種命名方法論,也意味着沒有硬性的檢測和預防措施。webpack
新的解決方案:預編譯語言 + 構建工具 + BEM + ACSS全局樣式+CSSModule組件樣式+ POSTCSSweb
預編譯語言的使用基本不變,但現代化開發中已經再也不須要經過預約義函數來解決單位轉換或是兼容性的問題。首先,構建工具能夠經過自動化檢測將預編譯語言轉換爲CSS,基於現代化構建工具的CSS-Module功能,能夠經過特定的語法解決CSS模塊化的問題,而基於POSTCSS實現的autoprefixer插件,能夠依據CanIUse網站提供的瀏覽器支持度數據實現代碼的跨瀏覽器前綴自動補齊。json
新的方案涉及到不少新的概念,但這並非簡單的炫技,每個概念都有優勢和適用的場合,你須要在恰當的場合使用恰當的技術,最愚蠢的作法就是由於某種技術熱門而盲目地要求開發人員在整個項目中使用。瀏覽器
以webpack4.0版本爲例來演示CSS模塊的處理方式,須要用到的插件及功能以下:sass
本篇不是webpack教程,在此直接給出帶有註釋的webpack.config.js的配置以供參考,示例中使用SCSS做爲預編譯語言,其餘預處理語言配置方式基本一致:前端構建
const HtmlWebpackPlugin = require('html-webpack-plugin');//用於自動生成html入口文件的插件 const MiniCssExtractPlugin = require("mini-css-extract-plugin");//將CSS代碼提取爲獨立文件的插件 const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");//CSS模塊資源優化插件 module.exports = { mode:'development', entry:'./main.js', output:{ filename:'main.bundle.js', path:__dirname + '/build' }, module: { rules: [ { test: /\.scss$/, exclude: /node_modules/, //排除node_modules文件夾 use: [{ loader: MiniCssExtractPlugin.loader//建議生產環境採用此方式解耦CSS文件與js文件 },{ loader: 'css-loader',//CSS加載器 options: {importLoaders: 2}//指定css-loader處理前最多能夠通過的loader個數 },{ loader: 'postcss-loader',//承載autoprefixer功能 },{ loader: 'sass-loader'//SCSS加載器,webpack默認使用node-sass進行編譯 } ] } ] }, plugins:[ new HtmlWebpackPlugin(),//生成入口html文件 new MiniCssExtractPlugin({ filename: "[name].css" })//爲抽取出的獨立的CSS文件設置配置參數 ], optimization:{ //對生成的CSS文件進行代碼壓縮 mode='production'時生效 minimizer:[ new OptimizeCssAssetsPlugin() ] } }
postcss.config.js的配置較爲簡單:
module.exports = { plugins:[ require('autoprefixer') ] }
package.json中增長新的參數指定打包須要支持的瀏覽器類別:
"browerslist": [ "last 2 versions", "IE 8", "UCAndroid" ]
編寫一段待SCSS代碼:
//變量定義 $grey: #1e1e1d; $yellow: #ffad15; $offwhite: #f8f8f8; $darkerwhite: darken($offwhite, 15);//SCSS函數 $baseFontSize:14px; //循環 @for $i from 1 through 3 { .item-#{$i} { width: 2em * $i; } } //mixin @mixin px2rem($name, $px){ #{$name}: $px / $baseFontSize * 1rem; } //嵌套 .class3{ font-weight: bold; display:flex; &-small{ color: $offwhite; @include px2rem('font-size',14px); } } //autoprefixer ::placeholder{ width:10px; }
能夠看到轉換後的結果:
提示:代碼壓縮等優化功能在4.0版本中默認當mode : 'production'時有效。
項目地址:CSS Modules開源地址
CSS Module在CSS中使用類選擇器,其基本原理是將CSS代碼中的樣式名替換爲哈希值,並創建一個json對照表,在js文件中對於屬性名選擇器的使用均被替換爲哈希字符串,以此來解決CSS模塊化的問題。
在webpack中使用CSS Modules功能很是簡單,只須要在css-loader的配置參數中設置:{modules:true}便可激活模塊化功能。
開啓模塊化功能後再進行打包,能夠看到一樣的main.css文件變成了以下樣子:
而在打包文件中增長了以下片斷:
固然CSS Modules的用法遠不止如此,更多的信息能夠參見上面的項目地址。
從上述配置中能夠看出,使用預編譯器編寫的樣式文件須要通過一系列loader和plugin才能獲得最終的目標文件,它之因此很抽象是由於中間的處理環節對開發者來講是黑箱操做,只看獲得輸入和輸出,筆者結合本身理解繪製了下面的示意圖,但願可以幫助你理解css文件在整個webpack打包流程中是如何被處理的(plugins部分還沒有進行研究,處理鏈中暫不涉及)。