標籤:

?? 再見,CommonsChunkPlugin

原文:gist.github.com/sokra/1

Webpack 4 移除了 CommonsChunkPlugin,取而代之的是兩個新的選項(optimization.splitChunksoptimization.runtimeChunk)。以下是它的工作原理。


? Defaults

默認情況下,它針對大多數用戶做了一些非常有用的優化。

注意:默認隻影響按需載入的 chunks,這是因為初始 chunks 的更改將會影響到 HTML 中的 script 標籤。如果你能處理這個問題(即通過分析入口模塊來生成 script 標籤),可以通過設置optimization.splitChunks.chunks: "all"為初始 chunks 也啟用這些優化。

webpack 將在滿足以下條件時自動分割 chunks:

  • 新的 chunk 能夠被多處引用,或者模塊來自node_modules文件夾
  • 新的 chunk 大於30kb(min + gz 之前)
  • 按需載入的模塊中,並行請求數小於等於5
  • 初始頁面的並行請求數小於等於3

在試圖滿足最後兩個條件時,webpack 將偏向於生成更大的 chunk。

讓我們看一些例子。

示例 1

// entry.jsimport("./a");

// a.jsimport "react";// ...

結果:一個包含 react 的單獨 chunk將被創建。import 語句被執行時,這個 chunk 將與包含./a的原始 chunk 並行載入。

原因:

  • 條件1:這個 chunk 包含來自node_modules的模塊
  • 條件2:react 大於30kb
  • 條件3:import 時並行請求數為2
  • 條件4:初始頁面載入時的並行請求數不變

優點:

與應用程序代碼相比,react 可能很少發生變化。通過將它打包為單獨的 chunk,可以將它與應用程序代碼分別緩存(假設你正在使用長期緩存:chunkhash、records、Cache-Control)。

示例 2

// entry.jsimport("./a");import("./b");

// a.jsimport "./helpers"; // helpers is 40kb in size// ...

// b.jsimport "./helpers";import "./more-helpers"; // more-helpers is also 40kb in size// ...

結果:一個包含./helpers及其所有依賴項的 chunk 將被創建。import 時,該chunk 將與原始 chunk 並行載入。

原因:

  • 條件1:這個 chunk 被2個模塊引用
  • 條件2:helpers 大於30kb
  • 條件3:import 時並行請求數為
  • 條件4:初始頁面載入時的並行請求數不變

優點:

將 helpers 的代碼打包到每個 chunk 意味著它可能被下載兩次。 而通過打包成一個單獨的 chunk,它只會被下載一次。 事實上,這是一個折衷的方案,因為我們需要額外做一次請求。 這也是為什麼需要限制一個最小尺寸(30kb)的原因。

通過設置 optimizations.splitChunks.chunks: "all" ,初始 chunk 也將被這樣處理。 Chunks 甚至可以在入口模塊和按需載入模塊之間共享。


? 配置

對於希望自定義功能的用戶,有很多選項可以滿足需求。

免責聲明:請不要嘗試沒有經過測試的手動優化。 當前的默認設置是針對 Web 性能的最佳實踐。

Cache Groups

通過 optimization 配置可以將模塊分配給緩存組。

默認會將node_modules中的所有模塊分配到一個名為vendors的緩存組;並將所有被引用2次及以上的模塊分配到一個名為default的變更組。

一個模塊可以被分配給多個緩存組。 Optimization 會優先選擇更高優先順序(priority 選項)的緩存組,或者更大的緩存組。

條件

當滿足所有條件時,來自相同 chunk 和緩存組的模塊將形成一個新的 chunk。

條件配置共有4個選項:

  • minSize (默認值:30000)chunk 的最小尺寸
  • minChunks (默認值:1)引用同一模塊的最小 chunk 數
  • maxInitialRequests (默認值:3)入口頁面的最大並行請求數
  • maxAsyncRequests (默認值:5)按需載入模塊的最大並行請求數

命名

可以使用name選項來控制分隔出的 chunk 的名稱。

注意:當為不同的 chunks 分配相同的名稱時,它們將被合併。這個特性可以用來將被不同入口點/分割點引用的所有 vendor 模塊合併到同一個 chunk,但我並不建議這樣做。因為這可能導致不必要的代碼被下載。

魔法值 true 將基於 chunks 和緩存組的 key 自動選擇一個名稱。也可以傳入一個字元串或函數。

當名稱和入口模塊的名稱匹配時,入口模塊將被移除。

選擇 chunks

通過chunks選項,可以配置被選擇的 chunks。這裡有3個可選的值:"initial", "async""all"。Optimization 配置中該選項的值分別代表選擇初始 chunks,按需載入 chunks,以及所有 chunks。

當模塊匹配時,reuseExistingChunk 選項允許重用現有的 chunks,而不是創建一個新的 chunk。

可以在 cache group 級別進行控制。

選擇模塊

test 選項用來控制緩存組中包含哪些模塊。默認情況下將選擇所有模塊。選項的值可以是正則表達式、字元串或函數。

可以通過模塊的絕對資源路徑或 chunk 名稱進行匹配。當一個 chunk 名稱匹配時,它包含所有的模塊都將被選擇。

配置 cache groups

以下是默認配置:

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 } }}

默認情況下,cache groups 繼承來自 splitChunks.*的所有選項,但test, priorityreuseExistingChunk選項只能在 cache group 級別進行配置。

cacheGroups 是一個對象,它可以配置多個 cache group 的 key 和選項:

這些選項都是可用的: chunks, minSize, minChunks, maxAsyncRequests, maxInitialRequests, name.

傳入false以禁用 default 組:optimization.splitChunks.cacheGroups.default: false

default 組的優先順序是負數,因此所有的自定義緩存組(默認優先順序為0)都將比它的優先順序高。

這裡有一些例子及其效果:

splitChunks: { cacheGroups: { commons: { name: "commons", chunks: "initial", minChunks: 2 } }}

創建一個名為commons的 chunk,它包含了所有入口的公共代碼。

注意:這將導致一些不必要代碼的下載。

splitChunks: { cacheGroups: { commons: { test: /[\/]node_modules[\/] name: "vendors", chunks: "all" } }}

創建一個名為 vendors 的chunk,它包含來自應用中 node_modules 文件夾的所有代碼。

注意:這將導致一些不必要代碼的下載。


? optimization.runtimeChunk

optimization.runtimeChunk: true 將為每個入口添加一個只包含 runtime 的 chunk。


推薦閱讀:

使用Feature Matrix來構建應用
利用WebPack 打包 Vue 項目,部署在 Github Pages 上遇到的小坑
基於gulp+webpack構建基礎
Webpack原理-編寫Plugin

TAG:webpack |