Webpack 4.0 CommonsChunkPlugin 和 optimization splitChunks

该文章内容大体翻译自 webpack 4: Code Splitting, chunk graph and the splitChunks optimization

原有的问题

webpack 4.0 对代码模块的关系图进行了一些巨大的优化,同时添加了一个新的 optimization 用于模块的分离(能够看作是对 CommonsChunkPlugin 的一次优化)。vue

先让咱们看看旧版关系图的一些缺陷。node

在以前的版本中,咱们将各个模块打包进编译后的文件之中,同时这些文件之间又是经过父子关系来进行关联,最后将咱们整个项目中的全部模块串联起来。react

当其中一个文件含有父级引用,那咱们能够推断出,在该文件完成加载时,已经成功加载了父级文件。那么咱们能够据此进行一些优化。好比当一个文件中的模块已经在父级文件中正常运行,那么咱们能够将该模块从文件中移除,由于它必然已经被成功加载。webpack

在入口点或异步拆分点处引用这些文件。这些文件将会并行加载。web

这种类型的关系图使得分离splitting变得很是困难。好比在你使用CommonsChunkPlugin插件时。会有一个或多个文件内模块被移动到新的文件中来。这一整个新文件须要被添加到关系图中来。但咱们应该如何设置它的层级呢?做为旧有文件的父级?仍是子级?CommonsChunkPlugin中将其设置为父级,但从技术层面来讲,这是错误的,而且致使了一些负面的优化结果(提早加载的这个文件中的部分模块不是必需的)。缓存

如今新的关系图中,引入了一个新概念:ChunkGroup。包含文件列表的文件分组。app

在入口点或异步拆分点处咱们会引用这个文件分组,该分组内的文件全都是并行加载。而一个文件能够被多个文件分组引用(但不会屡次加载)。dom

如今再也不使用父子级的关系来描述文件之间的联系,取而代之的是文件分组ChunkGroup异步

那么此时,splitting文件就可以被表述出来。被建立的新文件能够被添加到全部包含原始文件的文件分组中。同时也不会所以产生负面优化效果。优化

CommonsChunkPlugin和SplitChunksPlugin的区别

这个问题被修复以后,咱们能够更多的使用文件拆分了。咱们能够将任何文件拆分出来而且不须要提升其加载优先级。

CommonsChunkPlugin存在如下这些问题:

  • 须要下载当前还不须要使用的代码文件。
  • 异步加载使用文件效率低下。
  • 很难使用。(猜想这里指的是配置)
  • 实现方式很难理解。

因此新的插件诞生了:SplitChunksPlugin

它会使用模块引用计数和模块类别区分(好比:node_modules)来自动分离出须要被拆分的文件内引用模块。

There is a paradigm shift here. The CommonsChunkPlugin was like: “Create this chunk and move all modules matching minChunks into the new chunk”. The SplitChunksPlugin is like: “Here are the heuristics, make sure you fullfil them”. (imperative vs declarative)
这里没有理解所有的内容。

SplitChunksPlugin同时提供了更多的特性:

  • 不会加载非必须文件(除非进行了强制合并)
  • 异步文件处理更有效率。
  • 默认异步处理文件。
  • 它将引用模块分散到多个库文件中。
  • 更容易使用。
  • 不依赖文件引用关系图。
  • 更加的自动化。

例子

下面是一些使用SplitChunksPlugin的例子。这些用例仅仅展示了它在默认配置下的行为。你也可使用额外配置项来进行个性化定制。

提示:

  1. 能够经过optimization.splitChunks进行配置。这里的例子是关于文件的,默认状况下仅适用于异步加载的文件块。但也能够添加optimization.splitChunks.chunks: "all"来配置适用于全部类型的文件。
  2. 咱们假定每一个额外导入的库文件都大于30kb,由于优化仅在该体积以后开始进行。(能够经过配置minSize属性进行修改,默认 30000)

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将会自动建立2个库文件:

  • vendors~chunk-a~chunk-b: react, react-dom
  • vendors~chunk-c~chunk-d: angular
  • chunk-a chunk-b chunk-c chunk-d: 含有components

Vendors overlapping

  • 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依然会建立2个库文件:

  • vendors~chunk-a~chunk-b~chunk-c: react, react-dom
  • vendors~chunk-b~chunk-c: lodash
  • chunk-a chunk-b chunk-c: 含有components

Shared modules

  • 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

假设全部的shared components体积都大于 30kb,webpack将会建立一个库文件和一个通用组件文件:

  • vendors~chunk-a~chunk-b~chunk-c: vue
  • commons~chunk-a~chunk-b~chunk-c: some shared components
  • chunk-a chunk-b chunk-c: 含有components

当这些shared components体积小于30kb是,webpack会故意将该模块复制到chunk-a chunk-b chunk-c三个文件中。咱们认为进行分离所减少的加载体积的总体效果并不如一次额外的加载请求的消耗。

Multiple shared modules

  • 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将会建立2个库文件及2个通用组件文件

  • 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 chunk-b chunk-c chunk-d: Only the components

提示:由于生成的导入文件名称包含全部的原始文件名称,因此咱们推荐在生产环境中使用的长效缓存文件不要包含[name]在文件名中,或者设置optimization.splitChunks.name: false来关闭文件名生成逻辑。这样即便在后续开发中对该文件添加了新的引用,也不会修改文件名,该缓存逻辑依然生效。

相关文章
相关标签/搜索