[译]webpack 4: Code Splitting和chunks切分优化

原文地址: webpack 4: Code Splitting, chunk graph and the splitChunks optimization
原文做者: Tobias Koppers
译者: arzh
推荐理由: 从webpack3升级到webpack4所作的重要更改vue

webpack4chunk图进行了一些重大改进,并为chunk拆分添加了一个新的优化(这是对CommonsChunkPlugin的一种改进)node

让咱们来看看旧版关系图的一些缺点react

在旧图中,chunks经过父子关系和chunks包含模块来链接其余的chunkswebpack

当一个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会被添加到全部包含原始chunkChunkGroups 中,这并不会对父层级关系产生负面影响。

如今这个问题被修复了,咱们就能够开始更多的使用chunk分离了,咱们能够任意拆分chunk而不用担忧chunk图会被破坏

CommonsChunkPlugin有许多的问题:

  1. 会下载一些咱们所不须要的代码
  2. 在异步chunks下是低效率的
  3. 会比较难使用
  4. 实践起来比较难以理解

因此新的插件诞生了:SplitChunksPlugin

它能经过heuristics自动识别应该被分块的模块,使用模块重复计数和模块类别(如node_modules),来分割chunks

这里有一种二者的比喻。CommonsChunkPlugin就像:"建立一个chunk并将匹配minChunks的全部模块移动到新块中",SplitChunksPlugin就像:"这是heuristics,确保你知足他们"(Here are the heuristics, make sure you fullfil them)(命令式与声明式的区别)

SplitChunksPlugin也有一些很棒的属性:

  1. 它永远不会下载不须要的模块(只要你不经过名称强制执行chunk合并)
  2. 在异步chunks下也是高效的
  3. 默认为异步chunks模式分割
  4. 更加容易使用
  5. 不依赖于chunk
  6. 大可能是自动化配置的

如下是SplitChunksPlugin为你列举的几个例子。这些示例仅显示默认行为,附加配置有更多个性化的选择

注意:你能够经过optimization.splitChunks进行配置。这些示例说明了一些关于chunk的内容,默认状况下它只适用于异步chunk,可是使用optimization.splitChunks.chunks:"all"来配置,适用于全部类型的文件(同步、异步chunk

注意:咱们假设此处使用的每一个外部库都大于30kb,由于代码优化仅在超出此大小以后才能生效。

Vendors

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

Vendors重叠

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

假设共享组件的大小大于30kbwebpack将建立一个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关闭名称生成.这样在后续开发中添加了新的引用,也不会变动文件名。

对本文有任何优化建议,可扫描下述二维码一块儿讨论,同时也但愿你们多多关注,会不按期发送一些原创文章

相关文章
相关标签/搜索