原文:RIP CommonsChunkPluginnode
webpack 4 移除 CommonsChunkPlugin
,取而代之的是两个新的配置项(optimization.splitChunks 和 optimization.runtimeChunk),下面介绍一下用法和机制。react
webpack模式模式如今已经作了一些通用性优化,适用于多数使用者。webpack
须要注意的是:默认模式只影响按需(on-demand)加载的代码块(chunk),由于改变初始代码块会影响声明在HTML的script
标签。若是能够处理好这些(好比,从打包状态里面读取并动态生成script标签到HTML),你能够经过设置optimization.splitChunks.chunks: "all"
,应用这些优化模式到初始代码块(initial chunk)。web
webpack根据下述条件自动进行代码块分割:swift
node_modules
文件夹里面为了知足后面两个条件,webpack有可能受限于包的最大数量值,生成的代码体积往上增长。缓存
咱们来看一下一些例子:dom
// entry.js import("./a");
// a.js import "react-dom"; // ...
结果:webpack会建立一个包含react-dom
的分离代码块。当import
调用时候,这个代码块就会与./a
代码被并行加载。async
为何会这样打包:函数
node_modules
来的这样打包有什么好处呢?性能
对比起你的应用代码,react-dom
可能不会常常变更。经过将它分割至另一个代码块,这个代码块能够被独立缓存起来(假设你在用的是长期缓存策略:chunkhash,records,Cache-Control)
// entry.js import("./a"); import("./b");
// a.js import "./helpers"; // helpers is 40kb in size // ...
// b.js import "./helpers"; import "./more-helpers"; // more-helpers is also 40kb in size // ...
结果:webpack会建立一个包含./helpers
的独立代码块,其余模块会依赖于它。在import
被调用时候,这个代码块会跟原始的代码并行加载(译注:它会跟a.js
和b.js
并行加载)。
为何会这样打包:
import
)调用依赖(指的是a.js
和b.js
)helpers
体积大于30kb这样打包有什么好处呢?
将helpers
代码放在每个依赖的块里,可能就意味着,用户重复会下载它两次。经过用一个独立的代码块分割,它只须要被下载一次。实际上,这只是一种折衷方案,由于咱们为此须要付出额外的一次请求的代价。这就是为何默认webpack将最小代码块分割体积设置成30kb(译注:过小体积的代码块被分割,可能还会由于额外的请求,拖慢加载性能)。
经过optimizations.splitChunks.chunks: "all"
,上面的策略也能够应用到初始代码块上(inital chunks)。代码代码块也会被多个入口共享&按需加载(译注:以往咱们使用CommonsChunkPlugin最一般的目的)。
若是想要更深刻控制这个按需分块的功能,这里提供不少选项来知足你的需求。
Disclaimer:不要在没有实践测量的状况下,尝试手动优化这些参数。默认模式是通过千挑万选的,能够用于知足最佳web性能的策略。
这项优化能够用于将模块分配到对应的Cache group
。
默认模式会将全部来自node_modules
的模块分配到一个叫vendors
的缓存组;全部重复引用至少两次的代码,会被分配到default
的缓存组。
一个模块能够被分配到多个缓存组,优化策略会将模块分配至跟高优先级别(priority)的缓存组,或者会分配至能够造成更大致积代码块的组里。
在知足下述全部条件时,那些从相同代码块和缓存组来的模块,会造成一个新的代码块(译注:好比,在知足条件下,一个vendoer可能会被分割成两个,以充分利用并行请求性能)。
有四个选项能够用于配置这些条件:
minSize
(默认是30000):造成一个新代码块最小的体积minChunks
(默认是1):在分割以前,这个代码块最小应该被引用的次数(译注:保证代码块复用性,默认配置的策略是不须要屡次引用也能够被分割)maxInitialRequests
(默认是3):一个入口最大的并行请求数maxAsyncRequests
(默认是5):按需加载时候最大的并行请求数。要控制代码块的命名,能够用name
参数来配置。
注意:当不一样分割代码块被赋予相同名称时候,他们会被合并在一块儿。这个能够用于在:好比将那些多个入口/分割点的共享模块(vendor)合并在一块儿,不过不推荐这样作。这可能会致使加载额外的代码。
若是赋予一个神奇的值true
,webpack会基于代码块和缓存组的key
自动选择一个名称。除此以外,可使用字符串或者函数做为参数值。
当一个名称匹配到相应的入口名称,这个入口会被移除。
经过chunks
选项,能够配置控制webpack选择哪些代码块用于分割(译注:其余类型代码块按默认方式打包)。有3个可选的值:initial
、async
和all
。webpack将会只对配置所对应的代码块应用这些策略。
reuseExistingChunk
选项容许复用已经存在的代码块,而不是新建一个新的,须要在精确匹配到对应模块时候才会生效。
这个选项能够在每一个缓存组(Cache Group)里面作配置。
test
选项用于控制哪些模块被这个缓存组匹配到。原封不动传递出去的话,它默认会选择全部的模块。能够传递的值类型:RegExp
、String
和Function
经过这个选项,能够经过绝对资源路径(absolute modules resource path)或者代码块名称(chunk names)来匹配对应模块。当一个代码块名称(chunk name)被匹配到,这个代码块的全部模块都会被选中。
这是默认的配置:
splitChunks: { chunks: "async", minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, name: true, cacheGroups: { default: { minChunks: 2, priority: -20, reuseExistingChunk: true, }, vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 } } }
默认来讲,缓存组会继承splitChunks
的配置,可是test
、priorty
和reuseExistingChunk
只能用于配置缓存组。
cacheGroups
是一个对象,按上述介绍的键值对方式来配置便可,值表明对应的选项:
除此以外,全部上面列出的选择都是能够用在缓存组里的:chunks
, minSize
, minChunks
, maxAsyncRequests
, maxInitialRequests
, name
。
能够经过optimization.splitChunks.cacheGroups.default: false
禁用default
缓存组。
default
缓存组的优先级(priotity)是负数,所以全部自定义缓存组均可以有比它更高优先级(译注:更高优先级的缓存组能够优先打包所选择的模块)(默认自定义缓存组优先级为0)
能够用一些例子来讲明:
splitChunks: { cacheGroups: { commons: { name: "commons", chunks: "initial", minChunks: 2 } } }
这会建立一个commons
代码块,这个代码块包含全部被其余入口(entrypoints)共享的代码。
注意:这可能会致使下载额外的代码。
splitChunks: { cacheGroups: { commons: { test: /[\\/]node_modules[\\/]/, name: "vendors", chunks: "all" } } }
这会建立一个名为vendors
的代码块,它会包含整个应用全部来自node_modules
的代码。
注意:这可能会致使下载额外的代码。
经过optimization.runtimeChunk: true
选项,webpack会添加一个只包含运行时(runtime)额外代码块到每个入口。(译注:这个须要看场景使用,会致使每一个入口都加载多一份运行时代码)