沒有了CommonsChunkPlugin,咱拿什麼來分包(譯)

原文:RIP CommonsChunkPluginnode

webpack 4 移除 CommonsChunkPlugin,取而代之的是兩個新的配置項(optimization.splitChunks 和 optimization.runtimeChunk),下面介紹一下用法和機制。react

默認方式

webpack模式模式如今已經作了一些通用性優化,適用於多數使用者。webpack

須要注意的是:默認模式隻影響按需(on-demand)加載的代碼塊(chunk),由於改變初始代碼塊會影響聲明在HTML的script標籤。若是能夠處理好這些(好比,從打包狀態裏面讀取並動態生成script標籤到HTML),你能夠經過設置optimization.splitChunks.chunks: "all",應用這些優化模式到初始代碼塊(initial chunk)。web

webpack根據下述條件自動進行代碼塊分割:swift

  • 新代碼塊能夠被共享引用,OR這些模塊都是來自node_modules文件夾裏面
  • 新代碼塊大於30kb(min+gziped以前的體積)
  • 按需加載的代碼塊,最大數量應該小於或者等於5
  • 初始加載的代碼塊,最大數量應該小於或等於3

爲了知足後面兩個條件,webpack有可能受限於包的最大數量值,生成的代碼體積往上增長。緩存

咱們來看一下一些例子:dom

Example 1

// entry.js
import("./a");
// a.js
import "react-dom";
// ...

結果:webpack會建立一個包含react-dom的分離代碼塊。當import調用時候,這個代碼塊就會與./a代碼被並行加載。async

爲何會這樣打包:函數

  • 條件1:這個代碼塊是從node_modules來的
  • 條件2:react-dom大於30kb
  • 條件3:按需請求的數量是2(小於5)
  • 條件4:不會影響初始代碼請求數量

這樣打包有什麼好處呢?性能

對比起你的應用代碼,react-dom可能不會常常變更。經過將它分割至另一個代碼塊,這個代碼塊能夠被獨立緩存起來(假設你在用的是長期緩存策略:chunkhash,records,Cache-Control)

Example 2

// entry.js
import("./a");
import("./b");
// a.js
import "./helpers"; // helpers is 40kb in size
// ...
// b.js
import "./helpers";
import "./more-helpers"; // more-helpers is also 40kb in size
// ...

結果:webpack會建立一個包含./helpers的獨立代碼塊,其餘模塊會依賴於它。在import被調用時候,這個代碼塊會跟原始的代碼並行加載(譯註:它會跟a.jsb.js並行加載)。

