# Webpack 优化
# tree shanking优化 (opens new window)
移除JavaScript上下文中的未引用代码(dead-code)。它只支持es6中的import和export语法,所以并不会应用到require语法中
webpack生成环境模式是开启的,引起esModule的时候确保按需引入。
# 代码分离
常用的代码分离方法有三种:
- 入口起点:使用 entry 配置手动地分离代码。
- 防止重复:使用 Entry dependencies 或者 SplitChunksPlugin 去重和分离 chunk。
- 动态导入:通过模块的内联函数调用来分离代码。
使用 Entry dependencies 去重和分离 chunk。
module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
entry: {
index: {
import: './src/index.js',
dependOn: 'lodash',
},
another:{
import: './src/another-module.js',
dependOn: 'lodash'
},
lodash: 'lodash'
},
devServer: {
contentBase: './dist'
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SplitChunksPlugin 去重和分离 chunk。
// webpack.config.js
optimization: {
splitChunks: {
// 代码分割的类型,可以设置为'all','async','initial',默认是'async`
// 'all': 对同步和异步引入模块都进行代码分割
// 'async: 只对异步引入模块进行代码分割
// 'initial': 只对同步代码进行代码分割
chunks: 'all',
// 代码分割模块的最小大小要求,不满足不会进行分割,单位byte
minSize: 30000,
// 如果分割模块大于该值,还会再继续分割,0表示不限制大小
maxSize: 0,
// 最小被引用次数,只有在模块上述条件并且至少被引用过一次才会进行分割
minChunks: 1,
// 最大的异步按需加载次数
maxAsyncRequests: 5,
// 最大的同步按需加载次数
maxInitialRequests: 3,
// 分割模块打包chunk文件名分割符:'~'
automaticNameDelimiter: '~',
automaticNameMaxLength: 30,
// 分割文件名,设置为true会自动生成
name: true,
cacheGroups: { // 缓存组
vendors: {
// 分割模块匹配条件
test: /[\\/]node_modules[\\/]/,
// 权重
priority: -10
},
default: {
minChunks: 2,
priority: -20,
// 是否使用已有的chunk,设置为true表示如果使用到的文件已经被分割过了
// 就不会再进行分割,生成新的分割文件
reuseExistingChunk: true
}
}
}
}
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
40
41
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
40
41
动态导入(dynamic import)
function getComponent() {
return import('lodash')
.then(({ default: _ }) => {
const element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
})
.catch((error) => 'An error occurred while loading the component');
}
setTimeout(() => {
getComponent().then((component) => {
document.body.appendChild(component);
});
}, 50000);
// async
async function getComponent() {
const element = document.createElement('div');
const { default: _ } = await import('lodash');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
setTimeout(() => {
getComponent().then((component) => {
document.body.appendChild(component);
});
}, 50000);
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
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
# Prefetching和PreLoading
// preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。 // preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。 // preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。
prefetch: 加载的内容可能会在未来的任何时间被使用,它会在主文件加载完毕并且利用浏览器的空闲时间来进行资源请求
preloading: 加载的内容会被主文件立即用到,拥有中等程度的资源加载优先权,并且会在页面加载时立即和主文件平行使用浏览器提供的资源。