?? 再見,CommonsChunkPlugin
原文:https://gist.github.com/sokra/1522d586b8e5c0f5072d7565c2bee693
Webpack 4 移除了 CommonsChunkPlugin,取而代之的是兩個新的選項(optimization.splitChunks
和 optimization.runtimeChunk
)。以下是它的工作原理。
? Defaults
默認情況下,它針對大多數用戶做了一些非常有用的優化。
注意:默認隻影響按需載入的 chunks,這是因為初始 chunks 的更改將會影響到 HTML 中的 script 標籤。如果你能處理這個問題(即通過分析入口模塊來生成 script 標籤),可以通過設置
optimization.splitChunks.chunks: "all"
為初始 chunks 也啟用這些優化。
webpack 將在滿足以下條件時自動分割 chunks:
- 新的 chunk 能夠被多處引用,或者模塊來自
node_modules
文件夾 - 新的 chunk 大於30kb(min + gz 之前)
- 按需載入的模塊中,並行請求數小於等於5
- 初始頁面的並行請求數小於等於3
在試圖滿足最後兩個條件時,webpack 將偏向於生成更大的 chunk。
讓我們看一些例子。
示例 1
// entry.jsimport("./a");
// a.jsimport "react";// ...
結果:一個包含 react 的單獨 chunk將被創建。import 語句被執行時,這個 chunk 將與包含./a
的原始 chunk 並行載入。
原因:
- 條件1:這個 chunk 包含來自
node_modules
的模塊 - 條件2:react 大於30kb
- 條件3:import 時並行請求數為2
- 條件4:初始頁面載入時的並行請求數不變
優點:
與應用程序代碼相比,react 可能很少發生變化。通過將它打包為單獨的 chunk,可以將它與應用程序代碼分別緩存(假設你正在使用長期緩存:chunkhash、records、Cache-Control)。
示例 2
// entry.jsimport("./a");import("./b");
// a.jsimport "./helpers"; // helpers is 40kb in size// ...
// b.jsimport "./helpers";import "./more-helpers"; // more-helpers is also 40kb in size// ...
結果:一個包含./helpers
及其所有依賴項的 chunk 將被創建。import 時,該chunk 將與原始 chunk 並行載入。
原因:
- 條件1:這個 chunk 被2個模塊引用
- 條件2:helpers 大於30kb
- 條件3:import 時並行請求數為
- 條件4:初始頁面載入時的並行請求數不變
優點:
將 helpers 的代碼打包到每個 chunk 意味著它可能被下載兩次。 而通過打包成一個單獨的 chunk,它只會被下載一次。 事實上,這是一個折衷的方案,因為我們需要額外做一次請求。 這也是為什麼需要限制一個最小尺寸(30kb)的原因。
通過設置
optimizations.splitChunks.chunks: "all"
,初始 chunk 也將被這樣處理。 Chunks 甚至可以在入口模塊和按需載入模塊之間共享。
? 配置
對於希望自定義功能的用戶,有很多選項可以滿足需求。
免責聲明:請不要嘗試沒有經過測試的手動優化。 當前的默認設置是針對 Web 性能的最佳實踐。
Cache Groups
通過 optimization 配置可以將模塊分配給緩存組。
默認會將node_modules
中的所有模塊分配到一個名為vendors
的緩存組;並將所有被引用2次及以上的模塊分配到一個名為default
的變更組。
一個模塊可以被分配給多個緩存組。 Optimization 會優先選擇更高優先順序(priority
選項)的緩存組,或者更大的緩存組。
條件
當滿足所有條件時,來自相同 chunk 和緩存組的模塊將形成一個新的 chunk。
條件配置共有4個選項:
minSize
(默認值:30000)chunk 的最小尺寸minChunks
(默認值:1)引用同一模塊的最小 chunk 數maxInitialRequests
(默認值:3)入口頁面的最大並行請求數maxAsyncRequests
(默認值:5)按需載入模塊的最大並行請求數
命名
可以使用name
選項來控制分隔出的 chunk 的名稱。
注意:當為不同的 chunks 分配相同的名稱時,它們將被合併。這個特性可以用來將被不同入口點/分割點引用的所有 vendor 模塊合併到同一個 chunk,但我並不建議這樣做。因為這可能導致不必要的代碼被下載。
魔法值 true
將基於 chunks 和緩存組的 key 自動選擇一個名稱。也可以傳入一個字元串或函數。
當名稱和入口模塊的名稱匹配時,入口模塊將被移除。
選擇 chunks
通過chunks
選項,可以配置被選擇的 chunks。這裡有3個可選的值:"initial"
, "async"
和 "all"
。Optimization 配置中該選項的值分別代表選擇初始 chunks,按需載入 chunks,以及所有 chunks。
當模塊匹配時,reuseExistingChunk
選項允許重用現有的 chunks,而不是創建一個新的 chunk。
可以在 cache group 級別進行控制。
選擇模塊
test
選項用來控制緩存組中包含哪些模塊。默認情況下將選擇所有模塊。選項的值可以是正則表達式、字元串或函數。
可以通過模塊的絕對資源路徑或 chunk 名稱進行匹配。當一個 chunk 名稱匹配時,它包含所有的模塊都將被選擇。
配置 cache groups
以下是默認配置:
splitChunks: { chunks: "async", minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, name: true, cacheGroups: { default: { minChunks: 2, priority: -20 reuseExistingChunk: true, }, vendors: { test: /[\/]node_modules[\/]/, priority: -10 } }}
默認情況下,cache groups 繼承來自 splitChunks.*
的所有選項,但test
, priority
和 reuseExistingChunk
選項只能在 cache group 級別進行配置。
cacheGroups
是一個對象,它可以配置多個 cache group 的 key 和選項:
這些選項都是可用的: chunks
, minSize
, minChunks
, maxAsyncRequests
, maxInitialRequests
, name
.
傳入false
以禁用 default 組:optimization.splitChunks.cacheGroups.default: false
default 組的優先順序是負數,因此所有的自定義緩存組(默認優先順序為0)都將比它的優先順序高。
這裡有一些例子及其效果:
splitChunks: { cacheGroups: { commons: { name: "commons", chunks: "initial", minChunks: 2 } }}
創建一個名為commons
的 chunk,它包含了所有入口的公共代碼。
注意:這將導致一些不必要代碼的下載。
splitChunks: { cacheGroups: { commons: { test: /[\/]node_modules[\/] name: "vendors", chunks: "all" } }}
創建一個名為 vendors
的chunk,它包含來自應用中 node_modules 文件夾的所有代碼。
注意:這將導致一些不必要代碼的下載。
? optimization.runtimeChunk
optimization.runtimeChunk: true
將為每個入口添加一個只包含 runtime 的 chunk。
推薦閱讀:
※使用Feature Matrix來構建應用
※利用WebPack 打包 Vue 項目,部署在 Github Pages 上遇到的小坑
※基於gulp+webpack構建基礎
※Webpack原理-編寫Plugin
TAG:webpack |