該文章內容大體翻譯自 webpack 4: Code Splitting, chunk graph and the splitChunks optimization
webpack 4.0 對代碼模塊的關係圖進行了一些巨大的優化,同時添加了一個新的 optimization
用於模塊的分離(能夠看作是對 CommonsChunkPlugin
的一次優化)。vue
先讓咱們看看舊版關係圖的一些缺陷。node
在以前的版本中,咱們將各個模塊打包進編譯後的文件之中,同時這些文件之間又是經過父子關係
來進行關聯,最後將咱們整個項目中的全部模塊串聯起來。react
當其中一個文件含有父級引用,那咱們能夠推斷出,在該文件完成加載時,已經成功加載了父級文件。那麼咱們能夠據此進行一些優化。好比當一個文件中的模塊已經在父級文件中正常運行,那麼咱們能夠將該模塊從文件中移除,由於它必然已經被成功加載。webpack
在入口點或異步拆分點處引用這些文件。這些文件將會並行加載。web
這種類型的關係圖使得分離splitting
變得很是困難。好比在你使用CommonsChunkPlugin
插件時。會有一個或多個文件內模塊被移動到新的文件中來。這一整個新文件須要被添加到關係圖中來。但咱們應該如何設置它的層級呢?做爲舊有文件的父級?仍是子級?CommonsChunkPlugin
中將其設置爲父級,但從技術層面來講,這是錯誤的,而且致使了一些負面的優化結果(提早加載的這個文件中的部分模塊不是必需的)。緩存
如今新的關係圖中,引入了一個新概念:ChunkGroup
。包含文件列表的文件分組。app
在入口點或異步拆分點處咱們會引用這個文件分組,該分組內的文件全都是並行加載。而一個文件能夠被多個文件分組引用(但不會屢次加載)。dom
如今再也不使用父子級的關係來描述文件之間的聯繫,取而代之的是文件分組ChunkGroup
。異步
那麼此時,splitting
文件就可以被表述出來。被建立的新文件能夠被添加到全部包含原始文件的文件分組中。同時也不會所以產生負面優化效果。優化
這個問題被修復以後,咱們能夠更多的使用文件拆分了。咱們能夠將任何文件拆分出來而且不須要提升其加載優先級。
CommonsChunkPlugin
存在如下這些問題:
因此新的插件誕生了:SplitChunksPlugin
。
它會使用模塊引用計數和模塊類別區分(好比:node_modules)來自動分離出須要被拆分的文件內引用模塊。
There is a paradigm shift here. The CommonsChunkPlugin
was like: 「Create this chunk and move all modules matching minChunks
into the new chunk」. The SplitChunksPlugin
is like: 「Here are the heuristics, make sure you fullfil them」. (imperative vs declarative)
這裏沒有理解所有的內容。
SplitChunksPlugin
同時提供了更多的特性:
下面是一些使用SplitChunksPlugin
的例子。這些用例僅僅展示了它在默認配置下的行爲。你也可使用額外配置項來進行個性化定製。
提示:
optimization.splitChunks
進行配置。這裏的例子是關於文件的,默認狀況下僅適用於異步加載的文件塊。但也能夠添加optimization.splitChunks.chunks: "all"
來配置適用於全部類型的文件。minSize
屬性進行修改,默認 30000)chunk-a
: react, react-dom, some componentschunk-b
: react, react-dom, some other componentschunk-c
: angular, some componentschunk-d
: angular, some other componentswebpack將會自動建立2個庫文件:
vendors~chunk-a~chunk-b
: react, react-domvendors~chunk-c~chunk-d
: angularchunk-a chunk-b chunk-c chunk-d
: 僅含有componentschunk-a
: react, react-dom, some componentschunk-b
: react, react-dom, lodash, some other componentschunk-c
: react, react-dom, lodash, some componentswebpack依然會建立2個庫文件:
vendors~chunk-a~chunk-b~chunk-c
: react, react-domvendors~chunk-b~chunk-c
: lodashchunk-a chunk-b chunk-c
: 僅含有componentschunk-a
: vue, some components, some shared componentschunk-b
: vue, some other components, some shared componentschunk-c
: vue, some more components, some shared components假設全部的shared components
體積都大於 30kb,webpack將會建立一個庫文件和一個通用組件文件:
vendors~chunk-a~chunk-b~chunk-c
: vuecommons~chunk-a~chunk-b~chunk-c
: some shared componentschunk-a chunk-b chunk-c
: 僅含有components當這些shared components
體積小於30kb是,webpack會故意將該模塊複製到chunk-a chunk-b chunk-c
三個文件中。咱們認爲進行分離所減少的加載體積的總體效果並不如一次額外的加載請求的消耗。
chunk-a
: react, react-dom, some components, some shared react componentschunk-b
: react, react-dom, angular, some other componentschunk-c
: react, react-dom, angular, some components, some shared react components, some shared angular componentschunk-d
: angular, some other components, some shared angular componentswebpack將會建立2個庫文件及2個通用組件文件
vendors~chunk-a~chunk-b~chunk-c
: react, react-domvendors~chunk-b~chunk-c~chunk-d
: angularcommons~chunk-a~chunk-c
: some shared react componentscommons~chunk-c~chunk-d
: some shared angular componentschunk-a chunk-b chunk-c chunk-d
: Only the components
提示:由於生成的導入文件名稱包含全部的原始文件名稱,因此咱們推薦在生產環境中使用的長效緩存文件不要包含[name]
在文件名中,或者設置optimization.splitChunks.name: false
來關閉文件名生成邏輯。這樣即便在後續開發中對該文件添加了新的引用,也不會修改文件名,該緩存邏輯依然生效。