一步一步的了解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链式操作的正确使用方法
Jan 06 Javascript
jQuery制作效果超棒的手风琴折叠菜单
Apr 03 Javascript
[原创]Bootstrap 中下拉菜单修改成鼠标悬停直接显示
Apr 14 Javascript
在IE8上JS实现combobox支持拼音检索功能
May 23 Javascript
深入理解js数组的sort排序
May 28 Javascript
jQuery实现圣诞节礼物传送(花式轮播)
Dec 25 Javascript
easyui 中的datagrid跨页勾选问题的实现方法
Jan 18 Javascript
javascript实现复选框全选或反选
Feb 04 Javascript
React组件中的this的具体使用
Feb 28 Javascript
Vue2.0中集成UEditor富文本编辑器的方法
Mar 03 Javascript
jquery 键盘事件 keypress() keydown() keyup()用法总结
Oct 23 jQuery
js实现数据导出为EXCEL(支持大量数据导出)
Mar 31 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 自写函数代码 获取关键字 去超链接
2010/02/08 PHP
PHP程序员面试 切忌急功近利(更需要注重以后的发展)
2010/09/01 PHP
PHP对文件夹递归执行chmod命令的方法
2015/06/19 PHP
详解php中 === 的使用
2016/10/24 PHP
php+mysql+jquery实现日历签到功能
2017/02/27 PHP
如何制作浮动广告 JavaScript制作浮动广告代码
2012/12/30 Javascript
Javascript类型系统之String字符串类型详解
2016/06/21 Javascript
Javascript获取随机数的实现方法
2016/06/22 Javascript
plupload+artdialog实现多平台上传文件
2016/07/19 Javascript
js实现贪吃蛇小游戏(容易理解)
2017/01/22 Javascript
jQuery实现在新增加的元素上添加事件方法案例分析
2017/02/09 Javascript
Angular2安装angular-cli
2017/05/21 Javascript
angular4 如何在全局设置路由跳转动画的方法
2017/08/30 Javascript
在HTML文档中嵌入JavaScript的四种方法
2018/05/07 Javascript
vue组件实现进度条效果
2018/06/06 Javascript
angularJs提交文本框数据到后台的方法
2018/10/08 Javascript
[20:46]Ti4循环赛第三日VG vs DK
2014/07/12 DOTA
让python同时兼容python2和python3的8个技巧分享
2014/07/11 Python
Python描述器descriptor详解
2015/02/03 Python
Python程序中使用SQLAlchemy时出现乱码的解决方案
2015/04/24 Python
Django REST为文件属性输出完整URL的方法
2017/12/18 Python
python如何修改装饰器中参数
2018/03/20 Python
对python中for、if、while的区别与比较方法
2018/06/25 Python
python实现遍历文件夹修改文件后缀
2018/08/28 Python
python基础知识(一)变量与简单数据类型详解
2019/04/17 Python
django 配置阿里云OSS存储media文件的例子
2019/08/20 Python
基于Python第三方插件实现西游记章节标注汉语拼音的方法
2020/05/22 Python
为什么python比较流行
2020/06/19 Python
HTML5 canvas 基本语法
2009/08/26 HTML / CSS
JD Sports法国:英国篮球和运动时尚的领导者
2017/09/28 全球购物
澳大利亚拥有最好的家具和家居用品在线目的地:Nestz
2019/02/23 全球购物
Bluebella德国官网:英国性感内衣和睡衣品牌
2019/11/08 全球购物
安全生产先进个人事迹材料
2014/12/30 职场文书
2015年城管个人工作总结
2015/05/15 职场文书
合同审查法律意见书
2015/06/04 职场文书
vue-cropper插件实现图片截取上传组件封装
2021/05/27 Vue.js