一步一步的了解webpack4的splitChunk插件(小结)


Posted in Javascript onSeptember 17, 2018

初衷

webpack4出了两个月,发现大家包括我对splitChunk的使用都还是在摸索阶段。我也看了挺多别人的配置demo,都觉得不太满意或者没得到太好的解惑,issue 下面的问题也没什么人回复,只能自己操作了,顺便记录下来,如果大家有更好的,欢迎评论区留下地址。

常用参数

  • minSize(默认是30000):形成一个新代码块最小的体积
  • minChunks(默认是1):在分割之前,这个代码块最小应该被引用的次数(译注:保证代码块复用性,默认配置的策略是不需要多次引用也可以被分割)
  • maxInitialRequests(默认是3):一个入口最大的并行请求数
  • maxAsyncRequests(默认是5):按需加载时候最大的并行请求数。
  • chunks (默认是async) :initial、async和all
  • test: 用于控制哪些模块被这个缓存组匹配到。原封不动传递出去的话,它默认会选择所有的模块。可以传递的值类型:RegExp、String和Function
  • name(打包的chunks的名字):字符串或者函数(函数可以根据条件自定义名字)
  • priority :缓存组打包的先后优先级。

如果你对这些配置还是不熟悉的话,一拉到底,看看文档

正文

先总览一下所有配置,后续会根据demo跑一遍常见的需求。

optimization: {
 splitChunks: {
  chunks: "async", // 必须三选一: "initial" | "all"(推荐) | "async" (默认就是async)
  minSize: 30000, // 最小尺寸,30000
  minChunks: 1, // 最小 chunk ,默认1
  maxAsyncRequests: 5, // 最大异步请求数, 默认5
  maxInitialRequests : 3, // 最大初始化请求书,默认3
  automaticNameDelimiter: '~',// 打包分隔符
  name: function(){}, // 打包后的名称,此选项可接收 function
  cacheGroups:{ // 这里开始设置缓存的 chunks
   priority: 0, // 缓存组优先级
   vendor: { // key 为entry中定义的 入口名称
    chunks: "initial", // 必须三选一: "initial" | "all" | "async"(默认就是async) 
    test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
    name: "vendor", // 要缓存的 分隔出来的 chunk 名称 
    minSize: 30000,
    minChunks: 1,
    enforce: true,
    maxAsyncRequests: 5, // 最大异步请求数, 默认1
    maxInitialRequests : 3, // 最大初始化请求书,默认1
    reuseExistingChunk: true // 可设置是否重用该chunk
   }
  }
 }
 },

接下来看看第一个例子

entry: {
		pageA: "./pageA", // 引用utility1.js utility2.js
		pageB: "./pageB", // 引用utility2.js utility3.js
		pageC: "./pageC" // 引用utility2.js utility3.js
	},
	
	optimization: {
		splitChunks: {
			cacheGroups: {
				commons: {
					chunks: "initial",
					minChunks: 2,
					maxInitialRequests: 5, // The default limit is too small to showcase the effect
					minSize: 0 // This is example is too small to create commons chunks
				}
			}
		}
	},

结果如图,一切都很正常 commons~pageA~pageB~pageC.js 文件就是utility2.js commons~pageB~pageC.js,根据上述代码,这里的utility2被引用了三次,首先就被抽离了commons~pageA~pageB~pageC.js,然后utility3被引用了两次就放到了commons~pageB~pageC.js,最后只剩下被引用一次的utility1.js,就直接放到了pageA.js里面,如果这里的utility1.js的也是两次,他还是会新建一个chunk放进去,而不是合并到commons~pageB~pageC.js,除非同入口引用才会合并。

mpageA.js pageB.js pageC.js

一步一步的了解webpack4的splitChunk插件(小结)

这里有个地方是需要优化一下的,就是pageA.js pageB.js pageC.js的代码不多,但是打出来的包很大,肯定是一些webpack的运行文件,直接加上runtimeChunk

runtimeChunk: "single"
 // 等价于
 runtimeChunk: {
  name: "manifest"
 }

