性能优化之构建优化

本文最后更新于:2021/07/05 , 星期一 , 21:32

Tree-shaking

将上下文未用到的代码删掉,不会打包到最终文件中(基于ES6的模块化才可以),来达到减小JS文件大小的目的

有些代码可能会影响到全局作用域或没有用ES6的模块功能,可以通过设置package.json中的sideEffects来指定不希望被shaking掉的文件(在导入时会执行特殊行为的代码,而不是仅仅暴露一个 export 或多个 export。举例说明,例如 polyfill,它影响全局作用域,并且通常不提供 export。)

注意babel默认配置的影响:可能会将es6的模块化语法替换为兼容es5的其他模块化语法。

webpack 5:已经默认集成terser-webpack-plugin来压缩JS

作用域提升

未启用:webpack将模块打包成单独的模块,有依赖关系部分会通过webpack_require进来,再调用。

启动:先分析,然后将依赖提升或合并为一个闭包,来达到压缩代码体积的目的,提高执行效率。(具体可见webpack插件ModuleConcatenationPlugin

Babel7优化配置

在需要的地方引入polyfill

useBuiltIns设置为usage.

各个属性值的输入与输出差异可见:useBuiltIns详细说明

辅助函数的按需引入/复用

@babel/plugin-transform-runtime:重用 Babel 注入的帮助器代码来减少代码体积

根据目标浏览器按需转换代码

需要支持的版本越少,代码体积越小。

通过target:browsers属性设置。browsers可填写的值

webpack的依赖优化

提高构建速度,主要影响开发环境

noParse

直接通知webpack忽略较大的库:被忽略的库不能有import,require,define的引入方式

DllPlugin

避免开发环境打包时对不变的重复的库重复构建

eg.:

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
//webpack.dll.config.js
const path = require("path");
const webpack = require("webpack");
module.exports = {
mode: "production",
entry: {
react: ["react", "react-dom"],
},
output: {
filename: "[name].dll.js",
path: path.resolve(__dirname, "dll"),
library: "[name]"
},
plugins: [
new webpack.DllPlugin({
name: "[name]",
path: path.resolve(__dirname, "dll/[name].manifest.json")
})
]
};

//webpack.config.js
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');

module.exports ={
...,
plugins:[
new DllReferencePlugin({
manifest: require(`${__dirname}/dll/react.manifest.json`)
})
],
...
}

代码拆分

把单个bundle文件拆分成若干个小的bundles/chunks,以达到缩短首屏加载时间

手工定义入口(蠢方法,不推荐)

手动指定多个entry,用到的一些公共部分会重复打包

splitChunks

  • splitChunks提取公有代码,拆分业务代码与第三方库.
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
module.exports={
...,
optimization: {
splitChunks: {
cacheGroups: { //设置缓存组
vendor: {//第三方库
name: 'vendor',
test: /[\\/]node_modules[\\/]/,
minSize: 0,
minChunks: 1,
priority: 10,
chunks: 'initial'
},
common: {//业务代码
name: 'common',
test: /[\\/]src[\\/]/,
chunks: 'all',//
minSize: 0,
minChunks: 2
}
}
}
},
...
}

动态加载

Suspense

资源压缩

Minification

  • Terser 压缩JS

  • mini-css-extract-plugin和optimize-css-assets-webpack-plugin/CssMinimizerWebpackPlugin 提取与压缩css

  • HtmlWebpackPlugin 生成HTMl并压缩

资源持久化缓存

每个打包的资源文件有唯一的hash值,修改后只有受影响的文件hash变化,可以做增量式更新,充分利用浏览器缓存。

在webpack输出文件的时候,filename和chunkFilename用命名时使用变量[contenthash]

应用大小监测与分析

Stats分析与可视化图表

在终端输入webpack --profile --json > stats.json

Webpack Chart

webpack-bundle-analyzer进行体积分析

  • webpack --analyze

  • yarn add source-map-explorer:需要webpack中开启devtool生成source-map

speed-measure-webpack-plugin速度分析

speed-measure-webpack-plugin

React按需加载的实现

React Router基于webpack按需加载,使用loadable/component包装成HOC

使用@loadable/component

1
2
3
const LoadableComp = loadable(() => import('./Component.jsx'), {
fallback: '<div>loading...</div>'
});

webpack优化