Webpack 詳解之代碼分割(code-splitting)

本文全部的內容均基於 webpack@4.42.0 所撰寫。閱讀本文以前需瞭解 Webpack 的一些基本概念,如: entrychunkmodule 等。css

代碼分割是 Webpack 最引人注目的特性之一。這個特性容許開發者將代碼分割成不一樣的包,而後能夠按需加載或並行加載這些包。它能夠用來實現更小的包,並控制資源加載優先級,若是使用正確,將對加載時間產生重大影響。node

分割策略

首先介紹一下 Webpack 默認的代碼分割策略。webpack

webpack will automatically split chunks based on these conditions:web

  • New chunk can be shared OR modules are from the node_modules folder
  • New chunk would be bigger than 30kb (before min+gz)
  • Maximum number of parallel requests when loading chunks on demand would be lower or equal to 5
  • Maximum number of parallel requests at initial page load would be lower or equal to 3

上面這段話來自 Webpack 的官方文檔,說的是 Webpack 會在知足下面的條件時自動進行 chunk 的分割 (ps:若是沒有特殊配置的話,只有異步加載的 chunk 會自動進行分割)bash

  • 新的 chunk 能夠被共享或者 chunk 裏的 module 來自於 node_modules 文件夾
  • 新的 chunk 文件大小大於 30kb(壓縮前)
  • 按需加載的 chunk 內部的最大並行請求數不超過 5
  • 初始化頁面的並行請求的最大數量不超過 3

知足上面的四個條件 Webpack 就認爲能夠進行代碼分割,前兩個條件應該比較好理解,這裏解釋下後兩個條件的意思吧:併發

按需加載的 chunk 內部的最大並行請求數不超過 5

簡單來講就是加載 chunk 所發送的請求不能超過 5 個。舉個例子:異步

a.js 依賴了 1.js2.js3.js4.js 這四個文件,且這四個文件知足了代碼分割的前兩個條件 (被共享且大於 30kb)。這個時候就會分割出五個 chunk,分別是:a.chunk.js1.chunk.js2.chunk.js3.chunk.js4.chunk.js。此時加載 chunk~a 的併發請求數就剛好是 5 個,編譯後的加載代碼大體以下:async

// t.e 是加載的 chunk 的方法,t.e 的參數應該是 chunk 的 id,爲了容易閱讀,我這裏用了 chunk 的名稱替代。
Promise.all([t.e('1.chunk'),t.e('2.chunk'),t.e('3.chunk'),t.e('4.chunk'),t.e('a.chunk')]).then(() => // do some thing)
複製代碼

若是 a.js 又依賴了 5.js,,這個時候並不會分割出 5.chunk,由於若是分割出 5.chunk,那麼加載 a.chunk 的請求就是 6 個了, 5.js 的內容會被合併到 a.chunk 中。ui

初始化頁面的並行請求的最大數量不超過 3

這裏的初始化頁面能夠理解爲加載 entry,換句話說就是加載 entry的並行請求的最大數量不超過 3 個,如今就比較好理解了,和上一個條件基本一致,只不過一個是針對 entry 的,一個是針對普通的 chunk 的。這個配置是爲了對代碼分割的 chunk 數量進行必定的限制,避免分割出太多chunk致使請求數量過多的狀況。spa

要注意的是:

  • 這兩個限制並不包括 js 之外的請求好比css
  • 若是隻能容許再拆分一個模塊,那尺寸更大的模塊會被拆分出來。

分割配置

上面介紹的都是 Webpack 代碼分割的默認策略,這些策略是 Webpack 團隊認爲的最佳實踐。 若是你在項目有特殊的需求,好比認爲默認的 30kb 太大了,你想超過 10kb 就進行分割。Webpack 也提供了咱們一些配置去修改分割策略,這就是 Webpack 中的 optimization.splitChunks 配置,下面就介紹幾個比較相對重要的配置,完整的配置能夠查看文檔

splitChunks.chunks

function (chunk) | string

chunks 配置的是要針對哪些 chunk 進行代碼分割,以前有提到過,默認只會分割異步的加載的 chunkchunks 的值爲 string 時,有效的值爲all, asyncinitial

module.exports = {
  //...
  optimization: {
    splitChunks: {
      // 分割全部類型的 chunk
      chunks: 'all'
    }
  }
};
複製代碼
module.exports = {
  //...
  optimization: {
    splitChunks: {
      chunks (chunk) {
        // 除了 `my-excluded-chunk` 都進行分割
        return chunk.name !== 'my-excluded-chunk';
      }
    }
  }
};
複製代碼

splitChunks.minChunks

number

minChunks 指的是在代碼分割以前 module 至少被幾個 chunk 共享。默認值爲1

splitChunks.minSize

number

minSize 對應的就是分割策略中的第二個條件中的 30kb 的限制,開發者能夠根據項目的實際狀況靈活調節它的大小。

splitChunks.maxSize

number

這個配置是設置分割出來的 chunk 的最大文件大小的,默認值爲 0,也就是沒有上限。設置了該屬性,Webpack 就會盡量地把 chunk 的大小限制在maxSize 的值以內,不過一個完整的module 的代碼無法分割成幾段,因此該超過仍是會超過的。

你能夠經過設置這個屬性來分割出更多、更小的 chunk,不過隨之而來的就是更多的加載 chunk 的請求。

splitChunks.maxAsyncRequests

number

maxAsyncRequests 對應的是分割策略中的第三條的配置,默認值爲 5

splitChunks.maxInitialRequests

number

maxInitialRequests 對應的是分割策略中的第四條的配置,默認值爲 3

splitChunks.cacheGroups

cacheGroupssplitChunks 中最核心的配置之一,它的配置項包括 splitChunks.* 下的全部配置,且還多了testpriorityreuseExistingChunk 三個配置項。

cacheGroups 中的配置會覆蓋 splitChunks 中的配置,並且有優先級之分(經過 priority 設置優先級),cacheGroups 主要的用途是針對不一樣的 chunk 設置不一樣的分割策略,這能夠大大提高代碼分割的靈活性,筆者在這裏就不詳細展開說明使用方法了,感興趣的能夠參考官方文檔。

相關文章
相關標籤/搜索