預設配置
webpack 4 引入了零配置的概念,提供的預設配置來減少重複工作。
development 模式下,預設開啟了NamedChunksPlugin 和NamedModulesPlugin方便除錯,提供了更完整的錯誤資訊,更快的重新編譯的速度。
production 模式下,自動開啟splitChunks和minimizer,所以基本零配置,程式碼就會自動分割、壓縮、最佳化,同時 webpack 也會自動幫你 Scope Hoisting, Tree-shaking 。
注:v4.26後,minimizer等於true預設使用的外掛已由UglifyJsPlugin變為TerserPlugin。
主要預設配置:
詳細的mode預設配置,可以看這裡。
幾種hash
hash
hash 和每次 build有關,沒有任何改變的情況下,每次編譯出來的 hash都是一樣的,但當你改變了任何一點東西,它的hash就會發生改變。
chunkhash
chunkhash是根據具體每一個模組檔案自己的的內容包括它的依賴計算所得的hash,所以某個檔案的改動只會影響它本身的hash,不會影響其它檔案。
contenthash
當一個vue檔案打包成一個js時,使用MiniCssExtractPlugin會讓css樣式單獨提取為一個css檔案,這個提取出的css檔案,與vue編譯的js檔案,有相同的chunkid。而contenthash是根據css內容決定的,內容不變,contenthash不變,所以應該使contenthash作為部分檔名。
new MiniCssExtractPlugin({
filename: "static/css/[name]-css-[contenthash:5].css"
})
output:path 與 publicPath
path:指定輸出檔案的目標路徑
publicPath:用於在生產模式下更新內嵌到css、html檔案裡的url值。
舉個例子:
css中,這樣引用一個圖片
.image {
background-image: url('./test.png');
}
但在生產環境下,需要引用cdn中的圖片,這時透過定義publicPath來改變引用路徑。
module.exports = merge(baseConfig, {
mode: "production",
output: {
publicPath:'https://someCDN'
}
}
打包後
.image {
background-image: url('https://someCDN/test.png');
}
程式碼分割
webpack 4 的Code Splitting 它最大的特點就是配置簡單,如果你的 mode 是 production,那麼 webpack 4 就會自動開啟 Code Splitting。
webpack內建分包策略:
- 新程式碼塊可以被共享引用,或者這些模組都是來自node_modules資料夾裡面
- 新程式碼塊大於30kb(min+gziped之前的體積)
- 按需載入併發最大請求數, 應該小於或者等於5
- 初始載入的程式碼塊,最大數量應該小於或等於3
配置
optimization: {
splitChunks: {
chunks: "async", // 必須三選一: "initial" | "all"(推薦) | "async" (預設就是async)
minSize: 30000, // 最小尺寸,30000
minChunks: 1, // 最小 chunk ,預設1,只要被引用一次就分割出來
maxAsyncRequests: 5, // 最大非同步請求數, 預設5
maxInitialRequests : 3, // 最大初始化請求書,預設3
automaticNameDelimiter: '~',// 打包分隔符
name: function(){}, // 打包後的名稱,此選項可接收 function
cacheGroups:{ // 這裡開始設定快取的 chunks
vendor: { // key 為entry中定義的 入口名稱
chunks: "initial", // 必須三選一: "initial" | "all" | "async"(預設就是async)
test: /react|lodash/, // 正則規則驗證,如果符合就提取 chunk
name: "vendor", // 要快取的 分隔出來的 chunk 名稱
priority: 0, // 快取組優先順序
minSize: 30000,
minChunks: 1,
enforce: true,
maxAsyncRequests: 5, // 最大非同步請求數, 預設5
maxInitialRequests : 3, // 最大初始化請求書,預設3
reuseExistingChunk: true // 可設定是否重用該chunk
}
}
}
}
minChunks
最小 被引用的次數 ,預設1,只要被引用一次就分割出來。
maxAsyncRequests
表示能非同步請求的最大數量。比如非同步請求一個檔案,檔案中還非同步請求另一個檔案,這時兩個檔案會分開打包,如果設定為1,兩個非同步請求檔案會打包在一起。詳細解釋可以看webpack4 maxAsyncRequests記錄。
maxInitialRequests
程式碼分割以後,除去runtime所能生成的最多指令碼數量。
chunks
表示參與程式碼分割的模組型別
demo裡,如果chunks賦值為:
- initial:將所有非動態載入的模組放到vendor 裡
- async:將所有動態載入的模組打包到vendor
- all:把動態和非動態模組同時進行最佳化打包,放到vendor裡
詳細講解可以看這裡。
cacheGroups
cacheGroups:快取組,可以設定快取的chunks。
注意:
- cacheGroups 會繼承和覆蓋splitChunks的配置項,但是test、priorty和reuseExistingChunk只能用於配置快取組。
optimization.runtimeChunk
透過optimization.runtimeChunk: true選項,webpack會新增一個只包含執行時(runtime)額外程式碼塊到每一個入口。
打包後的js包括webpackJsonp,checkDeferredModules,__webpack_require__,__webpack_require__.e等用於模組載入的方法。
其中jsonpScriptSrc,函式中存在chunkid與chunkname的對映,用於根據chunkid得到chunks的載入路徑。因為這個對映會受chunk增加或減少的影響,經常變化,不單獨打包會生成到每個非非同步載入的chunk裡,使得本來沒變的chunk也不能快取了。所以一般會單獨打包或內嵌到html裡。
非同步載入打包模組
正常情況下,透過非同步引用的模組會打包成一個chunk。如果引用路徑是動態的,比如:
ret.component = () => import("@/views" + ret.path + ".vue");
會把views檔案下,所有沒有被引用的元件(被引用的是子元件),單獨打包成chunk。
參考資料
手摸手,帶你用合理的姿勢使用webpack4
Webpack——解決疑惑,讓你明白
沒有了CommonsChunkPlugin,我們拿什麼來分包(譯)