刚接触webpack时,使用webpack打包后只会生成一个被称为bundle的文件,在慢慢熟悉webpack后,如果同时对于前端优化有一定的了解,就会尝试将臃肿的bundle拆分成多个小文件并按需加载。
本文希望通过对webpack的部分配置进行说明,让读者对相关的操作有一定了解和掌握。以下操作均是在webpack@4环境下的说明。
webpack中通过配置的optimization.splitChunks
来实现这样的效果,该配置也是SplitChunksPlugins
插件的配置。
webpack为optimization.splitChunks
提供了默认值,让我们来看看:
//
// ** 默认的splitChunks内容 **
//
{
chunks: 'async',
minSize: 30000,
maxSize: 0,
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
}
}
};
让我们来仔细看看其中的配置
chunks
通过配置该项,开发者可以选择需要进行优化的chunk,被选中的chunk,其中的modules将被分析,并按照一定的策略生成新的chunk。
允许all
、async
、initial
、(chunkname) => boolean
四种值,具体效果如下:
- initial: 所有的立即加载的chunk(例如bundle文件)将被检查
- async: 所有延迟加载的chunk将被检查
- all: 等价于
initial
+async
效果,所有的chunk都将被检查 - (chunkname) => boolean: 函数形式可以提供更细粒度的控制
默认情况为async
,所以我们的bundle不会被优化,这里可以尝试修改为initial
之后再进行一次编译。
{
chunks: 'initial',
}
除了生成bundle之外,可能还会有名为vendors~xxx.js
的文件。(如果没有生成的话,可以尝试在代码中引入node_modules
中的包,再重新编译后查看结果。)
两次编译结果的变化,即chunks
从async
变为initial
后,bundle文件
因作为一个立即加载的chunk而被优化了。
minSize、maxSize
见名知意,minSize
和maxSize
限定了新生成的chunk的文件的最小/最大尺寸。只有当准备生成的chunk的最大和最小文件尺寸,只有在这个尺寸内的chunk文件才会被生成,否则代码会保持原样。
minSize=30000
表示chunk最小应该有30000bytes。maxSize=0
表示不限制chunk的最大尺寸。如果设置为一个其他的合理值,例如150000
,生成的chunk超过了maxSize
的情况下,该chunk将被进一步拆分成更小的chunk。
cacheGroups
cacheGroups是splitChunks配置的一个关键配置,其决定了module
应该如何合并成一个新的chunk。
{
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
}
在cacheGroups
配置下的每一个对象,都可以认为是一个cacheGroup
,例如上面的代码中是key为vendors
的对象。
cacheGroup.test
test
用于对所有的module
进行筛选,筛选过的module将被放入这个cacheGroup
所对应的chunk文件中。上例中通过[\\/]node_modules[\\/]
对于module
的路径进行测试,最终所有的node_modules路径
下的模块都将放在vendors
这个chunk下,这也是上面生成vendors~xxx.js
的原因。
cacheGroup.priority
定义cacheGroup
的优先级。因为对于每个module
来说,有可能同时匹配了多个cacheGroup
的test
规则,此时就需要根据优先级来决定需要放到哪个cacheGroup
中。
name
name
决定了生成的chunk文件的名字。默认为true
情况下,生成的名字格式为为cacheGroup名字~chunk1名字~chunk2名字.js
,其中chunk1名字
和chunk2名字
是因为这个cacheGroup
中包含了这两个chunk相关的代码,如果有更多的chunk的话以此类推。
automaticNameDelimiter
可能有细心的读者会注意到上一小节中用于连接chunk名称的~
,其实是automaticNameDelimiter
这个配置项设置的。开发者可以通过该配置项来设置自己想用的连接符。
automaticNameMaxLength
默认情况下,会限制name
小节中的chunk1名字~chunk2名字
部分长度,超出了限制情况下将进行截断。
例如:设为3情况下,vendors-chunk1名字~chunk2名字.js
将变成vendors~chu~21737d60.js
,仅仅保留了长度=3的chu
部分。在出现截断情况下,会在后面补充一段额外的字符,可能是一种避免文件名重复的机制。
minChunks
当和一个cacheGroup
相关的chunk数量超过minChunks
时,新的chunk文件才可以生成。
例如,在默认配置中:
{
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
可能有细心的读者又会问了:现在说的不是splitChunks.minChunks
吗,和cacheGroup.minChunks
有什么关系呢?
其实在splitChunks下的所有配置,在cacheGroup中都会继承或者覆盖。所以对于key为vendors
的cacheGroup来说,其minChunks为1,基本就是不限制,所以node_modules文件夹下的内容都会被放入到vendors
这个chunk。
所以我们知道,key为default
的cacheGroup,其中会放入至少两个chunk所引用的module。如果需要尝试的,可以通过在两个entry所生成的bundle文件中,引用相同的module,之后再打包,应该就会发现该module被放到了名为default~chunk1名字~chunk2名字
这样的文件中。
(至此希望大家已经对于chunk的生成逻辑有了大致的了解。)
一些关于webpack的其他文章: