React项目常用Webpack进行打包,Webpack中有一个功能是Code Spliting,使用该模块可以减少重复引用的模块,就是通过配置将一些公共模块例如react、react-dom打包到vendors.js中,只引用一次。避免了每次不同页面引入的时候,都打包一份相同的代码。但是这样会有一个问题,会导致vendor.js非常大。
http://admin.swczyc.com/shetuanGw/
访问之前点击NetWork面板可以看到如下请求。观察Size一栏。vendors.js大小是8.7MB,上下两个值分别代表压缩之后的值和原始值。在观察Time一栏数据传输时间居然为39.29s。
既然我们看到文件Size十分的大,因此想到使用压缩的方法,因为此项目的前端静态资源是部署在Nginx上,因此通过配置Nginx来达到压缩的效果。具体设置如下
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_level 2;
gzip_types text/plain text/css text/javascript application/javascript application/xml image/jpeg image/png image/gif;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
具体参数
gzip on
开启压缩模块,默认值off
gzip_min_length 1k
不压缩临界值,小于1K不压缩
gzip_buffers 4 16k
按照原始数据大小以16k为单位的4倍申请内存
gzip_comp_level 2
压缩级别,1-10,数字越大压缩效果越好,但是时间就越长
gzip_types text/plain
进行压缩的文件类型
gzip_vary on
会在相应头中添加Vary: Accept-Encoding,以便缓存服务器获取缓存的时候验证是否是支持同一压缩格式的请求,避免向其他服务器发送不匹配的压缩数据
gzip_disable “MSIE[1-6].”
IE6的某些版本对gzip的压缩支持很不好,禁用IE压缩
nginx -s reload
可以看到vendor.js从8.7MB压缩到2.4MB,传输时间从39.29减少到9.48,但是文件即使压缩之后依旧很大,这不禁让人疑惑,vendors.js中到底是谁占用了这么大内存。
在这里使用webpack可视化打包性能分析插件webpack-bundle-analyzer。
首先安装插件
npm install webpack-bundle-analyzer --save-dev
然后在webpack中配置
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
配置完成之后在package.json中增加命令
dist: "webpack -p"
分析出ant-design过大,monent包过大。
根据官网按需加载配置,只引入使用的组件,而不是引入所有。
参数style
设置为true代表引用css源文件就是less文件。
设置为css代表引用编译之后的css文件;
参数libraryDirectory
默认是lib,代表直接引用js编译后文件。
这里配置为es,转化为esmodule进行引入。但是配置完发现包大小没有缩小。因为webpack和antd现在本身就支持tree shaking了,但是webpack支持的tree shaking主要依赖于ES模块语法。因此这里将libraryDirectory设置为lib,直接引入lib文件,将无需转化为esmodule。将节省按需引入组件的工序。
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "lib",
"style": "true"
},
]
根据官网配置用dayjs替换moment
const AntdDayjsWebpackPlugin = require('antd-dayjs-webpack-plugin');
new AntdDayjsWebpackPlugin(),
但是依旧不能接受的vendors大小,尝试分离vendors包
splitchunk将react和ant分别配置缓存组
"react-vendor": {
test: (module) => {
debugger;
return /react/.test(module.context) || /redux/.test(module.context)
|| /classnames/.test(module.context) || /prop-types/.test(module.context)},
priority: 3,
reuseExistingChunk: true,
name: 'react',
},
"antd-vendor": {
// || /[\\/]node_modules[\\/]/.test(module.context)
test: (module) => (/antd?/.test(module.context)),
priority: 2,
reuseExistingChunk: true,
name: 'antd',
},
最终vendors包降到570MB
但是可以看到antd中的icons大小依然很大。按照官方升级antDesign4.0版本即可
const prefixButton = ();
import { SearchOutlined } from ‘@ant-design/icons’;
const prefixButton = (