最初,chunks(以及内部导入的模块)是通过内部 webpack 图谱中的父子关系关联的。CommonsChunkPlugin
曾被用来避免他们之间的重复依赖,但是不可能再做进一步的优化。
从 webpack v4 开始,移除了 CommonsChunkPlugin
,取而代之的是 optimization.splitChunks
。
optimization.splitChunks
下面这个配置对象代表 SplitChunksPlugin
的默认行为。
webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',//三选一:"initial" 初始化,"all"(默认就是all),"async"(动态加载)
minSize: 20000,//当导入的模块最小是多少字节才会进行代码分割
minRemainingSize: 0,//解析见代码下面的文字说明,不用设置
minChunks: 1,//当一个模块被导入(引用)至少多少次才对该模块进行代码分割
maxAsyncRequests: 30,//按需加载时的最大并行请求数
maxInitialRequests: 30,//入口点的最大并行请求数
enforceSizeThreshold: 50000,//解析见代码下面的文字说明,不用设置
cacheGroups: {//缓存组,这里是我们表演的舞台,抽取公共模块什么的,都在这个地方
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,//优先级
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
chunks:
all 模式下,入口文件和动态引入文件都会进行打包
initial 模式下,会将入口文件中的依赖包重新切割为一个新的文件,其它文件中动态引入的不会进行拆分,和async有点相反。
minRemainingSize:
在 webpack 5 中引入了 splitChunks.minRemainingSize
选项,通过确保拆分后剩余的最小 chunk 体积超过限制来避免大小为零的模块。 'development' 模式 中默认为 0
。对于其他情况,splitChunks.minRemainingSize
默认为 splitChunks.minSize
的值,因此除需要深度控制的极少数情况外,不需要手动指定它。
enforceSizeThreshold:
强制执行拆分的体积阈值和其他限制(minRemainingSize,maxAsyncRequests,maxInitialRequests)将被忽略。
cacheGroups
缓存组,这里是我们表演的舞台,抽取公共模块什么的,都在这个地方
priority:优先级,只配置在缓存组的每一项,决定执行的顺序。
minChunks:最小块,即当块的数量大于等于minChunks时,才起作用
minSize:最小大小,即当抽取的公共模块的大小,大于minSize所设置的值,才起作用
maxSize:如果引入的包大小已经超过了设置的最大值,那么webpack会尝试对该包再进行分割
test:匹配规则,说明要匹配的项
开始表演(直接上配置):
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
name: "vendor",//打包后的文件名
test: /[\\/]node_modules[\\/]/,
chunks: "all",
priority: 10
},
common: {
name: "common",
test: /[\\/]src[\\/]/,
minSize: 1024,
chunks: "all",
priority: 5
}
}
}
},
};
这里我配置了两个缓存组,即 vendor
和 common
vendor
: 抽取来自node_modules
文件夹下的第三方代码,优先级权重为10common
: 抽取来自src
文件夹下的代码,优先级权重为5vendor
比common
的优先级权重高,所以先提取vendor
,再提取common
打包
做好以上配置之后,打包的结果如下:
- 在入口文件引用的第三方文件,被打包到
vendor.js
- 在入口文件引用到的公共文件,被打包到
common.js
注:以上这种配置。实际场景这样设置,打出来的js会很大的。
实际中:
cacheGroups: {
common: {
name: 'chunk-common', // 打包后的文件名
chunks: 'initial',
minChunks: 2,
maxInitialRequests: 5,
minSize: 0,
priority: 1,
reuseExistingChunk: true//当已经存在分割时,使用已经存在且分割好的模块
},
vendors: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
chunks: 'initial',
maxSize: 600000,
maxInitialRequests: 20,
priority: 2,
reuseExistingChunk: true,
enforce: true
},
antDesignVue: {
name: 'chunk-ant-design-vue',
test: /[\\/]node_modules[\\/]ant-design-vue[\\/]/,
chunks: 'initial',
priority: 3,
maxSize: 600000,
reuseExistingChunk: true,
enforce: true
}
}
补充:
cacheGroups: {
// 匹配到是引入的node_modules中的模块时,打包后会将它分割到vendors.js文件内
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10, //优先级,主要是当模块引入符合多个规则时,根据优先级进行代码分割
filename: 'vendors.js', //分割组文件名。splitChunks中可以设置name:true/false,此设置是设置的分组文件名是否生效,即filename是否有效
},
// 当以上规则都没有匹配到时,进行兜底分割配置
default: {
priority: -20,
reuseExistingChunk: true, //当已经存在分割时,使用已经存在且分割好的模块
filename: 'common.js'
}
}