Webpack 4.0 CommonsChunkPlugin 和 optimization splitChunks

該文章內容大體翻譯自 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的區別

這個問題被修復以後,咱們能夠更多的使用文件拆分了。咱們能夠將任何文件拆分出來而且不須要提升其加載優先級。

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的例子。這些用例僅僅展示了它在默認配置下的行爲。你也可使用額外配置項來進行個性化定製。

提示:

  1. 能夠經過optimization.splitChunks進行配置。這裏的例子是關於文件的,默認狀況下僅適用於異步加載的文件塊。但也能夠添加optimization.splitChunks.chunks: "all"來配置適用於全部類型的文件。
  2. 咱們假定每一個額外導入的庫文件都大於30kb,由於優化僅在該體積以後開始進行。(能夠經過配置minSize屬性進行修改,默認 30000)

Vendors

  • chunk-a: react, react-dom, some components
  • chunk-b: react, react-dom, some other components
  • chunk-c: angular, some components
  • chunk-d: angular, some other components

webpack將會自動建立2個庫文件:

  • vendors~chunk-a~chunk-b: react, react-dom
  • vendors~chunk-c~chunk-d: angular
  • chunk-a chunk-b chunk-c chunk-d: 含有components

Vendors overlapping

  • chunk-a: react, react-dom, some components
  • chunk-b: react, react-dom, lodash, some other components
  • chunk-c: react, react-dom, lodash, some components

webpack依然會建立2個庫文件:

  • vendors~chunk-a~chunk-b~chunk-c: react, react-dom
  • vendors~chunk-b~chunk-c: lodash
  • chunk-a chunk-b chunk-c: 含有components

Shared modules

  • chunk-a: vue, some components, some shared components
  • chunk-b: vue, some other components, some shared components
  • chunk-c: vue, some more components, some shared components

假設全部的shared components體積都大於 30kb,webpack將會建立一個庫文件和一個通用組件文件:

  • vendors~chunk-a~chunk-b~chunk-c: vue
  • commons~chunk-a~chunk-b~chunk-c: some shared components
  • chunk-a chunk-b chunk-c: 含有components

當這些shared components體積小於30kb是,webpack會故意將該模塊複製到chunk-a chunk-b chunk-c三個文件中。咱們認爲進行分離所減少的加載體積的總體效果並不如一次額外的加載請求的消耗。

Multiple shared modules

  • chunk-a: react, react-dom, some components, some shared react components
  • chunk-b: react, react-dom, angular, some other components
  • chunk-c: react, react-dom, angular, some components, some shared react components, some shared angular components
  • chunk-d: angular, some other components, some shared angular components

webpack將會建立2個庫文件及2個通用組件文件

  • vendors~chunk-a~chunk-b~chunk-c: react, react-dom
  • vendors~chunk-b~chunk-c~chunk-d: angular
  • commons~chunk-a~chunk-c: some shared react components
  • commons~chunk-c~chunk-d: some shared angular components

chunk-a chunk-b chunk-c chunk-d: Only the components

提示:由於生成的導入文件名稱包含全部的原始文件名稱,因此咱們推薦在生產環境中使用的長效緩存文件不要包含[name]在文件名中,或者設置optimization.splitChunks.name: false來關閉文件名生成邏輯。這樣即便在後續開發中對該文件添加了新的引用,也不會修改文件名,該緩存邏輯依然生效。

相關文章
相關標籤/搜索