原文:RIP CommonsChunkPluginnode
webpack 4 移除 CommonsChunkPlugin
,取而代之的是兩個新的配置項(optimization.splitChunks 和 optimization.runtimeChunk),下面介紹一下用法和機制。react
webpack模式模式如今已經作了一些通用性優化,適用於多數使用者。webpack
須要注意的是:默認模式隻影響按需(on-demand)加載的代碼塊(chunk),由於改變初始代碼塊會影響聲明在HTML的script
標籤。若是能夠處理好這些(好比,從打包狀態裏面讀取並動態生成script標籤到HTML),你能夠經過設置optimization.splitChunks.chunks: "all"
,應用這些優化模式到初始代碼塊(initial chunk)。web
webpack根據下述條件自動進行代碼塊分割:swift
node_modules
文件夾裏面爲了知足後面兩個條件,webpack有可能受限於包的最大數量值,生成的代碼體積往上增長。緩存
咱們來看一下一些例子:dom
// entry.js import("./a");
// a.js import "react-dom"; // ...
結果:webpack會建立一個包含react-dom
的分離代碼塊。當import
調用時候,這個代碼塊就會與./a
代碼被並行加載。async
爲何會這樣打包:函數
node_modules
來的這樣打包有什麼好處呢?性能
對比起你的應用代碼,react-dom
可能不會常常變更。經過將它分割至另一個代碼塊,這個代碼塊能夠被獨立緩存起來(假設你在用的是長期緩存策略:chunkhash,records,Cache-Control)
// entry.js import("./a"); import("./b");
// a.js import "./helpers"; // helpers is 40kb in size // ...
// b.js import "./helpers"; import "./more-helpers"; // more-helpers is also 40kb in size // ...
結果:webpack會建立一個包含./helpers
的獨立代碼塊,其餘模塊會依賴於它。在import
被調用時候,這個代碼塊會跟原始的代碼並行加載(譯註:它會跟a.js
和b.js
並行加載)。
爲何會這樣打包:
import
)調用依賴(指的是a.js
和b.js
)helpers
體積大於30kb這樣打包有什麼好處呢?
將helpers
代碼放在每個依賴的塊裏,可能就意味着,用戶重複會下載它兩次。經過用一個獨立的代碼塊分割,它只須要被下載一次。實際上,這只是一種折衷方案,由於咱們爲此須要付出額外的一次請求的代價。這就是爲何默認webpack將最小代碼塊分割體積設置成30kb(譯註:過小體積的代碼塊被分割,可能還會由於額外的請求,拖慢加載性能)。
經過optimizations.splitChunks.chunks: "all"
,上面的策略也能夠應用到初始代碼塊上(inital chunks)。代碼代碼塊也會被多個入口共享&按需加載(譯註:以往咱們使用CommonsChunkPlugin最一般的目的)。
若是想要更深刻控制這個按需分塊的功能,這裏提供不少選項來知足你的需求。
Disclaimer:不要在沒有實踐測量的狀況下,嘗試手動優化這些參數。默認模式是通過千挑萬選的,能夠用於知足最佳web性能的策略。
這項優化能夠用於將模塊分配到對應的Cache group
。
默認模式會將全部來自node_modules
的模塊分配到一個叫vendors
的緩存組;全部重複引用至少兩次的代碼,會被分配到default
的緩存組。
一個模塊能夠被分配到多個緩存組,優化策略會將模塊分配至跟高優先級別(priority)的緩存組,或者會分配至能夠造成更大致積代碼塊的組裏。
在知足下述全部條件時,那些從相同代碼塊和緩存組來的模塊,會造成一個新的代碼塊(譯註:好比,在知足條件下,一個vendoer可能會被分割成兩個,以充分利用並行請求性能)。
有四個選項能夠用於配置這些條件:
minSize
(默認是30000):造成一個新代碼塊最小的體積minChunks
(默認是1):在分割以前,這個代碼塊最小應該被引用的次數(譯註:保證代碼塊複用性,默認配置的策略是不須要屢次引用也能夠被分割)maxInitialRequests
(默認是3):一個入口最大的並行請求數maxAsyncRequests
(默認是5):按需加載時候最大的並行請求數。要控制代碼塊的命名,能夠用name
參數來配置。
注意:當不一樣分割代碼塊被賦予相同名稱時候,他們會被合併在一塊兒。這個能夠用於在:好比將那些多個入口/分割點的共享模塊(vendor)合併在一塊兒,不過不推薦這樣作。這可能會致使加載額外的代碼。
若是賦予一個神奇的值true
,webpack會基於代碼塊和緩存組的key
自動選擇一個名稱。除此以外,可使用字符串或者函數做爲參數值。
當一個名稱匹配到相應的入口名稱,這個入口會被移除。
經過chunks
選項,能夠配置控制webpack選擇哪些代碼塊用於分割(譯註:其餘類型代碼塊按默認方式打包)。有3個可選的值:initial
、async
和all
。webpack將會只對配置所對應的代碼塊應用這些策略。
reuseExistingChunk
選項容許複用已經存在的代碼塊,而不是新建一個新的,須要在精確匹配到對應模塊時候纔會生效。
這個選項能夠在每一個緩存組(Cache Group)裏面作配置。
test
選項用於控制哪些模塊被這個緩存組匹配到。原封不動傳遞出去的話,它默認會選擇全部的模塊。能夠傳遞的值類型:RegExp
、String
和Function
經過這個選項,能夠經過絕對資源路徑(absolute modules resource path)或者代碼塊名稱(chunk names)來匹配對應模塊。當一個代碼塊名稱(chunk name)被匹配到,這個代碼塊的全部模塊都會被選中。
這是默認的配置:
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 } } }
默認來講,緩存組會繼承splitChunks
的配置,可是test
、priorty
和reuseExistingChunk
只能用於配置緩存組。
cacheGroups
是一個對象,按上述介紹的鍵值對方式來配置便可,值表明對應的選項:
除此以外,全部上面列出的選擇都是能夠用在緩存組裏的:chunks
, minSize
, minChunks
, maxAsyncRequests
, maxInitialRequests
, name
。
能夠經過optimization.splitChunks.cacheGroups.default: false
禁用default
緩存組。
default
緩存組的優先級(priotity)是負數,所以全部自定義緩存組均可以有比它更高優先級(譯註:更高優先級的緩存組能夠優先打包所選擇的模塊)(默認自定義緩存組優先級爲0)
能夠用一些例子來講明:
splitChunks: { cacheGroups: { commons: { name: "commons", chunks: "initial", minChunks: 2 } } }
這會建立一個commons
代碼塊,這個代碼塊包含全部被其餘入口(entrypoints)共享的代碼。
注意:這可能會致使下載額外的代碼。
splitChunks: { cacheGroups: { commons: { test: /[\\/]node_modules[\\/]/, name: "vendors", chunks: "all" } } }
這會建立一個名爲vendors
的代碼塊,它會包含整個應用全部來自node_modules
的代碼。
注意:這可能會致使下載額外的代碼。
經過optimization.runtimeChunk: true
選項,webpack會添加一個只包含運行時(runtime)額外代碼塊到每個入口。(譯註:這個須要看場景使用,會致使每一個入口都加載多一份運行時代碼)