splitChunks
一、认识
Webpack
的 optimization.splitChunks
是一个功能强大的配置,用于对代码进行分割(Code Splitting
),从而优化性能、减少文件体积和提高缓存利用率。splitChunks
优势如下:
-
减小主文件体积:将重复代码或第三方依赖抽离,避免多次打包。
-
按需加载:分离不常用的代码,只有在需要时才加载。
-
缓存优化:将变化较少的模块(如库文件)单独提取,提高缓存命中率。
-
加快构建速度:通过分离常用模块,减少每次构建时需要重新处理的代码量。
二、语法
splitChunks
的配置位于 optimization.splitChunks
,可以全局设置,也可以针对不同类型的模块精细化配置。
optimization: {
splitChunks: {
chunks: 'async', // 默认只分割异步加载的代码
minSize: 20000, // 模块最小大小(字节)超过此值才会被分割
minRemainingSize: 0, // 保证剩余入口块的大小
minChunks: 1, // 最少引用次数,满足后才分割
maxAsyncRequests: 30, // 异步请求的最大并发数
maxInitialRequests: 30, // 入口文件的最大并发请求数
enforceSizeThreshold: 50000, // 强制分割的大小阈值
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/, // 匹配 node_modules
priority: -10, // 优先级低于自定义分组
reuseExistingChunk: true, // 复用已存在的块
},
react: {
name: 'react',
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
chunks: 'all',
priority: 30, // 高优先级
},
lodash: {
name: 'lodash',
test: /[\\/]node_modules[\\/](lodash)[\\/]/,
chunks: 'all',
priority: 25, // 次高优先级
},
vendors: {
name: 'vendors',
test: /[\\/]node_modules[\\/]/,
chunks: 'all',
priority: 10, // 最低优先级
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
}
三、配置项
3.1 chunks
chunks
定义分割的代码类型
-
async
:仅分割动态导入的模块(默认)。 -
initial
:仅分割初始加载模块。 -
all
:分割所有模块(推荐,常用)。
语法
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
lodash: {
name: "lodash",
test: /[\\/]node_modules[\\/]lodash[\\/]/,
chunks: "all",
},
vendors: {
chunks: "all",
name: "vendors",
test: /[\\/]node_modules[\\/]/,
},
common: {
chunks: "all",
name: "common",
test: /[\\/]src[\\/]common[\\/]/,
},
},
}
}
3.2 minSize
minSize
模块分割的最小大小(单位:字节)。模块小于这个值时,不会被分割。
语法
optimization: {
splitChunks: {
cacheGroups: {
common: {
minSize: 0,
name: "common",
test: /[\\/]src[\\/]common[\\/]/,
}
},
}
}
3.3 minChunks
minChunks
模块被引用的最少次数,满足这个条件的模块才会被分割。
3.4 cacheGroups
cacheGroups
定义分组规则,决定模块最终的归属和输出文件:
-
test
:匹配的模块路径或名称(支持正则)。 -
name
:输出文件的名称。 -
chunks
: 定义分割的代码类型, ``async**:仅分割动态导入的模块(默认)。**
initial**:仅分割初始加载模块。**
all`:分割所有模块(推荐,常用)。 -
priority
:优先级,数值越大优先级越高。 -
reuseExistingChunk
:如果模块已经存在于某个分组中,其他分组引用时复用,而不是重新打包。如果关闭的话,每个分组都会重新生成模块副本,可能导致重复代码。建议:开启以减少重复代码。主要用于避免生成重复的chunk
,reuseExistingChunk
用于检查是否已经存在可以复用的代码块。如果某些模块已经被打包到某个chunk
中,则复用该chunk
,而不生成新的代码块。
splitChunks.cacheGroups
语法
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
lodash: {
name: "lodash",
test: /[\\/]node_modules[\\/]lodash[\\/]/,
chunks: "all",
priority: 10,
},
vendors: {
chunks: "all",
priority: 9,
name: "vendors",
test: /[\\/]node_modules[\\/]/,
},
common: {
priority: 8,
minSize: 0,
chunks: "all",
name: "common",
test: /[\\/]src[\\/]common[\\/]/,
reuseExistingChunk: true,
},
},
},
}
splitChunks.cacheGroups
构建顺序: 在 Webpack
的 splitChunks.cacheGroups
配置中,最终的构建结果与规则的顺序和优先级有关。cacheGroups
是一个对象,其中的每个键定义了一个分组规则。Webpack
按照以下逻辑决定模块最终分配到哪个分组:
-
priority
属性: 每个分组可以设置priority
,值越高,优先级越高。优先级高的分组会抢先匹配模块。如果模块符合多个分组规则,则分配给优先级最高的分组。 -
定义顺序(当
priority
相同): 如果没有明确指定priority
,则按定义顺序决定优先级,越早定义的分组优先匹配。 -
默认分组: 当模块未被任何分组匹配,或者所有分组的
test
条件都不满足时,模块会归入默认分组(如default
和defaultVendors
)。
splitChunks.cacheGroups
priority
决定归属:
cacheGroups: {
react: {
name: 'react',
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
chunks: 'all',
priority: 25,
},
vendors: {
name: 'vendors',
test: /[\\/]node_modules[\\/]/,
chunks: 'all',
priority: 10,
},
}
react
分组优先级高于 vendors(25 > 10)
,因此 react
和 react-dom
模块会被优先提取到 react.js
,即使它们也符合 vendors
分组规则。
splitChunks.cacheGroups
顺序影响默认行为: 如果没有设置 priority
,Webpack
会按分组的定义顺序匹配:
cacheGroups: {
vendors: {
name: 'vendors',
test: /[\\/]node_modules[\\/]/,
chunks: 'all',
},
react: {
name: 'react',
test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
chunks: 'all',
},
},
在这种情况下,react
和 react-dom
会被 vendors
捕获,因为 vendors
规则定义在前。
splitChunks.cacheGroups
规则冲突时的分组分配: 当多个规则的优先级相同时, 模块会按最后一个规则匹配分组。如果模块被两次以上使用,默认会划分到最通用的分组。
3.5 maxAsyncRequests
maxAsyncRequests
限制异步模块内部并行加载的最大请求数, 也就是每个 import()
里面最大的请求数
3.6 maxInitialRequests
maxInitialRequests
限制初始并行加载的最大请求数 , 也就是说每个 import()
里面最大的请求数
3.7 enforceSizeThreshold
enforceSizeThreshold
3.8 automaticNameDelimiter
automaticNameDelimiter