1.代码分割 。 使用optimization.spiltChunks配置

webpack4默认是会对代码进行分割的,也就是splitChunks有一个默认配置,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
splitChunks: {    
chunks: "async", //可取async, initial, all。async针对异步加载的chunk做切割
minSize: 30000, //默认最小分割大小30kb
minChunks: 1, // 共享该module的最小chunk数
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}

缓存组默认将​node_modules​中的模块拆到一个叫做​vendors​的代码块中,将最少重复引用两次的模块放入​default​中。 当然也可以定义自己的cacheGroup ,一般node_modules所有模块打成一个vendors会导致这个chunk很大, 所以可以将很大的模块(比如antd、moment等)单独处理到一个chunk中, 尤其是在异步组件引用不常用的模块时,将不常用的模块单独抽取, 可以减小首屏下载的包大小。以下是代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
cacheGroups: {
venders: {
test: /node_modules/,
name: 'vendors',
priority: -10
},

default: {
minSize: 0,
minChunks: 2,
reuseExistingChunk: true,
name: 'commons'
},

react_vendor:{
//test函数的两个参数: 第一个参数为module,第二个参数为引用这个module的chunk数组
test: (module, chunks) => {
let chunkName = chunks.reduce((a,b) => {
return a + ' , ' + b
}, '')
// console.log(module.context, chunkName , chunks.length)
return /react/.test(module.context)
},
priority: 1,
name: 'react_vendor'
},

moment_vendor:{
test: (module, chunks) => /moment/.test(module.context),
priority: 1,
name: 'moment_vendor'
},

lodash_vendor:{
test: (module, chunks) => /lodash/.test(module.context),
priority: 1,
name: 'lodash_vendor'
}
}
2.配合路由动态导入

使用ECMA提案的dynamic import()或者webpack的require.ensure 。 dynamic import()目前处于stage-3阶段, 所以要使用需要引入相应的babel preset 。 使用动态导入之后会将动态导入的模块或者组件单独打包, 不受optimization.splitChunks的影响。
在代码中异步加载About和User组件,两个组件都引用了lodash和util.js模块,在不修改splitChunks配置的情况下,lodash被单独打包成一个chunk, About和User组件分别被打成一个chunk,并且这两个chunk都包含了util.js, 这就出现了重复加载。

image

为了把util.js单独抽取出来, 需要修改splitChunks:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
splitChunks: {
chunks: "all",
//被引用次数超过设置的值, 才有可能被打包进新的chunk
minChunks: 1,
//控制包的最小大小, 如果切割完的新chunk小于设置值, 则不会生成这个新chunk
minSize: 1,
//初始加载请求时,并行请求数量的上限,不是针对某个chunk, 比如设置为3 , 则最多打出3个包
maxInitialRequests:10,
//chunk组,每一个新chunk就是一个cache group
cacheGroups: {

vendors: false,

default: {
minSize: 0,
minChunks: 2,
reuseExistingChunk: true,
name: 'commons'
}
}
}

上面代码中将默认的vendors组置为false, 禁用该缓存组, 避免抽取node_modules模块对这一步的测试造成影响, 在default设置中将minSize改为足够小。 这样webpack会将两个异步组件共同引用的lodash、util.js都抽取出来, 结果如下:

image