我最近做了一个TypeScript项目的性能优化,把页面从卡顿变成流畅,今天分享实战经验和技巧。
我,最近,负责,了,一个,TypeScript,项目,的,性能,优化,这个,项目,是,一个,比较,复杂,的,前端,应用,功能,多,数据量,大,之前,运行,起来,比较,卡,页面,加载,慢,交互,也,有,延迟,用户,体验,不,太,好,领导,让,我,做,一下,性能,优化,我,花,了,大概,两周,时间,从,分析,问题,到,定位,瓶颈,再,到,优化,解决,最后,把,页面,从,卡顿,变成,了,流畅,加载,速度,和,交互,响应,都,有,了,很大,提升,用户,体验,明显,改善。
今天,这篇,文章,就,来,分享,一下,这次,TypeScript,项目,性能,优化,的,实战,经验,和,技巧,包括,我,是,怎么,分析,性能,问题,的,怎么,定位,瓶颈,的,用,了,哪些,优化,手段,效果,如何,以及,一些,通用,的,TypeScript,和,前端,性能,优化,最佳,实践。
一、项目背景和问题
先,说说,项目,背景,和,遇到,的,问题,这个,项目,是,一个,企业级,的,数据,管理,平台,前端,用,TypeScript,加,React,开发,功能,比较,复杂,有,很多,数据,表格,图表,表单,还有,各种,交互,功能,数据量,也,比较,大,一个,页面,可能,要,加载,几万,条,数据,还要,做,各种,筛选,排序,统计,等等,操作,之前,的,版本,功能,都,实现,了,但是,性能,问题,比较,突出,主要,有,几个,方面。
第一,页面,加载,慢,首屏,加载,时间,比较,长,用户,打开,页面,要,等,好几秒,才能,看到,内容,白屏,时间,长,用户,体验,很,不好,第二,交互,卡顿,页面,上,的,各种,交互,比如,切换,标签,筛选,数据,排序,表格,滚动,等等,都,有,明显,的,延迟,和,卡顿,操作,之后,要,等,一下,才,有,反应,用户,感觉,很,不,流畅,第三,内存,占用,高,页面,开,久,了,之后,内存,占用,越来越,高,甚至,会,导致,浏览器,卡顿,或者,崩溃,尤其是,数据量,大,的,页面,更,明显,第四,打包,体积,大,项目,打包,出来,的,JS,文件,体积,很,大,加载,慢,也,影响,页面,性能,这些,问题,加,在,一起,导致,用户,体验,很,不好,很多,用户,反馈,页面,卡,慢,不好用,所以,领导,决定,做,一次,全面,的,性能,优化,我,就,负责,了,这个,任务。
二、性能分析和瓶颈定位
做,性能,优化,第一,步,不是,上来,就,优化,而是,先,分析,问题,定位,瓶颈,因为,只有,找到,真正,的,瓶颈,才能,有,针对性,地,优化,达到,事半功倍,的,效果,如果,盲目,优化,可能,花,了,很多,时间,但是,效果,不,明显,我,主要,用,了,以下,几个,工具,和,方法,来,分析,性能,问题,和,定位,瓶颈。
第一,用,Chrome,DevTools,的,Performance,面板,分析,运行时,性能,这是,最,常用,也,最,有效,的,性能,分析,工具,我,在,页面,上,做,各种,操作,比如,加载,页面,切换,标签,筛选,数据,滚动,表格,等等,同时,用,Performance,面板,录制,性能,数据,录制,完,之后,就能,看到,详细,的,性能,分析,结果,包括,FPS,CPU,占用,JS,执行,时间,渲染,时间,等等,还,能,看到,每个,函数,的,执行,时间,调用,栈,等等,通过,这个,工具,我,很快,就,发现,了,几个,瓶颈,比如,有,一个,数据,处理,函数,执行,时间,特别,长,一次,要,几百,毫秒,导致,页面,卡顿,还有,渲染,的,时候,有,很多,不必要,的,重绘,和,重排,也,影响,性能,还有,一些,事件,处理,函数,执行,时间,长,导致,交互,延迟,等等,这些,都,是,通过,Performance,面板,定位,到,的。
第二,用,Chrome,DevTools,的,Memory,面板,分析,内存,使用,情况,针对,内存,占用,高,的,问题,我,用,Memory,面板,做,了,内存,快照,和,分析,发现,有,几个,地方,存在,内存,泄漏,比如,一些,事件,监听,没有,移除,一些,定时器,没有,清除,还有,一些,大,对象,没有,被,垃圾,回收,一直,占用,内存,导致,页面,开,久,了,内存,越来越,高,另外,还,发现,有些,数据,被,重复,存储,了,多份,也,浪费,了,内存,这些,问题,都,是,通过,Memory,面板,分析,出来,的。
第三,用,webpack-bundle-analyzer,分析,打包,体积,针对,打包,体积,大,的,问题,我,用,webpack-bundle-analyzer,工具,对,打包,出来,的,文件,做,了,分析,可视化,地,看到,每个,模块,的,体积,大小,发现,有,几个,第三方,库,体积,特别,大,而且,有些,功能,我们,根本,没,用,到,但是,被,全量,打包,进去,了,还有,一些,我们,自己,写,的,代码,也,有,可以,优化,的,空间,比如,有些,工具,函数,重复,实现,了,有些,组件,可以,拆分,懒加载,等等,通过,这个,分析,我,对,打包,体积,的,构成,有,了,清楚,的,了解,也,知道,了,从,哪些,地方,入手,优化。
第四,用,Lighthouse,做,整体,性能,评分,和,建议,Lighthouse,是,Chrome,自带,的,一个,性能,审计,工具,能,对,页面,做,全面,的,性能,分析,给出,性能,评分,和,具体,的,优化,建议,我,用,Lighthouse,跑,了,几次,得到,了,整体,的,性能,情况,和,优化,建议,比如,建议,减少,首屏,JS,体积,使用,懒加载,优化,图片,减少,不必要,的,DOM,节点,等等,这些,建议,也,给,了,我,很多,参考,和,方向。
通过,这些,工具,和,方法,我,对,项目,的,性能,问题,有,了,全面,的,了解,也,定位,到,了,主要,的,瓶颈,主要,有,几个,一是,大数据量,处理,效率,低,二,是,不必要,的,渲染,和,重绘,重排,多,三,是,内存,泄漏,和,浪费,四,是,打包,体积,大,加载,慢,五,是,一些,代码,写法,不,够,高效,定位,到,瓶颈,之后,我,就,开始,有,针对性,地,做,优化,了。
三、具体优化措施和效果
下面,说说,我,具体,做,了,哪些,优化,措施,以及,效果,如何。
1. 大数据量处理优化
这是,最,核心,的,瓶颈,之一,项目,里,有,很多,大数据量,的,处理,比如,几万,条,数据,的,筛选,排序,统计,等等,之前,的,实现,比较,简单,粗暴,效率,不,高,一次,处理,要,几百,毫秒,甚至,上秒,导致,页面,卡顿,我,主要,做,了,以下,几个,优化。
第一,用,Web Worker,把,大,数据量,处理,放到,后台,线程,执行,不,阻塞,主线程,之前,所有,数据,处理,都,在,主线程,执行,处理,大,数据量,的,时候,会,阻塞,主线程,导致,页面,卡顿,交互,无响应,我,把,一些,耗时,的,大数据量,处理,逻辑,抽,出来,放到,Web Worker,里,执行,这样,处理,数据,的,时候,不,阻塞,主线程,页面,还是,能,正常,响应,交互,用户,体验,提升,很,明显,当然,Web Worker,也,不是,万能,的,有,一些,限制,比如,不能,直接,操作,DOM,和,主线程,通信,有,开销,等等,所以,只,把,真正,耗时,的,大数据量,计算,放,进去,不是,所有,逻辑,都,放,进去,这样,才能,达到,最,好,的,效果。
第二,优化,数据,处理,算法,和,数据结构,之前,的,一些,数据,处理,算法,效率,比较,低,比如,查找,用,的,是,线性,查找,时间,复杂度,O(n),数据量,大,的,时候,很,慢,我,把,一些,需要,频繁,查找,的,数据,改成,用,Map,或者,对象,做,索引,查找,时间,复杂度,变成,O(1),速度,提升,很,多,还有,一些,排序,和,统计,的,逻辑,也,做,了,优化,减少,不必要,的,遍历,和,计算,比如,能,一次,遍历,做完,的,事情,就,不,分,多次,遍历,能,提前,终止,的,就,提前,终止,减少,计算量,另外,对于,一些,重复,的,计算,用,缓存,记住,结果,避免,重复,计算,这些,优化,虽然,都是,小,细节,但是,加,起来,效果,很,明显,数据,处理,速度,提升,了,好几倍。
第三,数据,分页,和,虚拟,列表,对于,几万,条,数据,的,表格,之前,是,一次性,把,所有,数据,都,渲染,出来,DOM,节点,特别,多,渲染,慢,内存,占用,也,高,我,改成,了,分页,加载,和,虚拟,列表,分页,就是,一次,只,加载,和,渲染,一页,的,数据,比如,20条,或者,50条,用户,翻页,的,时候,再,加载,下,一页,这样,DOM,节点,少,了,很多,渲染,速度,快,了,内存,占用,也,低,了,虚拟,列表,就是,即使,数据量,大,也,只,渲染,可视,区域,内,的,数据,滚动,的,时候,动态,更新,渲染,的,内容,这样,不管,数据量,多,大,DOM,节点,数,都,保持,在,一个,比较,小,的,范围,性能,很,好,我,用,了,react-window,这个,库,来,实现,虚拟,列表,很,方便,效果,也,很,好,通过,分页,和,虚拟,列表,表格,的,渲染,性能,提升,非常,明显,之前,加载,几万,条,数据,要,好几秒,现在,几乎,瞬间,就,加载,完,了,滚动,也,很,流畅。
2. 渲染性能优化
除了,数据,处理,渲染,性能,也,是,一个,重要,的,瓶颈,之前,页面,有,很多,不必要,的,重绘,和,重排,还有,很多,不必要,的,组件,重新,渲染,导致,交互,卡顿,我,主要,做,了,以下,优化。
第一,优化,React,组件,渲染,减少,不必要,的,重新,渲染,项目,用,的,是,React,React,的,性能,优化,很,重要,的,一点,就是,减少,不必要,的,组件,重新,渲染,我,主要,用,了,几个,方法,一是,用,React.memo,包裹,纯,组件,避免,props,没,变,的,时候,重新,渲染,二是,用,useMemo,和,useCallback,缓存,计算,结果,和,回调,函数,避免,每次,渲染,都,重新,创建,新,的,对象,和,函数,导致,子,组件,不必要,的,重新,渲染,三是,合理,划分,组件,把,大,组件,拆,成,小,组件,把,变化,的,部分,和,不,变化,的,部分,分开,这样,变化,的,时候,只,重新,渲染,变化,的,部分,不,变化,的,部分,不用,重新,渲染,四是,避免,在,render,函数,里,做,耗时,的,计算,和,创建,新,对象,这些,都会,影响,渲染,性能,通过,这些,优化,组件,重新,渲染,的,次数,减少,了,很多,渲染,性能,提升,明显。
第二,减少,重排,和,重绘,重排,和,重绘,是,浏览器,渲染,的,两个,重要,概念,重排,是,元素,的,几何,属性,变化,导致,浏览器,重新,计算,布局,重绘,是,元素,的,外观,变化,但是,几何,属性,没,变,导致,浏览器,重新,绘制,元素,重排,的,代价,很,高,会,影响,性能,我,主要,做,了,几个,优化,一是,避免,频繁,操作,DOM,样式,批量,修改,样式,减少,重排,次数,二是,用,transform,和,opacity,做,动画,这,两个,属性,不会,触发,重排,只会,触发,合成,层,的,处理,性能,好,三是,对,频繁,变化,的,元素,提升,为,合成,层,用,will-change,或者,translateZ,减少,重排,和,重绘,的,影响,四是,避免,在,循环,里,读取,offsetTop,等,会,触发,强制,同步,布局,的,属性,这些,会,导致,浏览器,立即,执行,重排,性能,很差,通过,这些,优化,页面,的,重排,和,重绘,减少,了,很多,渲染,更,流畅,了。
第三,防抖,和,节流,对于,一些,频繁,触发,的,事件,比如,窗口,resize,页面,scroll,输入框,input,等等,如果,每次,触发,都,执行,处理,函数,会,导致,执行,次数,太多,影响,性能,我,对,这些,事件,的,处理,函数,做,了,防抖,或者,节流,防抖,就是,事件,触发,后,等待,一定,时间,如果,没有,再,触发,才,执行,处理,函数,适合,输入框,搜索,这种,场景,节流,就是,一定,时间,内,只,执行,一次,处理,函数,适合,scroll,resize,这种,频繁,触发,的,场景,通过,防抖,和,节流,事件,处理,函数,的,执行,次数,大大,减少,性能,提升,明显,交互,也,更,流畅,了。
3. 内存优化
针对,内存,占用,高,和,内存,泄漏,的,问题,我,也,做,了,专门,的,优化。
第一,修复,内存,泄漏,通过,Memory,面板,分析,我,找到,了,几处,内存,泄漏,的,地方,一是,一些,事件,监听,在,组件,卸载,的,时候,没有,移除,导致,事件,监听,一直,存在,回调,函数,也,一直,被,引用,无法,被,垃圾,回收,我,在,组件,卸载,的,生命周期,函数,里,加上,了,移除,事件,监听,的,代码,修复,了,这个,问题,二是,一些,定时器,setInterval,setTimeout,在,组件,卸载,的,时候,没有,清除,也,会,导致,内存,泄漏,我,也,在,组件,卸载,的,时候,加上,了,清除,定时器,的,代码,三是,一些,大,对象,被,全局,变量,或者,长生命周期,的,对象,引用,没有,释放,导致,一直,占用,内存,我,在,不用,的,时候,把,这些,引用,置,为,null,让,垃圾,回收,机制,能,回收,这些,对象,通过,这些,修复,内存,泄漏,的,问题,基本,解决,了,页面,开,久,了,内存,也,不会,一直,增长,了。
第二,减少,不必要,的,内存,占用,除了,内存,泄漏,还有,一些,不必要,的,内存,占用,也,做,了,优化,一是,避免,重复,存储,数据,之前,有些,数据,在,多个,地方,都,存了,一份,浪费,内存,我,做,了,数据,统一,管理,用,状态,管理,库,集中,存储,数据,各个,组件,需要,的,时候,从,状态,管理,库,里,取,不用,每个,组件,都,存,一份,减少,了,内存,占用,二是,及时,释放,不用,的,大数据,比如,切换,页面,的,时候,把,上,一个,页面,的,大数据,清空,释放,内存,不要,一直,留着,三是,用,更,节省,内存,的,数据结构,比如,对于,一些,简单,的,列表,用,数组,而,不是,对象,数组,内存,占用,更,小,通过,这些,优化,内存,占用,降低,了,不少,页面,运行,更,稳定,了。
4. 打包和加载优化
针对,打包,体积,大,加载,慢,的,问题,我,也,做,了,专门,的,优化。
第一,代码,分割,和,懒加载,之前,项目,是,把,所有,代码,都,打包,到,一个,JS,文件,里,体积,很,大,加载,慢,我,做,了,代码,分割,把,不同,页面,的,代码,分割,成,不同,的,chunk,用,React,的,lazy,和,Suspense,实现,路由,级别的,懒加载,用户,访问,哪个,页面,才,加载,哪个,页面,的,代码,不用,一次性,加载,所有,代码,另外,对于,一些,大,的,第三方,库,也,单独,打包,成,vendor,chunk,利用,浏览器,缓存,这些,库,一般,不,经常,变,用户,第二次,访问,的,时候,直接,用,缓存,不用,重新,加载,通过,代码,分割,和,懒加载,首屏,需要,加载,的,JS,体积,大大,减小,首屏,加载,速度,提升,明显。
第二,优化,第三方,库,的,引入,通过,webpack-bundle-analyzer,分析,我,发现,有些,第三方,库,体积,很大,而且,有些,功能,我们,没,用,到,但是,被,全量,打包,进去,了,我,做,了,几个,优化,一是,对于,支持,按需,引入,的,库,比如,lodash,antd,等等,改成,按需,引入,只,引入,用,到,的,函数,和,组件,不,全量,引入,大大,减小,了,打包,体积,二是,对于,一些,功能,简单,的,库,考虑,自己,实现,或者,用,更,轻量,的,替代,库,减小,体积,三是,对于,一些,只,在,特定,场景,用,的,大,库,改成,动态,导入,用,的,时候,才,加载,不用,不,加载,通过,这些,优化,第三方,库,的,体积,减小,了,很多,打包,整体,体积,也,小,了,不少。
第三,压缩,和,优化,资源,除了,JS,代码,其他,资源,也,做,了,优化,一是,JS,和,CSS,代码,开启,压缩,去掉,注释,空格,缩短,变量名,等等,减小,体积,二是,图片,资源,做,压缩,和,优化,用,更,高效,的,图片,格式,比如,WebP,减小,图片,体积,而且,用,懒加载,图片,不,在,首屏,的,图片,先,不,加载,滚动,到,可视,区域,再,加载,减小,首屏,加载,压力,三是,开启,gzip,或者,brotli,压缩,服务器,传输,资源,的,时候,压缩,传输,减小,传输,体积,加快,加载,速度,通过,这些,优化,资源,体积,减小,了,加载,速度,也,提升,了。
四、优化效果和总结
经过,大概,两周,的,优化,项目,的,性能,有,了,非常,明显,的,提升,我,用,Lighthouse,和,Performance,面板,重新,测,了,一下,首屏,加载,时间,从,之前,的,5秒,多,降到,了,1.5秒,左右,提升,了,70%,多,交互,响应,时间,也,从,之前,的,几百,毫秒,降到,了,几十,毫秒,基本,感觉,不到,延迟,很,流畅,内存,占用,也,降低,了,40%,左右,而且,不会,一直,增长,了,很,稳定,打包,体积,减小,了,60%,多,首屏,JS,体积,减小,了,70%,多,整体,性能,评分,从,之前,的,40多分,提升,到,了,90多分,用户,体验,改善,非常,明显,很多,用户,反馈,页面,变,快,了,流畅,了,很,好用,领导,也,很,满意,这次,性能,优化,算是,比较,成功,的。
总结,一下,这次,性能,优化,的,经验,我,觉得,有,几个,点,很,重要,第一,性能,优化,要,先,分析,定位,瓶颈,再,优化,不要,盲目,优化,用,数据,说话,找到,真正,的,瓶颈,才能,事半功倍,第二,性能,优化,是,一个,系统,工程,涉及,数据,处理,渲染,内存,打包,加载,等等,各个,方面,要,全面,考虑,综合,优化,才能,达到,最,好,的,效果,第三,要,关注,用户,体验,性能,优化,的,最终,目的,是,提升,用户,体验,所以,要,从,用户,的,角度,出发,关注,用户,实际,感受,到,的,性能,比如,首屏,加载,时间,交互,响应,流畅度,等等,而,不是,只,看,一些,技术,指标,第四,性能,优化,要,持续,做,不是,一次,优化,完,就,完,了,要,建立,性能,监控,和,回归,机制,持续,关注,性能,避免,新,的,代码,引入,新,的,性能,问题,保持,系统,的,高性能。
五、写在最后
这次,TypeScript,项目,的,性能,优化,对,我,来说,是,一次,很,好,的,锻炼,和,学习,通过,这次,优化,我,对,前端,性能,优化,有,了,更,深入,的,理解,也,掌握,了,很多,性能,分析,和,优化,的,工具,和,技巧,这些,经验,对,我,以后,的,开发,工作,都,很,有,帮助,也,希望,通过,这篇,文章,能,给,做,前端,开发,的,朋友,一些,参考,和,启发,帮,大家,更,好,地,做,性能,优化,提升,用户,体验。
当然,性能,优化,的,方法,和,技巧,还有,很多,我,这里,分享,的,只是,我,这次,项目,中,用,到,的,一些,比较,有效,的,方法,不一定,全面,也,不一定,适合,所有,项目,大家,还是,要,根据,自己,的,项目,情况,具体,分析,选择,适合,自己,的,优化,方法,而且,性能,优化,是,一个,持续,的,过程,需要,不断,学习,和,实践,才能,越,做,越,好。
最后,希望,大家,都,能,重视,性能,优化,做出,高性能,的,前端,应用,给,用户,好,的,体验,也,欢迎,大家,在,评论,区,分享,你们,做,性能,优化,的,经验,和,技巧,或者,遇到,的,问题,和,困惑,一起,交流,一起,进步,谢谢,大家,的,阅读。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录