webpack4之splitChunks.minSize和splitChunks.maxSize

概要

minSize和maxSize分別表示chunk在被拆分之前的最小體積和最大體積。(maxSize可以小於minSize)

準備工作

  1. 目錄
root
——dist(打包之後的文件夾)
——node_modules(下載的包)
——src(項目腳本目錄)
————entry(入口點腳本)
————modules(入口點中引入的模塊)
——package.json(包管理文件)
——webpack.config.js(webpack配置文件)
  1. webpack配置
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: {
    entry1: './src/entry/entry1.js',
    entry2: './src/entry/entry2.js'
  },
  plugins: [
    new CleanWebpackPlugin()
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  optimization: {
    splitChunks: {
      chunks: 'initial',
      minSize: 1,
      maxSize: 0,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 1,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
  // default config
  // optimization: {
  //   splitChunks: {
  //     chunks: 'async',
  //     minSize: 30000,
  //     minChunks: 1,
  //     maxAsyncRequests: 5,
  //     maxInitialRequests: 3,
  //     automaticNameDelimiter: '~',
  //     automaticNameMaxLength: 30,
  //     name: true,
  //     cacheGroups: {
  //       vendors: {
  //         test: /[\\/]node_modules[\\/]/,
  //         priority: -10
  //       },
  //       default: {
  //         minChunks: 2,
  //         priority: -20,
  //         reuseExistingChunk: true
  //       }
  //     }
  //   }
  // }
}
  1. package.json
{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10"
  }
}

案例

  1. demo1
################################
webpack.config.js:

splitChunks.maxSize設爲add.js的大小(單位爲字節byte)
splitChunks.minSize設爲1

################################
modules/add.js:(實際測試時通過註釋使得文件大小增大)

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
entry/entry1.js:

import add from '../modules/add.js'

console.log('index', add(1, 2))

################################
entry/entry2.js:

import add from '../modules/add'

console.log('index', add(1, 2))

打包之後,結果爲:

Hash: 358a729f95a5c6891684
Version: webpack 4.41.5
Time: 203ms
Built at: 2020/01/31 下午2:56:45
                          Asset       Size  Chunks             Chunk Names
default~entry1~entry2.bundle.js  151 bytes       0  [emitted]  default~entry1~entry2
               entry1.bundle.js   1.55 KiB       1  [emitted]  entry1
               entry2.bundle.js   1.56 KiB       2  [emitted]  entry2
Entrypoint entry1 = default~entry1~entry2.bundle.js entry1.bundle.js
Entrypoint entry2 = default~entry1~entry2.bundle.js entry2.bundle.js
[0] ./src/modules/add.js 1.92 KiB {0} [built]
[1] ./src/entry/entry1.js 68 bytes {1} [built]
[2] ./src/entry/entry2.js 65 bytes {2} [built]

假設add.js體積大小爲n,如果將minSize設爲n+1時,打包結果爲:

Hash: 96013ae2b6f35e4252f0
Version: webpack 4.41.5
Time: 73ms
Built at: 2020/01/31 下午3:01:48
                   Asset       Size  Chunks             Chunk Names
default~entry1.bundle.js  237 bytes       0  [emitted]  default~entry1
default~entry2.bundle.js  238 bytes       1  [emitted]  default~entry2
        entry1.bundle.js   1.47 KiB       2  [emitted]  entry1
        entry2.bundle.js   1.47 KiB       3  [emitted]  entry2
Entrypoint entry1 = default~entry1.bundle.js entry1.bundle.js
Entrypoint entry2 = default~entry2.bundle.js entry2.bundle.js
[0] ./src/modules/add.js 1.92 KiB {0} {1} [built]
[1] ./src/entry/entry1.js 68 bytes {0} [built]
[2] ./src/entry/entry2.js 65 bytes {1} [built]

當minSize設爲n+1時,n < n + 1,沒有達到最小值,所以add.js沒有被單獨打包出來。

  1. demo2
################################
webpack.config.js:

splitChunks.maxSize設爲add.js和entry1.js的大小之和(單位爲字節byte)
splitChunks.minSize設爲1

################################
modules/add.js:(實際測試時通過註釋使得文件大小增大)

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
entry/entry1.js:

import add from '../modules/add.js'

console.log('index', add(1, 2))

################################
entry/entry2.js:

import subtract from '../modules/subtract'

console.log('index', subtract(1, 2))

打包結果如下:

Hash: f54c64d4b9d87060c46d
Version: webpack 4.41.5
Time: 75ms
Built at: 2020/01/31 下午3:13:24
                   Asset       Size  Chunks             Chunk Names
default~entry1.bundle.js  123 bytes       0  [emitted]  default~entry1
        entry1.bundle.js   1.47 KiB       1  [emitted]  entry1
        entry2.bundle.js  976 bytes       2  [emitted]  entry2
Entrypoint entry1 = default~entry1.bundle.js entry1.bundle.js
Entrypoint entry2 = entry2.bundle.js
[0] ./src/entry/entry2.js + 1 modules 139 bytes {2} [built]
    | ./src/entry/entry2.js 80 bytes [built]
    | ./src/modules/subtract.js 59 bytes [built]
[1] ./src/entry/entry1.js + 1 modules 1.98 KiB {0} [built]
    | ./src/entry/entry1.js 65 bytes [built]
    | ./src/modules/add.js 1.92 KiB [built]

如果將minSize再加1,打包結果如下:

Hash: 573ca79b89928f028819
Version: webpack 4.41.5
Time: 73ms
Built at: 2020/01/31 下午3:17:18
           Asset       Size  Chunks             Chunk Names
entry1.bundle.js  976 bytes       0  [emitted]  entry1
entry2.bundle.js  977 bytes       1  [emitted]  entry2
Entrypoint entry1 = entry1.bundle.js
Entrypoint entry2 = entry2.bundle.js
[0] ./src/entry/entry1.js + 1 modules 1.98 KiB {0} [built]
    | ./src/entry/entry1.js 65 bytes [built]
    | ./src/modules/add.js 1.92 KiB [built]
[1] ./src/entry/entry2.js + 1 modules 139 bytes {1} [built]
    | ./src/entry/entry2.js 80 bytes [built]
    | ./src/modules/subtract.js 59 bytes [built]

可以看到沒有被打包出來。

  1. demo3

前面幾個案例,我們的maxSize都是設爲0,即小於minSize,那麼如果設爲非0數值,並且值小於minSize呢,效果是否是一樣的呢?

基於demo1,我們將minSize設爲add.js的體積大小,maxSize設爲10:

################################
webpack.config.js:

splitChunks.maxSize設爲add.js的大小(單位爲字節byte)
splitChunks.minSize設爲10

################################
modules/add.js:(實際測試時通過註釋使得文件大小增大)

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
entry/entry1.js:

import add from '../modules/add.js'

console.log('index', add(1, 2))

################################
entry/entry2.js:

import add from '../modules/add'

console.log('index', add(1, 2))

打包結果如下:

Hash: d922cb840f250b349314
Version: webpack 4.41.5
Time: 192ms
Built at: 2020/01/31 下午3:30:31
                                   Asset       Size  Chunks             Chunk Names
default~entry1~entry2~100271bb.bundle.js  151 bytes       0  [emitted]  default~entry1~entry2~100271bb
               entry1~14905de4.bundle.js   1.55 KiB       1  [emitted]  entry1~14905de4
               entry2~f28393c0.bundle.js   1.56 KiB       2  [emitted]  entry2~f28393c0
Entrypoint entry1 = default~entry1~entry2~100271bb.bundle.js entry1~14905de4.bundle.js
Entrypoint entry2 = default~entry1~entry2~100271bb.bundle.js entry2~f28393c0.bundle.js
[0] ./src/modules/add.js 1.92 KiB {0} [built]
[1] ./src/entry/entry1.js 65 bytes {1} [built]

測試時我們的add.js體積大小爲1963byte,所以minSize設置成了1963,同時maxSize設置成10,通過結果可以發現add.js仍然被打包出來,和demo1唯一的不同點是,打包出來的文件名多了一個~連接的後綴部分。

所以,max設置成0和非0是有區別的。

  1. demo4
################################
webpack.config.js:

splitChunks.maxSize設爲add.js和entry1.js的大小之和(單位爲字節byte)
splitChunks.minSize設爲10

################################
modules/add.js:(實際測試時通過註釋使得文件大小增大)

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
entry/entry1.js:

import add from '../modules/add.js'

console.log('index', add(1, 2))

################################
entry/entry2.js:

import subtract from '../modules/subtract'

console.log('index', subtract(1, 2))

打包報錯,具體原因個人不是很清楚。

基於前面四個案例,我們可以得出以下兩點:

a. maxSize默認爲0,表示最大體積沒有限制;
b. 如果設置的maxSize爲非0值,儘量保證 > minSize,< minSize可能導致腳本報錯;

  1. demo5

按正常的邏輯,我們讓maxSize > minSize,來看看打包的結果:

################################
webpack.config.js:

splitChunks.maxSize設爲add.js的大小(單位爲字節byte)
splitChunks.minSize設爲1

################################
modules/add.js:(實際測試時通過註釋使得文件大小增大)

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
entry/entry1.js:

import add from '../modules/add.js'

console.log('index', add(1, 2))

################################
entry/entry2.js:

import add from '../modules/add'

console.log('index', add(1, 2))

打包後結果爲:

Hash: 67137a86f859192e20c3
Version: webpack 4.41.5
Time: 203ms
Built at: 2020/01/31 下午6:14:26
                                   Asset       Size  Chunks             Chunk Names
       default~entry1~14905de4.bundle.js  147 bytes       1  [emitted]  default~entry1~14905de4
default~entry1~entry2~100271bb.bundle.js  151 bytes       0  [emitted]  default~entry1~entry2~100271bb
       default~entry2~f28393c0.bundle.js  148 bytes       2  [emitted]  default~entry2~f28393c0
                        entry1.bundle.js   1.47 KiB       3  [emitted]  entry1
                        entry2.bundle.js   1.47 KiB       4  [emitted]  entry2
Entrypoint entry1 = default~entry1~entry2~100271bb.bundle.js default~entry1~14905de4.bundle.js entry1.bundle.js
Entrypoint entry2 = default~entry1~entry2~100271bb.bundle.js default~entry2~f28393c0.bundle.js entry2.bundle.js
[0] ./src/modules/add.js 1.92 KiB {0} [built]
[1] ./src/entry/entry1.js 65 bytes {1} [built]
[2] ./src/entry/entry2.js 65 bytes {2} [built]

那麼如果將maxSize減1呢,也就是add.js的體積大小會大於maxSize,我們的正常邏輯思想是add.js不會被打包出來,但是結果確實和上面一樣的結果。

於是我們翻看官方文檔看看:

tells webpack to try to split chunks bigger than maxSize bytes into smaller parts.(用於告訴webpack試圖將大於maxSize的chunk拆分成更小的部分。)

這個是官方文檔中的一句話,所以我在想,正常情況下,拆分的chunk如果包含多個模塊,那麼當maxSize設爲比這個chunk小時,這個chunk會不會被拆分成多個模塊呢。

  1. demo6
################################
webpack.config.js:

splitChunks.maxSize設爲0
splitChunks.minSize設爲1

################################
modules/add.js:(實際測試時通過註釋使得文件大小增大)

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
entry/entry1.js:

import add from '../modules/add'
import subtract from '../modules/subtract'

console.log('index', add(1, 2) + subtract(3, 0))

################################
entry/entry2.js:

console.log('index', 1)

打包後結果爲:

Hash: 03737457923b3e2fc080
Version: webpack 4.41.5
Time: 207ms
Built at: 2020/02/01 上午10:56:53
                   Asset       Size  Chunks             Chunk Names
default~entry1.bundle.js  154 bytes       0  [emitted]  default~entry1
default~entry2.bundle.js   98 bytes       1  [emitted]  default~entry2
        entry1.bundle.js   1.47 KiB       2  [emitted]  entry1
        entry2.bundle.js   1.47 KiB       3  [emitted]  entry2
Entrypoint entry1 = default~entry1.bundle.js entry1.bundle.js
Entrypoint entry2 = default~entry2.bundle.js entry2.bundle.js
[0] ./src/entry/entry2.js 96 bytes {1} [built]
[1] ./src/entry/entry1.js + 2 modules 2.1 KiB {0} [built]
    | ./src/entry/entry1.js 125 bytes [built]
    | ./src/modules/add.js 1.92 KiB [built]
    | ./src/modules/subtract.js 59 bytes [built]

default~entry1.bundle.js包含了add.js和subtract.js。

如果把maxSize設置爲10呢,結果如何?

結果如下:

Hash: 798f35edfa0accbcef6c
Version: webpack 4.41.5
Time: 75ms
Built at: 2020/02/01 上午11:07:06
                            Asset       Size  Chunks             Chunk Names
default~entry1~100271bb.bundle.js  151 bytes       0  [emitted]  default~entry1~100271bb
default~entry1~14905de4.bundle.js  172 bytes       1  [emitted]  default~entry1~14905de4
default~entry1~b912b7e2.bundle.js  152 bytes       2  [emitted]  default~entry1~b912b7e2
default~entry2~f28393c0.bundle.js  100 bytes       3  [emitted]  default~entry2~f28393c0
                 entry1.bundle.js   1.47 KiB       4  [emitted]  entry1
                 entry2.bundle.js   1.47 KiB       5  [emitted]  entry2
Entrypoint entry1 = default~entry1~14905de4.bundle.js default~entry1~100271bb.bundle.js default~entry1~b912b7e2.bundle.js entry1.bundle.js
Entrypoint entry2 = default~entry2~f28393c0.bundle.js entry2.bundle.js
[0] ./src/modules/add.js 1.92 KiB {0} [built]
[1] ./src/modules/subtract.js 59 bytes {2} [built]
[2] ./src/entry/entry1.js 125 bytes {1} [built]
[3] ./src/entry/entry2.js 96 bytes {3} [built]

可以看到原來的default~entry1.bundle.js又另外單獨拆分除了add.js和subtract.js。

擴展

之前的案例中我們發現只要應用了maxSize配置(maxSize配置爲非0數值並且打包成功),那麼被拆分出來的bundle文件名都包含了隨機串的某個後綴,如上面的~100271bb。

這個隨機串是什麼?

When the chunk has a name already, each part will get a new name derived from that name. Depending on the value of optimization.splitChunks.hidePathInfo it will add a key derived from the first module name or a hash of it.

意思大概是這樣的:如果不受maxSize影響,拆分的chunk已經有一個名字name。而當我們應用了maxSize時,基於原來chunk拆分出來的bundle,它們的名稱將基於name進行派生,原理是webpack會基於splitChunks.hidePathInfo生成一個key(基於模塊名或者模塊的hash派生),這個key會被添加進name中,這個key個人猜測就是之前案例中的~100271bb,它或許是對應的bundle生成的hash值的前幾位數字或字符。

總結

  • minSize表示被拆分出的bundle在拆分之前的體積的最小數值,只有 >= minSize 的bundle會被拆分出來;
  • maxSize表示被拆分出的bundle在拆分之前的體積的最大數值,默認值爲0,表示bundle在拆分前的體積沒有上限;
  • maxSize如果爲非0值時,切忌小於minSize;
  • 如果bundle在被拆分前的體積大於maxSize,webpack將會嘗試將它拆分成更小的模塊(前提是bundle在拆分之前由多個模塊組成,如果僅僅只包含一個模塊,大於maxSize和大於minSize小於等於maxSize是一樣的效果);
  • 應用maxSize打包的bundle其名稱會由“不應用maxSize時產生的bundle名稱”和“一個生成的key值”組成;
  • maxSize對於直接引入(import或require引入)的部分或者按需引入的部分都有效,不過有些許區別,按需引入的包如果被拆分則使用chunk的名稱作爲bundle名,不會像前面的案例那樣包含一些key,如果非按需引入的部分包含於入口點名稱構建的bundle時,該bundle名稱將包含前面案例中類似的key;
  • minSize對於按需引入的部分是沒有效的,因爲無論在什麼情況下,按需引入的部分都會被拆分打包出來;

last(最後)
非常感謝您能閱讀完這篇文章,您的閱讀是我不斷前進的動力。如果上述內容或許有些錯誤或者有些個人理解比較偏離實際,還望指出,謝謝!!!

對於上面所述,有什麼新的觀點或發現有什麼錯誤,希望您能指出。

最後,附上個人常逛的社交平臺:
知乎:https://www.zhihu.com/people/bi-an-yao-91/activities
csdn:https://blog.csdn.net/YaoDeBiAn
github: https://github.com/yaodebian

個人目前能力有限,並沒有自主構建一個社區的能力,如有任何問題或想法與我溝通,請通過上述某個平臺聯繫我,謝謝!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章