爲何會這樣打包:

  • 條件1:這個代碼塊會被兩個導入(import)調用依賴(指的是a.jsb.js
  • 條件2:helpers體積大於30kb
  • 條件3:按需請求的數量是2(小於5)
  • 條件4:不會影響初始代碼請求數量

這樣打包有什麼好處呢?

helpers代碼放在每個依賴的塊裏,可能就意味着,用戶重複會下載它兩次。經過用一個獨立的代碼塊分割,它只須要被下載一次。實際上,這只是一種折衷方案,由於咱們爲此須要付出額外的一次請求的代價。這就是爲何默認webpack將最小代碼塊分割體積設置成30kb(譯註:過小體積的代碼塊被分割,可能還會由於額外的請求,拖慢加載性能)。

經過optimizations.splitChunks.chunks: "all",上面的策略也能夠應用到初始代碼塊上(inital chunks)。代碼代碼塊也會被多個入口共享&按需加載(譯註:以往咱們使用CommonsChunkPlugin最一般的目的)。

配置

若是想要更深刻控制這個按需分塊的功能,這裏提供不少選項來知足你的需求。

Disclaimer:不要在沒有實踐測量的狀況下,嘗試手動優化這些參數。默認模式是通過千挑萬選的,能夠用於知足最佳web性能的策略。

緩存組(Cache Group)

這項優化能夠用於將模塊分配到對應的Cache group

默認模式會將全部來自node_modules的模塊分配到一個叫vendors的緩存組;全部重複引用至少兩次的代碼,會被分配到default的緩存組。

一個模塊能夠被分配到多個緩存組,優化策略會將模塊分配至跟高優先級別(priority)的緩存組,或者會分配至能夠造成更大致積代碼塊的組裏。

Conditions

在知足下述全部條件時,那些從相同代碼塊和緩存組來的模塊,會造成一個新的代碼塊(譯註:好比,在知足條件下,一個vendoer可能會被分割成兩個,以充分利用並行請求性能)。

有四個選項能夠用於配置這些條件:

  • minSize(默認是30000):造成一個新代碼塊最小的體積
  • minChunks(默認是1):在分割以前,這個代碼塊最小應該被引用的次數(譯註:保證代碼塊複用性,默認配置的策略是不須要屢次引用也能夠被分割)
  • maxInitialRequests(默認是3):一個入口最大的並行請求數
  • maxAsyncRequests(默認是5):按需加載時候最大的並行請求數。

Naming

要控制代碼塊的命名,能夠用name參數來配置。

注意:當不一樣分割代碼塊被賦予相同名稱時候,他們會被合併在一塊兒。這個能夠用於在:好比將那些多個入口/分割點的共享模塊(vendor)合併在一塊兒,不過不推薦這樣作。這可能會致使加載額外的代碼。

若是賦予一個神奇的值true,webpack會基於代碼塊和緩存組的key自動選擇一個名稱。除此以外,可使用字符串或者函數做爲參數值。

當一個名稱匹配到相應的入口名稱,這個入口會被移除。

Select chunks

經過chunks選項,能夠配置控制webpack選擇哪些代碼塊用於分割(譯註:其餘類型代碼塊按默認方式打包)。有3個可選的值:initialasyncall。webpack將會只對配置所對應的代碼塊應用這些策略。

reuseExistingChunk選項容許複用已經存在的代碼塊,而不是新建一個新的,須要在精確匹配到對應模塊時候纔會生效。

這個選項能夠在每一個緩存組(Cache Group)裏面作配置。

Select modules

test選項用於控制哪些模塊被這個緩存組匹配到。原封不動傳遞出去的話,它默認會選擇全部的模塊。能夠傳遞的值類型:RegExpStringFunction

經過這個選項,能夠經過絕對資源路徑(absolute modules resource path)或者代碼塊名稱(chunk names)來匹配對應模塊。當一個代碼塊名稱(chunk name)被匹配到,這個代碼塊的全部模塊都會被選中。

配置緩存組(Configurate cache group)

這是默認的配置:

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

默認來講,緩存組會繼承splitChunks的配置,可是testpriortyreuseExistingChunk只能用於配置緩存組。

cacheGroups是一個對象,按上述介紹的鍵值對方式來配置便可,值表明對應的選項:

除此以外,全部上面列出的選擇都是能夠用在緩存組裏的:chunks, minSize, minChunks, maxAsyncRequests, maxInitialRequests, name

能夠經過optimization.splitChunks.cacheGroups.default: false禁用default緩存組。

default緩存組的優先級(priotity)是負數,所以全部自定義緩存組均可以有比它更高優先級(譯註:更高優先級的緩存組能夠優先打包所選擇的模塊)(默認自定義緩存組優先級爲0)

能夠用一些例子來講明:

Example 1

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

這會建立一個commons代碼塊,這個代碼塊包含全部被其餘入口(entrypoints)共享的代碼。

注意:這可能會致使下載額外的代碼。

Example 2

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

這會建立一個名爲vendors的代碼塊,它會包含整個應用全部來自node_modules的代碼。

注意:這可能會致使下載額外的代碼。

optimization.runtimeChunk

經過optimization.runtimeChunk: true選項,webpack會添加一個只包含運行時(runtime)額外代碼塊到每個入口。(譯註:這個須要看場景使用,會致使每一個入口都加載多一份運行時代碼)

相關文章
相關標籤/搜索