现在就好了

一步一步的了解webpack4的splitChunk插件(小结)

引用第三方模块 pageA引用vue.js pageB引用react react-dom

vendor: {
		test: /node_modules/,
		chunks: "initial",
		name: "vendor",
		priority: 10,
		enforce: true
	}

但是,这样子的话,会把pageA pageB pageC所有的库都打包到一起vendor.js

一步一步的了解webpack4的splitChunk插件(小结)

假如我想拆分这个vendor.js为pageA-vendor.js pageB-vendor.js怎么办,我试了很久,试出一个最简单的办法,去掉手动的vendor,让插件自动处理。

splitChunks: {
  chunks: "all",
  cacheGroups: {
				commons: {
					chunks: "initial",
					minChunks: 2,
					maxInitialRequests: 5, // The default limit is too small to showcase the effect
					minSize: 0 // This is example is too small to create commons chunks
				}
			}
		},

一步一步的了解webpack4的splitChunk插件(小结)

后来,我把webpack mode改成production后,发现不管用了,同样的配置,在生产模式下,打包出来的东西有点匪夷所思,vendor-pageB.js被合并到了pageB.js里面了。

一步一步的了解webpack4的splitChunk插件(小结)

后来我折腾了好久也分析不出来为什么,自己折腾出来一种方式,还是老子手动来吧,自动化一边去

commons: {
   chunks: "initial",
   minChunks: 2,
   maxInitialRequests: 5, // The default limit is too small to showcase the effect
   minSize: 0 // This is example is too small to create commons chunks
	},
  'vendor-pageA': {
   test: /vue/, // 直接使用 test 来做路径匹配
   chunks: "initial",
   name: "vendor-pageA",
   enforce: true,
  },
  'vendor-pageB': {
   test: /react/, // 直接使用 test 来做路径匹配
   chunks: "initial",
   name: "vendor-pageB",
   enforce: true,
  },

成功打包出来了自己想要的东西。

一步一步的了解webpack4的splitChunk插件(小结)

动态引入

动态引入大家应该都不陌生,就是大家所说的懒加载,直接在pageA和pageB页面里动态引入common-async.js,在这里我先说说,splitChunk应该是可以自动化处理类似commonChunk里的async,child等情况的。

import(/* webpackChunkName: "common-async.js" */"./common-async").then(common => {
 console.log(common);
})

还不错,成功打包出来了

一步一步的了解webpack4的splitChunk插件(小结)

这时候再试试,在这个common-async.js里面在引入共同的代码f.js,看看会不会重复打包

一步一步的了解webpack4的splitChunk插件(小结)

f.js成功的被抽离出来了,其他文件也没有被重复打包,挺好的。

一步一步的了解webpack4的splitChunk插件(小结)

注意的地方

  • cacheGroups 会继承和覆盖splitChunks的配置项,但是test、priorty和reuseExistingChunk只能用于配置缓存组。。
  • cacheGroups 里的每一项最好都要加上chunks参数,不然可能打包不出来你想要的东西。
  • minSize 默认是30KB(注意这个体积是压缩之前的)在小于30kb的情况下一定要设置一个值,否则也可能打包不出来你想要的东西,而且这东西要加在cacheGroups里面。
  • priority 在某些情况下,还是挺有用的,可以设置打包chunks的优先级。

上面的例子里面配置了一个commons,这里的name可以自己设置,也可以不设置,我是没设置的,你可以试试设置了是什么样子的,然后你就会明白这个name其实在某些情况下还是不设置的比较好。

commons: {
   	chunks: "initial",
		minChunks: 2,
		maxInitialRequests: 5, // The default limit is too small to showcase the effect
		minSize: 0 ,
		name: "commons"
  },

源码

代码分割

代码懒加载

参考文章

