首先如果不做任何处理,我们的webpack会将所有的js打包到一个文件中。
所以我们要做代码分割,常见的有三种方式:
- 使用entry配置手动分离。
- import()动态导入。
- 利用splitChunks。
那么我们需要明白一点:无论splitChunks如何配置,只要是动态引入的模块(页面),都是会被单独用一个文件来存放的。其次,通常情况下,不用动态引入,所有页面就都在一个js包里,动态引入了就一个页面一个js包。
splitChunks是作为一个配置对象传入的(chunks分割规则嘛,一个chunks就是一个js文件),splitChunks的默认配置为:
// 表示选择哪些 chunks 进行分割,可选值有:async,initial和all
chunks: "async",
// 表示新分离出的chunk必须大于等于minSize,默认为30000,约30kb。
minSize: 30000,
// 表示一个模块至少应被minChunks个chunk所包含才能分割。默认为1。
minChunks: 1,
// 表示按需加载文件时,并行请求的最大数目。默认为5。
maxAsyncRequests: 5,
// 表示加载入口文件时,并行请求的最大数目。默认为3。
maxInitialRequests: 3,
// 表示拆分出的chunk的名称连接符。默认为~。如chunk~vendors.js
automaticNameDelimiter: '~',
// 设置chunk的文件名。默认为true。当为true时,splitChunks基于chunk和cacheGroups的key自动命名。
name: true,
// cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块,就分配到该组。模块可以被多个组引用,但最终会根据priority来决定打包到哪个组中。默认将所有来自 node_modules目录的模块打包至vendors组,将两个以上的chunk所共享的模块打包至default组。
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
//
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
chunks
我们的chunks可分为两类:1.首页加载需要用到的(同步包,首页js) 2.到用的时候才需要加载的包(异步包,其他普通页面js)
chunks的值有:async(默认)、initial、all。
这三个值的意思是,只对异步包进行拆分,只对同步包进行拆分,对所有包都拆分。
例如说:首页main.js中动态引入a.js页面,a.js中引入vue。
- 当chunks为async时,会分为三个包,一个同步的app.js,一个异步页面包1.js,一个vue的依赖包2.js(2.js就是被分出来的一个包)。
- 当chunks为initial时,只会分为两个包,一个同步的app.js,一个异步页面包1.js。但如果我们改变题目,是main.js引入的vue,a.js中未引入,那么app.js会拆分成app.js和2.js了。
- 当chunks为all时,就很简单了,不论vue是index.js中引入,还是a.js中引入,都会被单独拆分出来。
minSize、maxInitialRequests、maxAsyncRequests
minSize: 分出来的包的最小大小,就是新包要比这个值大,才能分出来。
maxInitialRequests:最大同步包个数,就是你首页加载,需要的包不能超过这个数。
maxAsyncRequests:一次异步,最大异步包个数,就是你一个普通页面加载,需要的包不能超过这个数。
不满足这些条件的话,包是不允许分出来的。
minChunks
就是一个模块最少被几个chunks依赖才允许分离出来,默认是1。
例子:拿chunks中的例子来说,a.js中引入vue,那么vue属于被依赖了一次,minChunks为1满足条件,可以将vue单独作为包分离出来,但是如果minChunks为2就不行了,至少还要有其他chunks中依赖vue,才可以被分离出来。
cacheGroups
自定义chunk包,也就是说我们可以自定义chunks包,将符合条件的代码(或模块),从别的包里分出来放这里面。
cacheGroups继承 splitChunks 里的所有属性的值,如 chunks、minSize、minChunks、maxAsyncRequests、maxInitialRequests、automaticNameDelimiter、name ,我们还可以在 cacheGroups 中重新赋值,覆盖 splitChunks 的值。另外,还有一些属性只能在 cacheGroups 中使用:test、priority 、reuseExistingChunk。
通过 test 条件对模块进行过滤,符合条件的模块分配到相同的组,
priority优先级,同时满足两个的筛选条件的模块,根据优先级来决定放到哪个chunks中,priority越大,优先级越高。
cacheGroups 有两个默认的组,一个是 vendors,将所有来自 node_modules 目录的模块放进入;一个 default(vue3叫common了),包含了由两个以上的 chunk 所共享的模块。
名字默认由 cacheGroups 中组的 key + 源chunk名组成(例如vendors~app)
总结分析
对于默认配置,首先chunks为async,说明只会对异步包进行拆分,且拆分规则必须满足cacheGroups这些前面的这些属性,那么vendors呢?也就是说只有异步包里引用的来自 node_modules的部分(例如a.js中引入的vue)才会打包到vendors中。这样如果main.js里面有引入vue的话,肯定就被重复打包到app.js了,所以会有重复打包的情况,在开发环境中,将chunks设置成all,是一个比较好的优化方式。