为什么要进行 Chunks 优化
众所周知,在 webpack 中对 chunks 有一项非常重要的优化措施,在 webpack 4 以上,这个东西叫做 SplitChunkPlugin, 在 webpack 3 中这个东西叫做 CommonsChunkPlugin
首先我们先问一个问题,为什么要对 chunks 进行切分优化,我们先来看没有任何切分优化的场景
从上图看出页面 a 和页面 b 都引用了组件 b,并被同时打包进了页面 a 和 页面 b 的 chunks(1.js 和 2.js) 中,很明显我们打包了重复的模块,该打包模式至少有两个问题:
- 重复模块增大了 chunks 的体积,不仅浪费了用户流量,也降低了首屏速度
- 模块更新会导致包含它的所有 chunks 缓存都失效,如果发版比较频繁,缓存利用率会很低,严重影响首屏速度
下面我们引入 SplitChunkPlugin 插件对 chunks 进行优化
从上图看出我们将公共组件 b 从页面 a 和 b 的 chunks(1.js 和 3.js) 中抽离出来了,构成了一个单独的 chunk(2.js),这样就解决了上面两个问题,从而提高了首屏速度
以上只是一个简单的例子用来说明 SplitChunkPlugin 的主要用途,即在不同的 chunks 之间找出它们所包含的相同模块,并把这些模块从原来的 chunks 中抽取出来,组成另一个 chunk,也就是说我们的目标就是 deduplicate(去重) chunks 中的模块
如何进行 Chunks 优化
在 webpack 中,模块和 chunks 是多对多的关系,一个模块可以被打包在多个 chunks 中,一个 chunk 也可以包含多个模块,那么是否做到极限去重就是最佳的优化策略呢?
我们先定义什么是"极限去重":最终生成的任意一个 chunk 所包含的模块仅在该 chunk 中,也就是说,任意两个 chunk 都不包含相同的模块
极限去重的最大优势是不会产生冗余代码,是解决问题 1 的最佳方案,但它也产生了另外的问题:
在最坏的情况下,假设现有 n 个 chunks 需要优化,根据排列组合,最终会产生 C n n + C n n − 1 + . . . + C n 2 + C n 1 C_n^n + C_n^{n-1} + ... + C_n^2 + C_n^1 Cnn+Cn