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

个人目前能力有限,并没有自主构建一个社区的能力,如有任何问题或想法与我沟通,请通过上述某个平台联系我,谢谢!!!

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值