首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

再见,CommonsChunkPlugin!

英文:Tobias Koppers 译文:众成翻译/为之漫笔

www.zcfy.cc/article/rip-commonschunkplugin-md-github

webpack 4用两个新的配置选项(optimization.splitChunksandoptimization.runtimeChunk)替代了CommonsChunkPlugin。本文介绍这两个新选项的用法。

默认值

默认情况下会做一些优化,对多数用户都是合适的。

注意,默认值只会影响按需加载的块,因为要修改初始(initial)块会影响HTML中的script标签。如果你可以自己处理(比如根据入口配置生成script标签的时候),那可以对初始化也应用这些默认的优化:optimization.splitChunks.chunks: "all"。

webpack根据如下条件自动拆分块:

新块可以共享或者模块来自node_modules文件夹

新块会大于30kb(min+gz以前)

按需加载块之时最大的并行请求数小于等于5

页面初次加载时最大的并行请求数小于等于3

为尽力满足后两个条件,块的体积可以更大。

下面看几个例子。

例1

// entry.js

import("./a");

// a.js

import"react";

// ...

结果:会创建一个独立的包含React的块。在执行import调用时,这个块会随着包含./a的块并行加载。

为什么:

条件1:这个块包含的模块来自node_modules

条件2:react大于30kb

条件3:在执行import调用时,并行请求数是2

条件4:不影响页面初次加载

为什么应该这样拆分?

react可能不会像应用代码那样经常变更。把它挪到一个独立的块,浏览器就可以缓存它(假设你使用了长期缓存配置:chunkhash、records、Cache-Control)。

例2

// entry.js

import("./a");

import("./b");

// a.js

import"./helpers";

// helpers有40kb

// ...

// b.js

import"./helpers";

import"./more-helpers";

// more-helpers也有40kb

// ...

结果:会创建一个独立的包含./helpers的块。在执行import调用时,这个块会与原始的块并行加载。

为什么:

条件1:这个块由两个import调用共享

条件2:helpers大于30kb

条件3:在执行import调用时的并行请求数为2

条件4:不影响页面初次加载

为什么应该这样拆分?

让helpers代码保留在每个块中意味着用户要下载它两次,而独立出来以后,则只需下载一次。实际上这也是有代价的,因为会多一次请求。这也是为什么有最小30kb的限制的原因。

Withoptimizations.splitChunks.chunks: "all"the same would happend for initial chunks. Chunks can even be shared between entrypoints and on-demand loading.

配置

对于喜欢折腾的用户,还有很多选项可供使用。

声明:不要在没有度量的情况下手工优化。默认值考虑了最佳实践和Web性能。

缓存组

这个选项将模块分配到缓存组(cacheGroups)。

默认是将node_modules中的所有模块都分配到一个叫vendors的缓存组,将至少在2个块中重复出现的模块分配到另一个叫default的缓存组。

一个模块可以被分配到多个缓存组。这个优化通过priority选项或构成较大块的模块来优先选择缓存组。

条件

在满足所有条件的情况下,来自相同块和缓存组的模块会构成一个新块。

有4个选项可以用于配置条件:

minSize(default: 30000) 块的最小大小

minChunks(default: 1) 拆分前共享一个模块的最小块数

maxInitialRequests(default 3) 一个入口最大并行请求数

maxAsyncRequests(default 5) 按需加载时最大行行请求数

命名

要控制拆分后新块的名字,可以使用name选项。

注意:如果给不同的块指定了相同的名字,结果就是这些块会被合并成一个。这样配置可以把所有vendor模块拆分为一个由所有入口点/拆分点共享的块,但我不建议这样用。因为这会导致下载的代码变多。

魔术值true会自动根据块和缓存组的键选择一个名字。另外,除给这个选项传一个字符串,也可以传一个函数。

如果名字与入口点名字相同,则删除入口点。

选择块

通过chunks选项可以选择块,有3个值:"initial"、"async"和"all"。分别用于选择初始块、按需加载的块和所有块。

reuseExistingChunk选项用于配置在模块完全匹配时重用已有的块,而不是创建新块。

选择块可以针对每个缓存组分别设置。

选择模块

test选项控制当前缓存组选择哪个模块。省略表示选择所有模块。值可以是RegExp、字符串或函数。

可以匹配绝对模块资源的路径或块名字。如果匹配的是块名字,则会选择该块中的所有模块。

配置缓存组

以下是默认配置:

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、priority和reuseExistingChunk则只能在缓存组层次上配置。

cacheGroups是一个对象,其中键是缓存组的键,而值是选项(这是全部):chunks、minSize、minChunks、maxAsyncRequests、maxInitialRequests,name。

要禁用默认组,传入false:optimization.splitChunks.cacheGroups.default: false。

这里默认缓存组(default)的优先级(priority)是负数,以便任意自定义的缓存组都优先级(默认为0)都会更高。

以下是一些配置的实例:

splitChunks:{

cacheGroups:{

commons:{

name:"commons",

chunks:"initial",

minChunks:2

}

}

}

这样就创建了一个commons块,包含入口点共享的所有代码。

注意:这会导致用户不必要地下载更多代码。

splitChunks:{

cacheGroups:{

commons:{

test:/[\\/]node_modules[\\/]

name:"vendors",

chunks:"all"

}

}

}

这样就创建了一个vendors块,包含整个应用中来自node_modules的所有代码。

注意:这会导致用户不必要地下载更多代码。

optimization.runtimeChunk

optimization.runtimeChunk: true会给每个入口文件的输出再添加一个块,其中只包含运行时。

觉得本文对你有帮助?请分享给更多人

关注「前端大全」,提升前端技能

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180416B1HRHL00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券