要理解splitChunks,先要理解webpack的提出的几个概念,module、chunk和bundle。
webapck拆分出的chunk有四种:
import('abc').then(res=>{})
这种异步加载的代码,在webpack中即为运行时代码这样做的目的是避免文件的频繁变更导致浏览器缓存失效,所以其是更好的利用缓存。提升用户体验。
默认配置:
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
假如我们有这样一个配置
module.exports = {
entry: {
app: './src/index'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash:8].bundle.js', // 用于以entry为入口的chunk
chunkFilename: '[name].[hash:16].bundle.js' // 用于动态加载的chunk
}
}
// .src/index.js
const test = 123
console.log(test)
import _ from 'lodash'
setTimeout(()=> {
import(/* webpackChunkName: 'test' */ './test')
import(/* webpackChunkName: 'math' */ './math')
}, 2000)
// ./test.js
import './helper'
// ./math.js
import './helper'
// ./helper.js
// 从jQuery官网download的源码,helper.js Size > 30kb
默认在build的时候,webpack会将lodash和业务逻辑都打包到一个bundle中,这个bundle非常的大
async,表明只能分离异步的模块
当为initial时,只能分离初始化的模块,异步的模块无法分离
将初始化或者异步的模块都分离出来
optimization: {
splitChunks: {
chunks (chunk) {
return chunk.name !== 'test' && chunk.name !== 'math'
}
}
}
异步文件的最大并行请求数量
optimization: {
splitChunks: {
maxAsyncRequests: 1 // 2
}
}
在build的时候会发现,这时候webpack并没有帮我们做codeSplitting
将maxAsyncRequests改成2时,helper里的内容就会分离成一个单独的bundle。
entry的最大并行请求数,默认是3个。这个选项主要适用于多页应用的项目
maxInitialRequest/maxAsyncRequests < maxSize < minSize
.
chunk-a: react, react-dom, 一些组件1
chunk-b: react, react-dom, 一些组件2
chunk-c: angular, 一些组件3
chunk-d: angular, 一些组件4
webpack4 会自动创建两个vendor chunks,结果如下:
vendors~chunk-a~chunk-b: react, react-dom
vendors~chunk-c~chunk-d: angular
chunk-a 到 chunk-d: 只包含各自的组件
chunk-a: react, react-dom, 一些组件1
chunk-b: react, react-dom, lodash, 一些组件2
chunk-c: react, react-dom, lodash, 一些组件3
webpack4同样也会创建两个vendors chunks,结果如下:
vendors~chunk-a~chunk-b~chunk-c: react, react-dom
vendors~chunk-b~chunk-c: lodash
chunk-a 到 chunk-c: 只只包含各自的组件
chunk-a: vue, 一些组件1, 一些被共享的业务组件(非node_modules资源)
chunk-b: vue, 另一些组件2, 一些被共享的业务组件
chunk-c: vue, 另一些组件3, 一些被共享的业务组件
假定被共享的组件大小超过30kb,那么webpack4会创建一个venrdors chunk和一个commons chunk,结果如下:
vendors~chunk-a~chunk-b~chunk-c: vue
comons-chunk-a~chunk-b~chunk-c: 一些被共享的业务组件
chunk-a 到 chunk-c: 只包含各自的组件
当被共享的业务组件大小小于30kb时,webpack4会将他们重复的模块放到chunk-a到chunk-c中,而不是分离出一个common chunk来。我们认为,下载一个体积小于30kb的chunk而导致额外的http请求,是不值得的。
chunk-a: react, react-dom, 一些组件1, 一些共享的react组件
chunk-b: react, react-dom, angular, 一些组件2
chunk-c: react, react-dom, angular, 一些组件3, 一些共享的react组件, 一些共享的angular组件
chunk-d: angular, 一些组件4, 一些共享的angular组件
webpack4会创建两个vendors chunks和两个commons chunks
vendors~chunk-a~chunk-b~chunk-c: react, react-dom
vendors~chunk-b~chunk-c~chunk-d: angular
commons~chunk-a~chunk-c: 一些共享的react组件
commons~chunk-c~chunk-d: 一些共享的angular组件
chunk-a to chunk-d: 各自的组件
chunks:可用值为“all”、“async”、“initial”,默认值是“async”
minSize:控制最小包的大小,大于这个值才会去拆分,如果拆分的公共模块小于这个大小,那就复制成多份,直接打包到引用该模块的包里
minChunks:模块的重复调用次数大于等于minChunks值时,就会满足这项拆包条件,但只看入口模块导入的,不看动态加载模块中导入的(import(‘…’)),即使设置的chunks为“all”。
maxInitialRequests:入口文件最大请求的文件数量(import等方式)
maxAsyncRequests:用于限制异步模块内部的并行最大请求数
name:主要用于分离chunks后的名字,可以是字符串或者函数,相同name会合并成一个chunk
splitChunks.cacheGroups