1. 程式人生 > >webpack4: 程式碼分割CommonChunkPlugin的壽終正寢

webpack4: 程式碼分割CommonChunkPlugin的壽終正寢

這是小弟第一次翻譯,雖自己理解了其精華,但無法精準表達,還望海涵。

webpack 4對塊圖進行了一些重大改進,並增加了對 chunk 拆分的新優化(這是對 CommonsChunkPlugin 的一種改進)。

讓我們看看之前的塊圖存在的缺點。

之前的塊圖通過父子關係連線到其他塊,chunk 包含模組。

當一個塊有父母時,可以假定在載入時至少有一個父母已經載入了。這些資訊可以被優化步驟所使用。當 chunk 中的模組在所有父母中都使用時,就可以把這個模組提取出來,因為它在任何情況下都需要使用。

在入口或者非同步分割點引用這些 chunk 。這些 chunk 是並行載入的。

這種圖形很難理解 chunks 的分割。例如在使用 CommonChunkPlugin 的時候,從一個或多個 chunks 刪除模組並放入一個新模組,這個新模組需要連線到塊圖中。但是應該怎麼定位這個新模組?作為之前 chunk 的父母?作為孩子? 在 CommonChunkPlugin 中將其新增為父母,但是從技術角度上這是錯誤的,也會造成對優化產生很多負作用。

新的塊圖引入了一個新物件:ChunkGroup. 一個ChunkGroup包含一個Chunks.

在入口點或非同步分割點處引用一個ChunkGroup,這就意味著包含所有並行的Chunks。一個Chunk可以被引用在多個ChunkGroup中。

Chunk之間不再存在父子關係,ChunkGroups 之間也不存在這種關係。

現在 Chunks 的分割可以被理解了,因為新的Chunks被新增到所有包含原始 Chunk 的 ChunkGroups 中,這並不會影響父母關係。

現在解決了這個問題,我們可以開始更多的使用Chunk分割。我們可以拆分任何 chunk,而不用擔心破壞塊圖。 CommonsChunkPlugin存在很多問題:

它可能導致下載更多的超過我們使用的程式碼
它在非同步chunks中是低效的。
配置繁瑣,很難使用
難以被理解
所以一個新的外掛誕生了: SplitChunksPlugin

它使用模組重複計數和模組類別(如 node_modules ),通過 heuristics 自動識別應該被分塊的模組,並分割 chunks。

這有個兩者的比喻,CommonsChunkPlugin就好像: 建立一個所有模組中都共同存在的模組。 而SplitChunksPlugin就像是:“Here are the heuristics, make sure you fullfil them”

SplitChunksPlugin 也有著不錯的特點:

不會下載不需要的程式碼
對非同步chunks也很高效
被預設用於非同步chunks
可以通過多個vendor chunks來進行vender的分割
使用簡單
不依賴塊圖
基本上是自動的
這裡有一些SplitChunksPlugin會為你做的例子。這些示例僅顯示預設行為。有更多的可能性與額外的配置。

您可以通過optimization.splitChunks進行配置。這些示例提到了有關塊的內容,預設情況下,它僅適用於非同步塊,但對於optimization.splitChunks.chunks:“all”對於初始塊也是如此。

我們假設這裡使用的每個外部庫都大於30kb,因為優化僅在該閾值之後進行。

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 會自動建立兩個 vendors chunks, 結果如下:

vendors~chunk-a~chunk-b: react, react-dom

vendors~chunk-c~chunk-d: angular

chunk-a to chunk-d: Only the components

Vendors 重疊
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 會自動建立兩個 vendors chunks, 結果如下:

vendors~chunk-a~chunk-b~chunk-c: react, react-dom

vendors~chunk-b~chunk-c: lodash

chunk-a to chunk-c: Only the components

共享模組
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

假設共享元件的大小大於30kb,webpack將建立vendors chunk 和一個a commons chunk,結果如下:

vendors~chunk-a~chunk-b~chunk-c: vue

commons~chunk-a~chunk-b~chunk-c: some shared components

chunk-a to chunk-c: Only the components

When the size of the shared components is smaller than 30kb, webpack intentionally duplicates the modules in chunk-a to chunk-c. We think reduces download size is not worth the extra request needed for a separate chunk load.

多個共享模組
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將建立兩個vendors chunks和兩個commons chunks

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 to chunk-d: Only the components

Note: Since the chunk name includes all origin chunk names it’s recommended for production builds with long term caching to NOT include [name] in the filenames, or switch off name generation via optimization.splitChunks.name: false. Elsewise files will invalidate i. e. when more chunks with the same vendors are added.

由於塊名稱包含所有源塊名稱,因此建議在生產環境下使用來達到長期快取,以避免在檔名中包含[name].或者通過optimization.splitChunks.name關閉名稱生成:false。其他檔案將使我無效。即當新增更多與同一vendors的塊時。