纪实"/>
前端优化纪实
前言
要优化一个老项目,webpack3的React+antd3 PC项目。
优化前
PPE Load: 3.97
开始
分析
- 项目的js产物只有一个,index.js,大小达到了4.62MB,是体积优化的对象
- 对于node_module部分,而这4.62MB里大部分都是一些依赖,可以用删去重复的依赖,分包,按需加载。
- 对于业务代码部分,可以看到图2分析的页面是spa里的一个单页,但加载的index.js里包含了其他页面的业务代码,可以使用路由懒加载去解决。
体积
常规
- 升级webpack版本到4。
工欲善其事必先利其器。主流的webpack版本能找到的文档也多一点。
之前是用的部门自封装的脚手架,这次直接换成最新的。脚手架用的umi-cli再封装的一层,感兴趣的可以看看。 - moment
最优解是moment可以用 date-fns 按需引入进行替换。
但是项目引入了一些组件使用了moment,所以是对moment的语言部分做了剔除。
chainWebpack(config, { webpack }) {config.plugin().use(webpack.IgnorePlugin, [/\.\/locale/, /moment/]);},
- lodash
使用babel-plugin-lodash插件对import { head } from 'lodash';
这种写法做优化。
但是用了之后看体积是没变的,还是引了全部的lodash……
观看了文档externalize-lodash
猜测是因为引入的组件使用的lodash导致我没办法控制这个引入方式?
正确的做法是,作为组件应该把lodash作为peerDependency。 - 静态资源改为cdn链接
项目里的静态资源就是几个svg,大小还好,都是几k - 检查项目是否有未引用的静态资源
使用unused-files-webpack-plugin。
antd3体积优化
- 对antd做按需加载
项目用的antd3,且并无升级计划所以额外做一下这个步骤。
使用babel-plugin-import
["import", {"libraryName": "antd","style": "css"}]
插件做的事情:
// 未配置按需加载前,需使用此方法引入组件
- import Button from 'antd/lib/button';// 配置完成后使用此方法按需加载组件
+ import { Button } from 'antd';
体积减少的原因
之前是es和lib都引入了,现在使用这个插件之后,引入的组件都在lib里。
比如table组件,之前就引了两次,现在所有的写法都只会引入lib里的代码。
发现umi有个坑,.babelrc
无效了,只能在config
里写
- antd Icon
因为Icon引入是这样的
import {Icon} from 'antd';<Icon type=XXXX/>
感觉没救了,引入的外部组件也这么引的,除了换成antd4之外(成本高),没找到好办法优化。
阶段性小结
这时候js包体积从4.62M→3.6M
(大多数的包都是使用了外部业务组件而产生的依赖,组件历史实在是源远流长,所以包这块已经没办法再缩减了)
为了进一步缩小单页需要的体积,需要做分包和路由懒加载。
分包
在webpack是使用SplitChunksPlugin
我是直接去拷了umi的文档
export default {dynamicImport: {},chainWebpack: function (config, { webpack }) {config.merge({optimization: {splitChunks: {chunks: 'all',minSize: 30000,minChunks: 3,automaticNameDelimiter: '.',cacheGroups: {vendor: {name: 'vendors',test({ resource }) {return /[\\/]node_modules[\\/]/.test(resource);},priority: 10,},},},}});},
}
做完之后这个js整包就根据node_modules、共用js、页面js拆分成多个js
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2I7iomHS-1650545474116)(.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]
他的好处就在减小了访问单页的资源大小,比如对于main页来说,资源大小约等于 2.53+0.473+0.057=3.06M
但是🔽
FCP的时间并没有被优化,查看chrome coverage 发现vendors有很大比重无用的代码,这会影响FCP(first contentful paint)的时间
vendors装的是node_module里的依赖,每一个页面依赖的包差距比较大,所以对于单页来说包的无用部分比较多。当然在打开下一个单页的时候,这个文件已经有缓存了,会省掉下载的时间。
看怎么取舍吧,因为发了一天之后FCP上升至原来的double(502ms→939ms),我决定还是把包修改成根据路由来切分。
这种切分方式,如果用umi就这么写
dynamicImport: {},
无用的代码从68.8%→49.2%
使用lighthouse看First Contentful Paint是有明显提升的
- 大组件按需加载
参考:
启用按需加载
Loadable Components
考虑到包的结构和体积看起来挺合理的,没有特大的组件,先这样吧
性能
常规
- 预加载/懒加载
html dns-prefetch, preconnect
对于接口可以使用preconnect来减少接口初次 tcp 和 tls 链接的等待时间。
Lighthouse
性能优化顺序应该是优化开始时拿着这份报告来当做优化指导的,不管怎么说看一下经过以上操作之后得分有什么变化
- / 路径缺失
当登录态丢失的时候,登陆完会返回/而不是登录前的那个页面,(使用hash路由的常见问题),这就造成了/这个路径虽然没有任何地方引用但是仍然被打开。打开就罢了,因为这个页面没有配置任何组件,也没有在nginx上配备跳转的原因,性能特别差,影响到大盘总体的性能
【其他优化效果-待更新】
参考:
1、
2、
更多推荐
前端优化纪实
发布评论