前段时间优化一个公司历史老项目的Web性能,却引出了一系列的问题,让我反思良多。
我通过Chrome的Lighthouse工具可以看出一些性能参数和问题反馈,我逐一对其进行优化。
根据资源请求的不同,大致可以分为前端资源性能和后端程序性能两个方面。
先分析一下前端资源吧:
Defer offscreen images。
Chrome给出的建议是:
Consider lazy-loading offscreen and hidden images after all critical resources have finished loading to lower time to interactive. Learn more.
意思是可以考虑延迟加载一些图片或者隐藏一些图片在所有关键资源完成加载后再考虑加载,通过延迟加载来降低交互时间。
lazy-load的实现方法很多,开源框架推荐:lazysizes。
当然也可以使用npm方式安装:
npm install lazysizes
使用方式很简单,先引入lazysize到需要的页面:
然后给需要被lazyload的img标签上加新的属性,如下:
<img data-sizes="auto" data-src="image2.jpg" data-srcset="image1.jpg 300w, image2.jpg 600w, image3.jpg 900w" />特别要注意,有时候太多background方式加载的图片也会影响性能,lazysizes也可以处理这样的图片。方法如下,使用data-bg属性即可:
<div data-bg="/path/to/image.jpg"></div>Reduce JavaScript execution time
解决这个问题方法很多,第一个想到的就是压缩资源。
比如压缩js和css文件,可以考虑使用webpack工具或者gulp来压缩大资源文件,合并一些文件资源请求。
还可以通过预加载来提高响应速度,可以在最重要的js资源文件的引入上加入预加载,代码如下:
通过增加preload
最后还可以异步加载资源,异步不会阻塞主进程,代码调整也很小:
除此之外JavaScript的执行时间过长还有可能是有大量逻辑运算,有很多页面把一些逻辑判断和计算都交给前端去计算,这样也不利于渲染,建议还是把复杂逻辑和计算尽可能交给后端去处理,让前端渲染更加“轻量”。
3. Backend response
数据接口返回有时候也很拖累响应时间,因为一些前端结构需要根据返回的数据进行组装新的页面结构。
这里可以考虑找到性能真正的瓶颈,到底是数据库查询导致的慢,还是业务逻辑不清晰导致的冗余,或者其他原因。
我遇到的是因为老项目的数据库操作类不是单例,会每次产生一个数据库连接句柄,且该页面复杂又多的sql查询。
我勇敢地修改着10多年历史的代码,编写了单例模式的操作类,然后增加了必要的缓存机制。
然而后面我遇到了问题,首先单例类在一些特殊情形下不满足之前的代码需求,导致奇特的数据库报错,而async属性导致一些js文件无法同步加载到位,而有一些依赖这些资源的php文件执行报错。
最终在同事的帮助下,恢复了服务,我也再一次体会到了任何一种性能提升都要谨慎,特别是对一个古老的项目。
前人不敢动的代码,可能是深渊。
PS:我的公众号 成都有娃儿会同步发布该文章,也可以关注哦!