Skip to content

webpack 默认分包策略

主要是关于 SplitChunksPlugin 的分包策略,SplitChunksPlugin 通过 module 被引用频率、chunk 大小、包请求数三个维度决定是否执行分包操作,这些决策都可以通过 optimization.splitChunks 配置项调整定制,基于这些维度可以实现单独打包某些特定路径的内容

SplitChunksPlugin 内置了 default 与 defaultVendors 两个配置组,提供一些开箱即用的特性:

  1. node_modules 资源会命中 defaultVendors 规则,并被单独打包
  2. 只有包体超过 20kb 的 Chunk 才会被单独打包
  3. 加载 Async Chunk 所需请求数不得超过 30
  4. 加载 Initial Chunk 所需请求数不得超过 30

知识点:Webpack 内部包含三种类型的 Chunk:

  • Initial Chunk:基于 Entry 配置项生成的 Chunk
  • Async Chunk:异步模块引用,如 import(xxx) 语句对应的异步 Chunk
  • Runtime Chunk:只包含运行时代码的 Chunk

根据 Module 使用频率

SplitChunksPlugin 支持按 Module 被 Chunk 引用的次数决定是否进行分包,开发者可通过 optimization.splitChunks.minChunks 设定最小引用次数

注意,这里“被 Chunk 引用次数”并不直接等价于被 import 的次数,而是取决于上游调用者是否被视作 Initial Chunk 或 Async Chunk 处理

根据 请求数量分包

在满足 minChunks 基础上,还可以通过 maxInitialRequest/maxAsyncRequests 配置项限定分包数量,配置项语义:

  • maxInitialRequest:用于设置 Initial Chunk 最大并行请求数
  • maxAsyncRequests:用于设置 Async Chunk 最大并行请求数

这里所说的“请求数”,是指加载一个 Chunk 时所需同步加载的分包数。 例如对于一个 Chunk A,如果根据分包规则(如模块引用次数、第三方包)分离出了 i 个子 Chunk, 那么请求 A 时,浏览器需要同时请求所有的子 Chunk,此时并行请求数等于 ¡ 个分包加 A 主包,即 ¡+1

并行请求数关键逻辑总结如下:

  • Initial Chunk 本身算一个请求
  • Async Chunk 不算并行请求
  • 通过 runtimeChunk 拆分出的 runtime 不算并行请求
  • 如果同时有两个 Chunk 满足拆分规则,但是 maxInitialRequests(或 maxAsyncRequest) 的值只能允许再拆分一个模块,那么体积更大的模块会被优先拆解

根据 体积分包

在满足 minChunks 与 maxInitialRequests 的基础上,SplitChunksPlugin 还会进一步判断 Chunk 包大小决定是否分包

  • minSize:超过这个尺寸的 Chunk 才会正式被分包
  • maxSize:超过这个尺寸的 Chunk 会尝试继续做分包
  • maxAsyncSize:与 maxSize 功能类似,但只对异步引入的模块生效
  • maxInitialSize:与 maxSize 类似,但只对 entry 配置的入口模块生效
  • enforceSizeThreshold:超过这个尺寸的 Chunk 会被强制分包,忽略上述其它 size 限制

使用 cacheGroups

plitChunksPlugin 提供了 cacheGroups 配置项用于为不同文件组设置不同的规则

  • test:接受正则表达式、函数及字符串,所有符合 test 判断的 Module 或 Chunk 都会被分到该组
  • type:接受正则表达式、函数及字符串,与 test 类似均用于筛选分组命中的模块,区别是它判断的依据是文件类型而不是文件名,例如 type = 'json' 会命中所有 JSON 文件
  • idHint:字符串型,用于设置 Chunk ID,它还会被追加到最终产物文件名中,例如 idHint = 'vendors' 时,输出产物文件名形如 vendors-xxx-xxx.js
  • priority:数字型,用于设置该分组的优先级,若模块命中多个缓存组,则优先被分到 priority 更大的组
js
// 通过 cacheGroups 属性设置 vendors 缓存组,
// 所有命中 vendors.test 规则的模块都会被视作 vendors 分组,
// 优先应用该组下的 minChunks、minSize 等分包配置
module.exports = {
  //...
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          minChunks: 1,
          minSize: 0,
        },
      },
    },
  },
};

参考文献

https://www.51cto.com/article/689344.html

Released under the MIT License.