原文地址: webpack 4: Code Splitting, chunk graph and the splitChunks optimization
原文做者: Tobias Koppers
译者: arzh
推荐理由: 从webpack3
升级到webpack4
所作的重要更改vue
webpack4
对chunk
图进行了一些重大改进,并为chunk
拆分添加了一个新的优化(这是对CommonsChunkPlugin
的一种改进)node
让咱们来看看旧版关系图的一些缺点react
在旧图中,chunks
经过父子关系和chunks
包含模块来链接其余的chunks
webpack
当一个chunk
有多个父节点的话,咱们能够认为当这个chunk
被加载的时候,至少有一个父节点已经被加载了.这个信息能够被用来优化,例如,当一个chunk
的模块,在全部父节点均可用时,它能够从chunk
中被移除,由于它必定已经被成功加载了。web
在入口点或异步拆分点处引用chunk
列表时,这些chunks
会并行加载。缓存
这种类型的关系图使得分离chunks
变得十分困难,例如使用CommonsChunkPlugin
会有这样的问题,当你删除一个或多个chunks
模块,并将它们放在一个新的chunk
中,这个新的chunk
须要被从新链接到关系图中,可是如何链接呢?做为旧的chunk的父级,仍是子级?CommonsChunkPlugin
将其添加为父级,但这在技术上是错误的,同时也会对其余优化产生负面影响(父节点信息是不许确的)dom
新的chunk
图中引入了一个新对象: ChunkGroup
,一个ChunkGroup
包含多个chunk
异步
在入口点或异步拆分点处引用单个ChunkGroup
,这意味着全部被ChunkGroup
包含的chunk
都是并行加载的。一个chunk
能够被引用在多个ChunkGroup
中(但不会被加载屡次)优化
如今就再也不使用父子关系来关联chunk
,而是经过ChunkGroup
来进行关联插件
如今chunks
的分割能够被理解了,新增长的chunks
会被添加到全部包含原始chunk
的ChunkGroups
中,这并不会对父层级关系产生负面影响。
如今这个问题被修复了,咱们就能够开始更多的使用chunk
分离了,咱们能够任意拆分chunk
而不用担忧chunk
图会被破坏
CommonsChunkPlugin
有许多的问题:
chunks
下是低效率的因此新的插件诞生了:SplitChunksPlugin
它能经过heuristics
自动识别应该被分块的模块,使用模块重复计数和模块类别(如node_modules
),来分割chunks
这里有一种二者的比喻。CommonsChunkPlugin
就像:"建立一个chunk
并将匹配minChunks
的全部模块移动到新块中",SplitChunksPlugin
就像:"这是heuristics
,确保你知足他们"(Here are the heuristics, make sure you fullfil them)(命令式与声明式的区别)
SplitChunksPlugin
也有一些很棒的属性:
chunk
合并)chunks
下也是高效的chunks
模式分割chunk
图如下是SplitChunksPlugin
为你列举的几个例子。这些示例仅显示默认行为,附加配置有更多个性化的选择
注意:你能够经过optimization.splitChunks
进行配置。这些示例说明了一些关于chunk
的内容,默认状况下它只适用于异步chunk
,可是使用optimization.splitChunks.chunks:"all"
来配置,适用于全部类型的文件(同步、异步chunk
)
注意:咱们假设此处使用的每一个外部库都大于30kb
,由于代码优化仅在超出此大小以后才能生效。
chunk-a: react
, react-dom
, some components
chunk-b: react
, react-dom
, some other components
chunk-c: angular
, some components
chunk-d: angular
, some other components
webpack将会自动建立两个vendors chunks
,结果以下:
vendors~chunk-a~chunk-b: react
, react-dom
vendors~chunk-c~chunk-d: angular
chunk-a to chunk-d: Only the components
chunk-a: react
, react-dom
, some components
chunk-b: react
, react-dom
, lodash
, some other components
chunk-c: react
, react-dom
, lodash
, some components
webpack也会建立两个vendors chunks
,结果以下:
vendors~chunk-a~chunk-b~chunk-c: react
, react-dom
vendors~chunk-b~chunk-c:lodash
chunk-a to chunk-c: Only the components
chunk-a: vue
, some components
, some shared components
chunk-b: vue
, some other components
, some shared components
chunk-c: vue
, some more components
, some shared components
假设共享组件的大小大于30kb
,webpack
将建立一个vendors chunk
和一个commons chunk
,结果以下:
vendors~chunk-a~chunk-b~chunk-c: vue
commons~chunk-a~chunk-b~chunk-c: some shared components
chunk-a to chunk-c: Only the components
当这些shared components
体积小于30kb
时,webpack
会特地将该模块复制到chunk-a chunk-b chunk-c
三个文件中。他们认为进行分离所减少的加载体积的总体效果并不如一次额外的加载请求的消耗。
chunk-a: react
, react-dom
, some components
, some shared react components
chunk-b: react
,react-dom
, angular
, some other components
chunk-c: react
,react-dom
, angular
, some components
, some shared react components
, some shared angular components
chunk-d: angular
, some other components
, some shared angular components
webpack将建立两个vendors chunk
和两个commons chunk
,结果以下:
vendors~chunk-a~chunk-b~chunk-c: react
, react-dom
vendors~chunk-b~chunk-c~chunk-d: angular
commons~chunk-a~chunk-c: some shared react components
commons~chunk-c~chunk-d: some shared angular components
chunk-a to chunk-d: Only the components
注意:因为chunk
名称包括全部原始chunk
名称,所以建议使用长期缓存的生产版本不包括文件名中的[name]
,或经过optimization.splitChunks.name:false
关闭名称生成.这样在后续开发中添加了新的引用,也不会变动文件名。
对本文有任何优化建议,可扫描下述二维码一块儿讨论,同时也但愿你们多多关注,会不按期发送一些原创文章