Lazy Loading
的 chunks,例如
import(xxx)
語法載入的模組
initial
:只處理同步加載的 chunk,例如
import xxx
語法載入的模組
all
:兼容以上兩種方式,通通進行處理
我們在 entry 內的所有模組都是使用
import
方式進行載入,這才導致 SplitChunksPlugin 在預設配置下沒有任何反應,因為
chunks
預設配置是
async
,關於
async
的實際應用將會在下面補充介紹。理解了
chunks
是做什麼用,接下來換最為重要的
cacheGroups
選項部分:
cacheGroups
:定義 chunks 所屬的緩存組
{cacheGroups}
:緩存組名稱,可由
name
屬性更改
cacheGroups.{cacheGroups}.priority
:緩存組優先級,默認為
0
cacheGroups.{cacheGroups}.test
:控制當下緩存組匹配的 chunk,省略它會選擇所有 chunk
cacheGroups.{cacheGroups}.filename
:僅當 chunk 為同步加載時,才允許覆蓋文件名
cacheGroups.{cacheGroups}.enforce
:忽略全域的
部分選項
cacheGroups
選項是使用 SplitChunksPlugin 成功與否的關鍵,這邊要注意的是上面提到的選項,都是
cacheGroups
專屬可配置的區域選項,有沒有注意到我說的是區域選項?事實上,
cacheGroups
同層的選項都是屬於全域選項,也就是說你也可以在
cacheGroups
內配置
chunks
選項,一樣可以作用,且預設就已提供兩個
cacheGroups
供我們使用,為什麼前面單純的將
chunks
選項更改為
initial
就可以將 node_modules 內的模組抽離成獨立檔案,答案是不是呼之欲出了?
1 2 3 4 5 6 7 8 9 10 11
12 13 14 15 16 17 18 19
|
module.exports = { optimization: { splitChunks: { chunks: 'initial', cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10, }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, }, }, }, };
|
沒錯!就是依靠預設配置的
vendors
這一個
cacheGroups
,為什麼之前採預設配置都沒有反應,就是因為
vendors
參考的全域
chunks
配置屬性為
async
,但我們是採用同步加載方式引入模組,當然會沒有反應,此時將
chunks
改為
initial
即可正常啟動抽離 chunk 的動作,但一般我們並不會使用預設的
cacheGroups
,通常都會新增客製的
cacheGroups
做使用,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
module.exports = { optimization: { splitChunks: { cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, chunks: 'initial', name: 'vendors', enforce: true, priority: 10, }, }, }, }, };
|
上面是一個抽離 node_modules 相關模組使之成為獨立檔案的標準寫法,我們並沒有更改預設的全域配置,直接以區域配置進行客製化,將符合正規表達式的 chunk 抽離出來,且 chunk 的載入方式須為同步載入,忽略全域的部分選項,最後將 chunk 名稱更改為 vendors,此時的編譯結果如下:
1 2 3 4 5 6 7
|
webpack-demo/ │ ├─── dist/ │ │ │ ├─── vendors.js │ ├─── main.js │ └─── index.html
|
大功告成!如果 entry 內有任何引入 node_modules 模組的檔案,此模組都會被單獨打包進 vendors.js 內,如果你想要針對特定檔案進行抽離,只需要在正規表達式做撰寫即可,你也可以新增不同的
cacheGroups
專門針對不同要求做打包,優化整體的檔案結構。
介紹到這邊,已經把最重要的
cacheGroups
與
chunks
屬性給釐清了,可能有人會問,那其他的屬性呢?像是
minSize
、
maxSize
、
minChunks
等等,是做什麼用的?事實上,這幾個選項就如同字面上的意思,舉個例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
module.exports = { optimization: { splitChunks: { minSize: 70000, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, chunks: 'initial', name: 'vendors', enforce: true, }, }, }, }, };
|
上面這種寫法是不影響 vendors 這個
cacheGroups
的,因為我們啟用了
enforce
選項,代表不參考全域的屬性,正確的寫法應該如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
module.exports = { optimization: { splitChunks: { cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, chunks: 'initial', name: 'vendors', enforce: true, minSize: 70000, }, }, }, }, };
|
此時如果 node_modules 內的套件並沒有超過 70 KB,也就不會進入這一個
cacheGroups
,自然就不會產生 vendors 這個檔案,各位可自行試試看剩餘這這些選項,其實都大同小異,最重要的
cacheGroups
與
chunks
觀念學會比較重要。
SplitChunksPlugin Options
可傳遞參數列表,以下為常用的參數配置:
automaticNameDelimiter:
String
指定用於生成名稱的連結符號,默認為
~
minChunks:
Number
在做抽離代碼動作前,chunks 的最小引用次數,默認為
1
1 2 3 4 5 6 7 8 9
|
module.exports = { optimization: { splitChunks: { automaticNameDelimiter: '@', minChunks: 2, }, }, };
|