webpack 4 移除 CommonsChunkPlugin,取而代之的是兩個新的配置項(optimization.splitChunks 和 optimization.runtimeChunk


默認方式

webpack模式模式現在已經做了一些通用性優化,適用於多數使用者。

需要注意的是:默認模式只影響按需(on-demand)加載的代碼塊(chunk),因為改變初始代碼塊會影響聲明在HTML的script標簽。如果可以處理好這些(比如,從打包狀態里面讀取並動態生成script標簽到HTML),你可以通過設置optimization.splitChunks.chunks: "all",應用這些優化模式到初始代碼塊(initial chunk)。

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

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

為了滿足后面兩個條件,webpack有可能受限於包的最大數量值,生成的代碼體積往上增加。

我們來看一下一些例子:

Example 1

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

 

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

為什么會這樣打包:

  • 條件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是一個對象,按上述介紹的鍵值對方式來配置即可,值代表對應的選項:

除此之外,所有上面列出的選擇都是可以用在緩存組里的:chunksminSizeminChunksmaxAsyncRequestsmaxInitialRequestsname

可以通過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)額外代碼塊到每一個入口。(譯注:這個需要看場景使用,會導致每個入口都加載多一份運行時代碼)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM