splitChunksPlugin配置参数详解
基础知识点
- webpack内部的Code-Splitting(代码分割),实际上是splitChunksPlugin插件来实现
- 默认会对所有的异步加载进行代码分割 import()函数
optimization: {
// splitChunks: {
// chunks: "all"
// }
},
- 异步导入第三方模块(或自己业务模块)
- 数字0代表代码分割产生的id值,如果我们希望是一个可识别的英文名,在异步加载代码import()函数中可以使用魔法注释的语法
语法: /webpackChunkName:模块名/
- 我们发现魔法注释我们填写的是lodash,为什么打包后生成的文件名是vendors~lodash,多了一个vendors呢?因为受webpack.config.js中optimization的默认配置项的值的影响
- 查看splitChunksPlugin插件配置项=>因为optimization.splitChunks配置选项就是往webpack内部的splitChunksPlugin插件传参,由splitChunksPlugin插件来进项代码分割
- vendors和default的默认值都改成false(之后详解具体含义),再打包
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
vendors: false, // 默认值改成false
default: false // 默认值改成false
}
}
}
小结
- 异步导入(import()函数)才能使用魔法字符串
- 异步导入(import()函数)使用魔法字符串生效的前提必须cacheGroups中的vendors和default设置为false,即没有缓存组
- cacheGroups只对同步导入模块有约束作用,且同步导入的模块要进行代码分割必须配置相关的缓存组
- 当上面异步导入模块,加了魔法注释 /webpackChunkName:lodash/,
- 同时满足vendors缓存组的检测,所以lodash模块打包到vendors缓存组中vendors~lodash.js
- 当cacheGroups中的vendors和default设置为false,则没有缓存组,直接用魔法注释的命名生成分割后的文件名
splitChunks参数详解
splitChunks参数默认值概览
optimization: {
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
- 为了调试方便,我们先把vendors和default设为false,之后详解两个属性的含义
optimization: {
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: false,
default: false
}
}
}
chunks
- 含义:对异步还是同步导入(import)的模块进行代码分割
- 默认值:async 默认只对异步导入模块进行分割,同步代码不分割
- 其他值: all 对异步和同步导入(import)的模块都进行代码分割
optimization: {
splitChunks: {
chunks: "all", //设置为all
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: false,
default: false
}
}
}
- 但我们发现打包后还是没生成lodash.js文件,即同步导入模块没有进行代码分割
- 当chunks设置为all时,webpack在打包同步导入的模块时,但不会直接把导入的模块进行分割,还会执行cacheGroups(缓存组)里面的逻辑,只有配置了cacheGroups的相关参数才能对同步导入的模块进行代码分割
- 打包同步导入模块的流程(前提:chunks:“all”)
- 将前面vendors:false和default:false改成默认配置项
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
a:当同步导入模块时,webpack根据chunks:"all"知道要对同步导入的模块进行代码分割
b:webpack继续执行cacheGroups中的配置流程,vendors配置项里面的test会检测导入的模块是否在node_modules目录下,很显然,同步导入的lodash模块在node_modules目录下,满足检测需求,webpack会把同步导入的模块打包到vendors这个缓存组中
c: yarn build 打包,vendors~main代表分割出来的模块在哪个入口文件中导入
- 当我们不想在vendors后面加上main(入口文件名),缓存组中filename配置,这个属性只对同步导入模块分割生效,异步导入模块分割会报错
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
filename: "venders.js" //修改分割后生成文件名
}
小结
- cacheGroups只对同步导入模块有约束作用,且同步导入的模块要进行代码分割必须配置相关的缓存组
- 当同步导入模块进行代码分割时,如果cacheGroups中没有匹配的缓存组,则不会进行代码分割,同步导入模块还是合在main.js中(所有要加上一个default缓存组保底)
- 当异步导入模块进行代码分割时,不管有没有匹配到缓存组,都会进行代码分割,分两种情况**(缓存组只会对异步导入模块的的文件名产生影响,不会对代码分割的行为有任何影响)**
a:如果cacheGroups中没有匹配的缓存组,会根据魔法注释的命名生成分割后的文件(lodash.js),就像上面vendors和default缓存在都设置为false
b:如果cacheGroups中没有匹配的缓存组,会根据魔法注释的命名和匹配到的缓存组同时拼接命名生成分割后的文件(vendors~lodash.js)
minSize
- 含义:当导入的模块最小是多少字节才会进行代码分割
- 默认值:30000字节
minChunks
- 含义: 当一个模块被导入(引用)至少多少次才对该模块进行代码分割
- 默认值:1
- 实例:当minChunks:2时,分同步导入和异步导入两种情况
optimization: {
splitChunks: {
chunks: "all",
minSize: 30000,
: 2, //最少被引用两次才进行代码分割
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
a: 同步导入模块代码分割
b: 异步导入模块分割:异步导入模块不管optimization.splitChunks的选项配置的值是什么都会进行代码分割
maxAsyncRequests
- 含义:同时加载的模块数是几个
- 举例:当我们异步引入了10个类库,按照正常情况下,每个类库都会进行代码分割成一个单独的js文件(脱离main.js),即生成了除main.js外的10个分割js文件,如果
- maxAsyncRequests:5 则打包时,前5个类库会进行代码分割,生成对应的5个js文件,后面的5个类库依然存在于main.js中,不进行代码分割
- 默认值:5
maxInitialRequests
- 含义: 入口文件(index.js)进行代码分割的时候,最多能分割出多少个js文件,超出的模块不会进行代码分割
- 默认值:3
- maxInitialRequests和maxAsyncRequests的区别是
a: maxAsyncRequests包含入口文件及其入口依赖文件(实际上也是模块)中所导入的模块的一起来统计是否超过maxAsyncRequests设置的值
b: maxInitialRequests只是对入口文件中直接导入包数量的统计
automaticNameDelimiter
- 含义:文件名连接符
- 默认值:~
name
- 含义:起的文件名有效
- 默认值:true
缓存组中的属性
前提知识:为什么需要缓存组
- cacheGroups只对同步导入模块有约束作用,且同步导入的模块要进行代码分割必须配置相关的缓存组
- 异步导入的模块不管有没有缓存组都会对每个异步导入的模块单独生成一个js模块
a:有缓存组
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
b: 没有缓存组
cacheGroups: {
vendors: false,
default: false
}
- 同步导入的模块必须有缓存组才能进行代码分割
a. 没有cacheGroups(缓存组)
在入口文件中同步导入lodash模块和jquery模块,两个模块同时满足chunks: “all”, minSize: 3000等条件,则lodash和jquery模块都会分割成单独的js文件,想要把lodash和jquery模块分割到同一个js文件中是做不倒的
b: 有缓存组
打包lodash的时候,先不着急生成jquery的文件,先放到vendors缓存组中缓存着,打包jquery的时候发现jquery也符合vendors这个缓存组的要求,也缓存到这个组中,当最终所有的模块都分析好了之后,把符合vendors这个缓存组的所有模块打包到一起去,所以起名为缓存组是有道理的
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
vendors缓存组
text
- 正则匹配条件
priority
- 缓存组的优先级(和z-index概念一样)
reuseExistingChunk
- 如果一个模块被打包了,遇到相同的模块时不会再打包,复用之前的模块