该文章内容大体翻译自 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
。
它会使用模块引用计数和模块类别区分(好比: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
的例子。这些用例仅仅展示了它在默认配置下的行为。你也可使用额外配置项来进行个性化定制。
提示:
optimization.splitChunks
进行配置。这里的例子是关于文件的,默认状况下仅适用于异步加载的文件块。但也能够添加optimization.splitChunks.chunks: "all"
来配置适用于全部类型的文件。minSize
属性进行修改,默认 30000)chunk-a
: react, react-dom, some componentschunk-b
: react, react-dom, some other componentschunk-c
: angular, some componentschunk-d
: angular, some other componentswebpack将会自动建立2个库文件:
vendors~chunk-a~chunk-b
: react, react-domvendors~chunk-c~chunk-d
: angularchunk-a chunk-b chunk-c chunk-d
: 仅含有componentschunk-a
: react, react-dom, some componentschunk-b
: react, react-dom, lodash, some other componentschunk-c
: react, react-dom, lodash, some componentswebpack依然会建立2个库文件:
vendors~chunk-a~chunk-b~chunk-c
: react, react-domvendors~chunk-b~chunk-c
: lodashchunk-a chunk-b chunk-c
: 仅含有componentschunk-a
: vue, some components, some shared componentschunk-b
: vue, some other components, some shared componentschunk-c
: vue, some more components, some shared components假设全部的shared components
体积都大于 30kb,webpack将会建立一个库文件和一个通用组件文件:
vendors~chunk-a~chunk-b~chunk-c
: vuecommons~chunk-a~chunk-b~chunk-c
: some shared componentschunk-a chunk-b chunk-c
: 仅含有components当这些shared components
体积小于30kb是,webpack会故意将该模块复制到chunk-a chunk-b chunk-c
三个文件中。咱们认为进行分离所减少的加载体积的总体效果并不如一次额外的加载请求的消耗。
chunk-a
: react, react-dom, some components, some shared react componentschunk-b
: react, react-dom, angular, some other componentschunk-c
: react, react-dom, angular, some components, some shared react components, some shared angular componentschunk-d
: angular, some other components, some shared angular componentswebpack将会建立2个库文件及2个通用组件文件
vendors~chunk-a~chunk-b~chunk-c
: react, react-domvendors~chunk-b~chunk-c~chunk-d
: angularcommons~chunk-a~chunk-c
: some shared react componentscommons~chunk-c~chunk-d
: some shared angular componentschunk-a chunk-b chunk-c chunk-d
: Only the components
提示:由于生成的导入文件名称包含全部的原始文件名称,因此咱们推荐在生产环境中使用的长效缓存文件不要包含[name]
在文件名中,或者设置optimization.splitChunks.name: false
来关闭文件名生成逻辑。这样即便在后续开发中对该文件添加了新的引用,也不会修改文件名,该缓存逻辑依然生效。