Webpack 4 SplitChunksPlugin配置方案(转)
通常情况下我们的 WebApp 是有我们的自身代码和第三方库组成的,我们自身的代码是会常常变动的,而第三方库除非有较大的版本升级,不然是不会变的,所以第三方库和我们的代码需要分开打包,我们可以给第三方库设置一个较长的强缓存时间,这样就不会频繁请求第三方库的代码了。
那么如何提取第三方库呢?在 webpack4.x 中, SplitChunksPlugin 插件取代了 CommonsChunkPlugin 插件来进行公共模块抽取,我们可以对SplitChunksPlugin 进行配置进行 拆包 操作。
SplitChunksPlugin配置示意如下:
optimization: {
splitChunks: {
chunks: "initial", // 代码块类型 必须三选一: "initial"(初始化) | "all"(默认就是all) | "async"(动态加载)
minSize: 0, // 最小尺寸,默认0
minChunks: 1, // 最小 chunk ,默认1
maxAsyncRequests: 1, // 最大异步请求数, 默认1
maxInitialRequests: 1, // 最大初始化请求书,默认1
name: () => {}, // 名称,此选项课接收 function
cacheGroups: { // 缓存组会继承splitChunks的配置,但是test、priorty和reuseExistingChunk只能用于配置缓存组。
priority: "0", // 缓存组优先级,即权重 false | object |
vendor: { // key 为entry中定义的 入口名称
chunks: "initial", // 必须三选一: "initial"(初始化) | "all" | "async"(默认就是异步)
test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
name: "vendor", // 要缓存的 分隔出来的 chunk 名称
minSize: 0,
minChunks: 1,
enforce: true,
reuseExistingChunk: true // 可设置是否重用已用chunk 不再创建新的chunk
}
}
}
}
复制代码
SplitChunksPlugin 的配置项很多,可以先去官网了解如何配置,我们现在只简单列举了一下配置元素。
如果我们想抽取第三方库可以这样简单配置
splitChunks: {
chunks: 'all', // initial、async和all
minSize: 30000, // 形成一个新代码块最小的体积
maxAsyncRequests: 5, // 按需加载时候最大的并行请求数
maxInitialRequests: 3, // 最大初始化请求数
automaticNameDelimiter: '~', // 打包分割符
name: true,
cacheGroups: {
vendor: {
name: "vendor",
test: /[\\/]node_modules[\\/]/, //打包第三方库
chunks: "all",
priority: 10 // 优先级
},
common: { // 打包其余的的公共代码
minChunks: 2, // 引入两次及以上被打包
name: 'common', // 分离包的名字
chunks: 'all',
priority: 5
},
}
},
复制代码
这样似乎大功告成了?并没有,我们的配置有很大的问题:
- 我们粗暴得将第三方库一起打包可行吗? 当然是有问题的,因为将第三方库一块打包,只要有一个库我们升级或者引入一个新库,这个 chunk 就会变动,那么这个chunk 的变动性会很高,并不适合长期缓存,还有一点,我们要提高首页加载速度,第一要务是减少首页加载依赖的代码量,请问像 react vue reudx 这种整个应用的基础库我们是首页必须要依赖的之外,像 d3.js three.js这种特定页面才会出现的特殊库是没必要在首屏加载的,所以我们需要将应用基础库和特定依赖的库进行分离。
- 当 chunk 在强缓存期,但是服务器代码已经变动了我们怎么通知客户端?上面我们的示意图已经看到了,当命中的资源在缓存期内,浏览器是直接读取缓存而不会向服务器确认的,如果这个时候服务器代码已经变动了,怎么办?这个时候我们不能将 index.html 缓存(反正webpack时代的 html 页面小到没有缓存的必要),需要每次引入 script 脚本的时候去服务器更新,并开启 hashchunk,它的作用是当 chunk 发生改变的时候会生成新的 hash 值,如果不变就不发生变动,这样当 index 加载后续 script资源时如果 hashchunk 没变就会命中缓存,如果改变了那么会重新去服务端加载新资源。
下图示意了如何将第三方库进行拆包,基础型的 react 等库与工具性的 lodash 和特定库 Echarts 进行拆分
cacheGroups: {
reactBase: {
name: 'reactBase',
test: (module) => {
return /react|redux/.test(module.context);
},
chunks: 'initial',
priority: 10,
},
utilBase: {
name: 'utilBase',
test: (module) => {
return /rxjs|lodash/.test(module.context);
},
chunks: 'initial',
priority: 9,
},
uiBase: {
name: 'chartBase',
test: (module) => {
return /echarts/.test(module.context);
},
chunks: 'initial',
priority: 8,
},
commons: {
name: 'common',
chunks: 'initial',
priority: 2,
minChunks: 2,
},
}
复制代码
我们对 chunk 进行 hash 化,正如下图所示,我们变动 chunk2 相关的代码后,其它 chunk 都没有变化,只有 chunk2 的 hash 改变了
output: {
filename: mode === 'production' ? '[name].[chunkhash:8].js' : '[name].js',
chunkFilename: mode === 'production' ? '[id].[chunkhash:8].chunk.js' : '[id].js',
path: getPath(config.outputPath)
}
复制代码
我们通过 http 缓存+webpack hash 缓存策略使得前端项目充分利用了缓存的优势,但是 webpack 之所以需要传说中的 webpack配置工程师 是有原因的,因为 webpack 本身是玄学,还是以上图为例,如果你 chunk2的相关代码去除了一个依赖或者引入了新的但是已经存在工程中依赖,会怎么样呢?
我们正常的期望是,只有 chunk2 发生变化了,但是事实上是大量不相干的 chunk 的 hash 发生了变动,这就导致我们缓存策略失效了,下图是变更后的 hash,我们用红圈圈起来的都是 hash 变动的,而事实上我们只变动了 chunk2 相关的代码,为什么会这样呢?
原因是 webpack 会给每个 chunk 搭上 id,这个 id 是自增的,比如 chunk 0 中的id 为 0,一旦我们引入新的依赖,chunk 的自增会被打乱,这个时候又因为 hashchunk 根据内容生成 hash,这就导致了 id 的变动致使 hashchunk 发生巨变,虽然代码内容根本没有变化。
这个问题我们需要额外引入一个插件HashedModuleIdsPlugin,他用非自增的方式进行 chunk id 的命名,可以解决这个问题,虽然 webpack 号称 0 配置了,但是这个常用功能没有内置,要等到下个版本了。
webpack hash缓存相关内容建议阅读此文章 作为拓展
作者:寻找海蓝96
链接:https://juejin.im/post/5d00820b5188255ee806a1c7
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Webpack 4 SplitChunksPlugin配置方案(转)的更多相关文章
- Webpack中SplitChunksPlugin 配置参数详解
代码分割本身和 webpack 没有什么关系,但是由于使用 webpack 可以非常轻松地实现代码分割,所以提到代码分割首先就会想到使用 webopack 实现. 在 webpack 中是使用 Spl ...
- CSS预编译与PostCSS以及Webpack构建CSS综合方案
CSS全称Cascading Style Sheets(层叠样式表),用来为HTML添加样式,本质上是一种标记类语言.CSS前期发展非常迅速,1994年哈肯·维姆·莱首次提出CSS,1996年12月W ...
- 自定义配置Webpack和Babel配置
在使用ant-design-vue的包时样式是可以生效的但是如果我需要用到less文件时会报一个异常 当然这个异常其实很清晰的说明了什么问题看错误信息里面有issues地址,看来问题不止我们遇见了可以 ...
- 深入浅出 webpack 之基础配置篇
前言 前端工程化经历过很多优秀的工具,例如 Grunt.Gulp.webpack.rollup 等等,每种工具都有自己适用的场景,而现今应用最为广泛的当属 webpack 打包了,因此学习好 webp ...
- Atitit.兼具兼容性和扩展性的配置方案attilax总结
Atitit.兼具兼容性和扩展性的配置方案attilax总结 文件配置法1 Jdbc多数据源文件配置发1 Bat文件配置法1 改进的文件配置法(采用类似i18n技术) 推荐1 使用自动化pc_id的方 ...
- webpack + vuejs 基本配置(一)
开始之前 本文包含以下技术,文中尽量给与详细的描述,并且附上参考链接,读者可以深入学习: 1.webpack2.Vue.js3.npm4.nodejs —- 这个就不给连接了,因为上面的连接都是在你实 ...
- webpack react基础配置一
简单介绍webpack react基本配置,入门型: 环境配置: 依赖nodejs,官网下载最新版的nodejs:nodejs.org/en 安装完nodejs npm便自动集成了,通过npm安装其 ...
- Spring MVC之视图解析器和URL-Pattern的配置方案
上期讲解了第一入门案例之后接下来了解一下视图解析器与URL-Pattern的配置方案 先来说视图解析器,在上次博客文章中我们完成了入门案例,接下来我们就在上一个例子中完善一下体出视图解析器 <? ...
- Apache安全配置方案
Apache安全配置方案 from:http://drops.wooyun.org/%e8%bf%90%e7%bb%b4%e5%ae%89%e5%85%a8/2727 apache的一些配置主要是通过 ...
随机推荐
- 【VUE】图片预览放大缩小插件
From: https://www.jianshu.com/p/e3350aa1b0d0 在看项目时,突然看到预览图片的弹窗,感觉好僵硬,不能放大,不能切换,于是便在网上找下关于图片预览的插件,有找到 ...
- 微信之通过AppID和AppSecret获取access_token
最近在搞微信公众平台这方面的东西,,但实际使用的时候发现和access_token有关的接口都无法正常调用,于是debug了下,发现获取到了AppID和AppSecret,在最后请求access_to ...
- 图像处理基本工具——Python 环境下的 Pillow( PIL )
由于笔者近期的研究课题与图像后处理有关,需要通过图像处理工具对图像进行变换和处理,进而生成合适的训练图像数据.该系列文章即主要记录笔者在不同的环境下进行图像处理时常用的工具和库.在 Python 环境 ...
- 最后一个对象属性后边不要加豆号的bug,血淋淋的教训啊,模块化开发IE7下的严重错误,养成好习惯
最近总是写滚动图效果,重复的劳动后,决定写一个滚动图的封装插件.结果写完后在其他浏览器都可以用,却IE7下毫无反应.反复测试各种检查后,发现竟然是在参数对象最后一个属性后多加了个逗号,结果就死在了IE ...
- 牛客挑战赛32 E. 树上逆序对
对于一对 $(x, y)$,能成为逆序对的取决于绝对值大的那个数的符号.假如 $a[x] > a[y]$,当 $a[x]$ 为正时,不管 $a[y]$ 取不取负号都比 $a[x]$ 小.当 $a ...
- python - 将天数转换成日期
# 如果是 0 则为今天 def getdate(day): today = datetime.datetime.now() deviation = datetime.timedelta(days=- ...
- Codeforces Round #603 (Div. 2) A. Sweet Problem(数学)
链接: https://codeforces.com/contest/1263/problem/A 题意: You have three piles of candies: red, green an ...
- Linux 中 Buffer/Cache内存占用过高解决方法
在Linux系统中,我们经常用free命令来查看系统内存的使用状态.在一个RHEL6的系统上,free命令的显示内容大概是这样一个状态: 这里的默认显示单位是kb,我的服务器是128G内存,所以数字显 ...
- 一个项目管理Master的心声
毕业第二年我被幸运女神所眷顾,一下成为了一个20多人研发团队的项目master,自己还未从职场菜鸟的称呼中走出来,就要开始管理团队,在接到通知的时候心里既兴奋又慌得六神无主,然而奔着初生牛犊不怕虎的精 ...
- http-server开启测试服务器
一.安装 npm install --global http-server 二.查看使用帮助 hs -h 三.基本使用 ①默认开启占用8080端口启动一个服务器,直接打开浏览器 hs -o ②指定都端 ...