webpack文档
官方demo

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQUERY THICKBOX弹出层插件
Aug 30 Javascript
JS无限极树形菜单,json格式、数组格式通用示例
Jul 30 Javascript
让alert不出现弹窗的两种方法
May 18 Javascript
js实现上传图片预览的方法
Feb 09 Javascript
javascript实现右侧弹出“分享到”窗口效果
Feb 01 Javascript
js发送短信倒计时的简单实现方法
Sep 08 Javascript
react-native中ListView组件点击跳转的方法示例
Sep 30 Javascript
JS获取数组中出现次数最多及第二多元素的方法
Oct 27 Javascript
JavaScript如何对图片进行黑白化
Apr 10 Javascript
Vue项目引进ElementUI组件的方法
Nov 11 Javascript
angular4自定义组件非input元素实现ngModel双向数据绑定的方法
Dec 28 Javascript
解决Layui中layer报错的问题
Sep 03 Javascript
React Router V4使用指南(精讲)
Sep 17 #Javascript
关于vue编译版本引入的问题的解决
Sep 17 #Javascript
理顺8个版本vue的区别(小结)
Sep 17 #Javascript
vue.js编译时给生成的文件增加版本号
Sep 17 #Javascript
详解关于Vue版本不匹配问题(Vue packages version mismatch)
Sep 17 #Javascript
详解如何解决Vue和vue-template-compiler版本之间的问题
Sep 17 #Javascript
微信小程序中this.data与this.setData的区别详解
Sep 17 #Javascript
You might like
一棵php的类树(支持无限分类)
2006/10/09 PHP
mysql下创建字段并设置主键的php代码
2010/05/16 PHP
Trying to clone an uncloneable object of class Imagic的解决方法
2012/01/11 PHP
Ping服务的php实现方法,让网站快速被收录
2012/02/04 PHP
php截取字符串之截取utf8或gbk编码的中英文字符串示例
2014/03/12 PHP
ThinkPHP中redirect用法分析
2014/12/05 PHP
PHP 爬取网页的主要方法
2018/07/13 PHP
jQuery EasyUI API 中文文档 - ComboTree组合树
2011/10/11 Javascript
jquery zTree异步加载简单实例分享
2013/02/05 Javascript
JavaScript实现复制功能各浏览器支持情况实测
2013/07/18 Javascript
jQuery实现返回顶部功能适合不支持js的浏览器
2014/08/19 Javascript
jquery实现拖拽调整Div大小
2015/01/30 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐二)
2016/07/12 Javascript
js插件Jcrop自定义截取图片功能
2016/10/14 Javascript
在JS中a标签加入单击事件屏蔽href跳转页面
2016/12/16 Javascript
Bootstrap进度条实现代码解析
2017/03/07 Javascript
Node.js 实现简单的接口服务器的实例代码
2017/05/23 Javascript
npm scripts 使用指南详解
2018/10/08 Javascript
基于Angular中ng-controller父子级嵌套的相关属性详解
2018/10/08 Javascript
layui输入框只允许输入中文且判断长度的例子
2019/09/18 Javascript
vue+elementui 对话框取消 表单验证重置示例
2019/10/29 Javascript
node+multer实现图片上传的示例代码
2020/02/18 Javascript
Vue的自定义组件不能使用click方法的解决
2020/07/28 Javascript
[04:11]DOTA2上海特级锦标赛主赛事首日TOP10
2016/03/03 DOTA
python自动化脚本安装指定版本python环境详解
2017/09/14 Python
浅谈python装饰器探究与参数的领取
2017/12/01 Python
Python OpenCV读取png图像转成jpg图像存储的方法
2018/10/28 Python
Django 实现xadmin后台菜单改为中文
2019/11/15 Python
python计算波峰波谷值的方法(极值点)
2020/02/18 Python
实例讲解CSS3中的border-radius属性
2015/08/18 HTML / CSS
美国网上书店:Barnes & Noble
2018/08/15 全球购物
心理健康日活动总结
2014/05/08 职场文书
高中生旷课检讨书
2014/10/08 职场文书
2015年出纳个人工作总结
2015/04/02 职场文书
收银员岗位职责范本
2015/04/07 职场文书
Pytorch 如何实现LSTM时间序列预测
2021/05/17 Python