webpack4也已经出来好久了,之前写了一篇CommonsChunksplugin的,但webpack4已经废弃了CommonsChunksplugin,改用了splitChunks;splitChunks在用法上和思想用都有所不同,更加方便,优化方式更好,但是总体来说,还是大同小异。
用法
webpack4打包优化直接写在配置项里面,而不是写在插件里面,这是splitChunks的默认配置:
module.exports = {
//...
entry:{},
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
default: {
test: function (module, chunks) {
return true
},
priority: -20,
reuseExistingChunk: true
}
}
}
},
}
配置项详解
splitChunks和CommonsChunksplugin的配置项是差不多的。
1. chunks
string | Function(chunk)
抽取公共模块的来源
string:只有三个值async(动态加载模块),initial(入口模块),all(全部模块入口和动态的)。
Function(chunk): chunk对象包含chunk本身的许多信息,有用的也就是chunk.name,可以通过name选择特定的模块来源,返回true则选中,否则不选中。
module.exports = {
//...
optimization: {
splitChunks: {
chunks (chunk) {
// 选择名字为`my-excluded-chunk`的模块。
return chunk.name !== 'my-excluded-chunk';
}
}
}
};
2. maxAsyncRequests
Number
default:5
异步的按需加载模块最大的并行请求数,通过import()或者require.ensure()
方式引入的模块,分离出来的包是异步加载的。
3. maxInitialRequests
Number
default:3
初始加载网页的最大并行数.
5. minSize
Number
default:30000
打包出来的新的chunk需要满足的最小文件大小,否则不打包,单位B,默认30000。
6. maxSize
Number
default:0 ;
打包出来的新的chunk最大的文件大小,与minSize相对,超过这个值,将新的chunk再进一步拆分成更小的chunk,单位B,默认0。
minSize、maxsize、maxAsyncRequests、maxInitalRequests,相互之间可能存在冲突,比如分离出来的包>maxSize,需要进一步拆分chunk,拆分出来的chunk大小<minSize,或者说拆分出来chunk之后,chunk的数量>maxInitalRequests,这个时候怎么办?它们之间是有优先级的:minSize > maxSize > maxInitialRequest/maxAsyncRequests,也就是我必须先满足minSize才会考虑是否满足maxSize,最后才考虑maxInitialRequest/maxAsyncRequests的条件
7. automaticNameDelimiter
sring
name连接符,分离出来的新chunk的名字,默认基于cacheGroupsKey,chunks来源的name来取,例:缓存组的cacheGroupsKey是vendor
,来源chunk是的name是adminA
,adminB
,那么连接符是~
,分离出的chunk名字是vendor~adminA~adminB.js
。
8. name
Boolean | string | function (module, chunks, cacheGroupKey)
分离出来的chunk的取名规则。不能和入口文件同名,如果和入口文件同名,那么入口文件将会被移除,不会被打包
Boolean :
如果是true,基于cacheGroupsKey,chunks来源的name来取。如果是false,按照数字0排序。string :
string作为name, string.js。function (module, chunks, cacheGroupKey):
- cacheGroupKey: 缓存组的键名;
- chunks: Array类型,
splitChunks.chunks
的数组集合,每一个chunk对象有很多属性,这里有用也就只有chunks[i].name
,即打包来源chunk的键名; - module: 可能有用的值
module.context
,module.resource
,module.type
;module.context
公共模块来源chunk的所在文件夹,例如通过 npm 下载的包chunks.context == path.resolve(__dirname , ‘node_modules’);,module.resource
公共模块来源chunk的完整路径,module.type
文件类型javascript/auto
,css/auto
。 - 返回值: 返回值作为文件名,同样不能和入口文件同名,否则入口文件会被移除
分割线
上面的默认配置并不好用,也不需要配置,如果你要做精细化的代码分离,需要配置缓存组cacheGroups,cacheGroups拥有上面所有的属性,除此之外还有priority
、reuseExistingChunk
、test
、enforce
四个属性,并且缓存组能够覆盖上面所有的属性。
- priority :优先级,default:0;如果两个缓存组都需要将某一公共模块打包,为了不重复打包,肯定只能打包进入其中之一,那么优先考虑priority 高的。
- reuseExistingChunk:是否重用已经存在的模块,default:true;例:如果在当前缓存组需要抽离出 jquery.js,但是 jquery.js已经被其它缓存组抽取出来了,那么将会重用已经抽取出来的 jquery.js。
- test:
function (module, chunks) | RegExp | string
在chunks的基础上,精确的选择那些公共模块应该被打包。 - enforce:忽略minSize、maxSize、maxAsyncRequests、maxInitalRequests等限制条件直接打包。
缓存组也有默认配置 default ,default的配置会覆盖splitChunks中的默认配置,并且其它缓存组的minSize的优先级低于default缓存组的优先级,所以默认配置最好还是在splitChunks配置,不要在缓存组配置:
optimization: {
splitChunks: {
cacheGroups: {
default:
chunks: "all",
priority: -20,
reuseExistingChunk: true,
}
}
}
},
抽取第三方库:test用正则匹配路径中包含“/node_modules/”的模块,name叫vendor,否则name是基于缓存组的键名(此处是“vendor”,默认的是“default”)和chunks来取名的。
example1: 抽取第三方库,adminA和adminB都引入了jquery。
module.exports = {
mode: 'production',
context: path.resolve(__dirname),
entry: {
adminA: "./adminA.js",
adminB: "./adminB.js"
},
output: {
filename: "[name].js",
chunkFilename: "[name].chunk.js",
path: path.resolve(__dirname, 'dist')
},
optimization: {
splitChunks: {
chunks: "all",
maxSize: 80000,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: "vendor",
chunks: "all",
minSize:20000
},
}
}
}
}
example2: 抽取公共类,adminA和adminB都引入了jquery和childA,childA>20kb。此处分离出来的包name是default ~ adminA ~ adminB ~ 07dd53af.chunk.js”,default是默认配置缓存组的键名,adminA和adminB是chunks来源。
example3: 在exmaple2的基础上,减少chuildA的体积,此处childA<20kb;minSize:设置为20000;
optimization: {
splitChunks: {
maxSize: 80000,
//添加
minSize: 20000
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: "vendor",
chunks: "all"
},
}
}
},
结果:childA没有被分离出来。