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的一些配置主要是通过 ...
随机推荐
- Linux学习25-Xshell设置页面最大显示行数
前言 在使用xshell查看日志的时候,有时候日志太多,往上翻的时候,前面的就找不到了. 需要设置xshell的页面显示最大行数,查看更多的日志详情. 设置显示行数 左上角-文件-属性 终端-设置最大 ...
- thrift rpc通信
thrift rpc通信 框架 别人的简历: 负责抓取程序的开发和维护,对抓取内容进行数据提取.整理.1.定向数据抓取程序的维护和开发,了解了Sqlite数据库.Thrift服务和多线程的开发调试.2 ...
- Win10上的Docker应用:Hello World
前言: 最近学习了Docker相关技术点,国内关于Docker的资料大多是基于Linux系统的,但是我对Linux又不熟(实际上没用过,掩面哭笑.Jpg). 好在在Win10下也是支持Docker的, ...
- 第五篇 -- Xml序列化
XML序列化是将对象的公共属性和字段转换为XML格式,以便存储或传输的过程.反序列化则是从XML输出中重新创建原始状态的对象.XML序列化中最主要的类是XmlSerializer类.它的最重要的方法是 ...
- Elasticsearch 中的 ignore_above
检索超过ignore_above设定长度的字段后,无法返回结果
- Python bytes类型及用法
bytes 类型 Python 3 新增了 bytes 类型,用于代表字节串,是一个类型,不是C#中的列表. 字符串(str)由多个字符组成,以字符为单位进行操作: 字节串(bytes)由多个字节组成 ...
- BAT脚本一键启动多个程序
最近写代码,开机要开各种环境,IDE,每次都要对着桌面图标一个个点击,感觉非常麻烦,简直浪费生命,每天开机要花好几分钟打开这些东西,于是稍微学习了一下window下的bat脚本语言,写了一个极为简单而 ...
- 2019年12月份关于Android Studio 需要了解的知识总结
因为期末项目答辩的原因,我和我的小组成员一起写了个作品展示app 就是用AndroidStudio写的 具体功能呢还加上了云服务器,bmob,等等 我是不知道那个云服务器要怎么配置啊,也不会用,都是 ...
- 学习:Windows API核心DLL文件
在 Windows 的系统目录中,存在着很多的动态链接库文件(DLL 文件).这些 DLL 文件中包括了 Windows API 函数可执行程序. DLL 将各函数"导出",这样应 ...
- jmeter+ant+jenkins搭建接口自动化测试环境(基于win)
1.jmeter jmeter依赖java运行环境,所以需要提前下载jdk并配置好环境变量 官网下载(http://jmeter.apache.org/download_jmeter.cgi),我用的 ...