webpack的chunk生成逻辑 - SegmentFault 思否
source link: https://segmentfault.com/a/1190000040955485
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
webpack的chunk生成逻辑
刚接触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
决定了生成的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的其他文章:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK