Webpack 4 splitChunks 插件配置详解与实战避坑指南

作者:构建工坊时间:2026-10-22 17:54:33浏览:412

本文深入解析 Webpack 4 中 splitChunks 插件的核心参数与配置策略。通过多个实战案例,详细演示如何利用 cacheGroups 进行模块复用、第三方库分离及动态引入处理。重点剖析生产模式下打包异常的原因,并提供手动配置缓存组以解决 vendor 合并问题的具体方案,帮助开发者掌握高效的代码分割技巧。

引言与初衷

初衷

Webpack 4 发布已有数月,观察发现包括作者在内,许多开发者对 splitChunks 插件的使用仍处于探索阶段。作者查阅了大量他人的配置示例,但大多未能完全满足需求或解决疑惑,相关 Issue 下也鲜有回复,因此决定通过实际测试进行记录与总结。若读者有更优方案,欢迎在评论区分享。

splitChunks 核心参数解析

常用参数

  • minSize(默认值 30000):定义生成新代码块所需的最小体积阈值。
  • minChunks(默认值 1):指定代码块在分割前被引用的最小次数。该参数旨在保证代码块的复用性,默认策略下即使仅被引用一次也可被分割。
  • maxInitialRequests(默认值 3):限制一个入口点允许的最大并行请求数量。
  • maxAsyncRequests(默认值 5):限制按需加载(异步加载)时的最大并行请求数量。
  • chunks(默认值 async):可选值为 initial、async 和 all。
  • test:用于筛选匹配该缓存组的模块。若不传递特定值,默认匹配所有模块。支持传入 RegExp、String 或 Function 类型。
  • name:指定打包后 chunks 的名称,可接受字符串或根据条件自定义名称的函数。
  • priority:定义缓存组打包的优先级顺序。

若对上述配置仍感陌生,建议查阅官方文档以获取更详尽的解释。

正文

基础配置与模块复用示例

首先总览所有配置项,随后将通过具体 Demo 演示常见需求的处理流程。


optimization: {
 splitChunks: {
  chunks: "async", // 必须三选一: "initial" | "all"(推荐) | "async" (默认就是async)
  minSize: 30000, // 最小尺寸,30000
  minChunks: 1, // 最小 chunk ,默认1
  maxAsyncRequests: 5, // 最大异步请求数, 默认5
  maxInitialRequests : 3, // 最大初始化请求书,默认3
  automaticNameDelimiter: '~',// 打包分隔符
  name: function(){}, // 打包后的名称,此选项可接收 function
  cacheGroups:{ // 这里开始设置缓存的 chunks
   priority: 0, // 缓存组优先级
   vendor: { // key 为entry中定义的 入口名称
    chunks: "initial", // 必须三选一: "initial" | "all" | "async"(默认就是async) 
    test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
    name: "vendor", // 要缓存的 分隔出来的 chunk 名称 
    minSize: 30000,
    minChunks: 1,
    enforce: true,
    maxAsyncRequests: 5, // 最大异步请求数, 默认1
    maxInitialRequests : 3, // 最大初始化请求书,默认1
    reuseExistingChunk: true // 可设置是否重用该chunk
   }
  }
 }
 },

接下来分析第一个示例。


entry: {
		pageA: "./pageA", // 引用utility1.js utility2.js
		pageB: "./pageB", // 引用utility2.js utility3.js
		pageC: "./pageC" // 引用utility2.js utility3.js
	},
	
	optimization: {
		splitChunks: {
			cacheGroups: {
				commons: {
					chunks: "initial",
					minChunks: 2,
					maxInitialRequests: 5, // The default limit is too small to showcase the effect
					minSize: 0 // This is example is too small to create commons chunks
				}
			}
		}
	},

结果如图所示,运行正常。文件 commons~pageA~pageB~pageC.js 对应 utility2.js,commons~pageB~pageC.js 对应 utility3.js。根据配置,utility2 被引用三次,因此首先被抽离至 commons~pageA~pageB~pageC.js;utility3 被引用两次,放入 commons~pageB~pageC.js;剩余仅被引用一次的 utility1.js 则直接归入 pageA.js。需注意,若 utility1.js 也被引用两次,它仍会新建一个 chunk 而非合并至 commons~pageB~pageC.js,除非它们属于同一入口才会合并。

mpageA.js pageB.js pageC.js

引言与初衷

此处存在一个优化点:pageA.js、pageB.js 和 pageC.js 代码量虽少,但打包体积较大,这通常是由于 Webpack 运行时文件所致。可通过添加 runtimeChunk 配置来解决。


 runtimeChunk: "single"
 // 等价于
 runtimeChunk: {
  name: "manifest"
 }

添加后效果改善。

引言与初衷

第三方库分离与生产环境避坑

接着处理第三方模块引用:pageA 引入 vue.js,pageB 引入 react 和 react-dom。


vendor: {
		test: /node_modules/,
		chunks: "initial",
		name: "vendor",
		priority: 10,
		enforce: true
	}

然而,上述配置会导致 pageA、pageB 和 pageC 的所有库被打包至同一个 vendor.js 文件中。

引言与初衷

若希望将 vendor.js 拆分为 pageA-vendor.js 和 pageB-vendor.js,经过多次尝试,发现最简单的方法是移除手动指定的 vendor 配置,交由插件自动处理。


splitChunks: {
  chunks: "all",
  cacheGroups: {
				commons: {
					chunks: "initial",
					minChunks: 2,
					maxInitialRequests: 5, // The default limit is too small to showcase the effect
					minSize: 0 // This is example is too small to create commons chunks
				}
			}
		},

引言与初衷

随后将 webpack mode 改为 production 模式,发现相同配置下打包结果异常:vendor-pageB.js 被合并到了 pageB.js 内部。

引言与初衷

经过长时间排查仍无法确定原因,最终采取手动配置方式,放弃部分自动化处理。


 commons: {
   chunks: "initial",
   minChunks: 2,
   maxInitialRequests: 5, // The default limit is too small to showcase the effect
   minSize: 0 // This is example is too small to create commons chunks
	},
  'vendor-pageA': {
   test: /vue/, // 直接使用 test 来做路径匹配
   chunks: "initial",
   name: "vendor-pageA",
   enforce: true,
  },
  'vendor-pageB': {
   test: /react/, // 直接使用 test 来做路径匹配
   chunks: "initial",
   name: "vendor-pageB",
   enforce: true,
  },

成功打包出预期结果。

引言与初衷

动态引入与懒加载处理

动态引入

动态引入即常说的懒加载。在 pageA 和 pageB 中直接动态引入 common-async.js。此处推测 splitChunks 应能自动处理类似 commonChunk 中 async 或 child 类型的情况。


import(/* webpackChunkName: "common-async.js" */"./common-async").then(common => {
 console.log(common);
})

结果良好,成功打包。

引言与初衷

进一步测试:在 common-async.js 中引入共同代码 f.js,观察是否会出现重复打包。

引言与初衷

f.js 成功被抽离,其他文件未重复打包,效果良好。

引言与初衷

配置注意事项与建议

注意的地方

  • cacheGroups 会继承并覆盖 splitChunks 的配置项,但 test、priority 和 reuseExistingChunk 仅能用于配置缓存组。
  • 建议 cacheGroups 中的每一项都明确添加 chunks 参数,否则可能导致打包结果不符合预期。
  • minSize 默认值为 30KB(注意这是压缩前的体积)。若模块小于 30KB,必须显式设置一个值,否则可能无法打包出预期结果,且该设置需置于 cacheGroups 内部。
  • priority 在特定情况下非常有用,可用于设定打包 chunks 的优先级。

上述示例中配置了一个名为 commons 的组,其 name 属性可设置也可省略。作者未设置,建议读者尝试设置后的效果,从而理解在某些情况下不设置 name 更为合适。


 commons: {
   	chunks: "initial",
		minChunks: 2,
		maxInitialRequests: 5, // The default limit is too small to showcase the effect
		minSize: 0 ,
		name: "commons"
  },

源码

代码分割

代码懒加载

参考文章

webpack文档 官方demo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

作者最新文章
相关文章
更多