如何系统地进行前端性能优化【加载篇】

1,273 阅读4分钟

作者:梅瑀。继监控篇之后,本文总结了做加载性能优化的常用手段

加载优化分两种情况,一种是新用户第一次打开我们页面,这里面临的挑战是各种缓存都无法起作用,怎么保证将加载速度控制在用户可以接受的范围,提升转化率。第二种情况是老用户,这里我们的优势为能用上各种缓存,挑战是如何把性能做到极致,实现低代价更新,提升用户留存率

初次加载

指用户第一次看到页面的时候,这时页面应没有任何缓存信息。优秀的首屏速度是转化率提升的必要条件。

按需加载

永远只加载用户需要的内容。灵活地做好代码分割是第一步。拿React技术栈举例,常用的手段有 异步 import 、 React.lazy 、 @loadable/component 等等。这个需要根据具体业务场景灵活地调整。比如说首页一个点击频率不是太高的弹窗。可以讲弹窗逻辑代码分离成一个单独的js。有的同学可能会问如果点击这个弹窗会不会造成顿卡(因为还需要临时去加载js)。对于这种问题,我们可以用 prefetch 来解决。让浏览器在空置时间去下载这个js,但不会解析。等用户点击的时候,基本只剩解析时间了。顿卡感也会大大减少。

当然,按需加载不仅仅指js按需加载。也包括图片等其他资源,比如说页面上一些比较小的用户头像,加载高分辨率图片显然不太划算,好在一些CDN都能通过url参数去灵活控制选用不同分辨率图片。

优化代码体积

上线前通过analyzer分析体积较大的一些js。

首先要做的就是确认tree shrink被正确执行。比较常犯的错误是:如果一个node_modules只有main入口没有module入口,是无法正确进行tree shrink的,开发组件库的同学需要注意了。

根据业务需要兼容的平台,灵活选择构建target和相关polyfill。推荐的解决方案是:分几个版本的polyfill放在服务器上,页面用script标签去引用polyfill,然后服务端根据请求ua灵活返回不同版本的polyfill。

服务端开启gzip压缩,也能大大减少网络传输量,不过需要注意的是这个也会增加浏览器gzip解码的负担。

采用新的图片格式,也能减少传输体积,比如说webp。

能用css写的效果尽量少用图片。

和nodejs类似,如果是选用webpack之类的工具做代码打包的话,请保证及时升级到最新的稳定版本。

preload

通常SPA场景会做代码分割,总会有一些必然会用到但是是在 main.js 加载之后的js,由于只有解析了 main.js 之后我们才知道要加载这些js。所以从加载时间线上看这些是串行。我们可以把这些js作为preload选项。让浏览器一开始就去加载这个js,但是并不会执行。等到真正要用到的再解析,这样在加载上就变成了并行,可以显著节约加载的时间。

cdn

基本操作,不再赘述。

http2/dns预解析

http1.1 的情况下,浏览器对同域名并行资源下载的数据会有限制。而 http2 由于通道复用的优势,会大大增加这个限制数量。和prefetch同理,如果你的页面会请求其他域名的资源,可用dns-prefetch来去做提前解析dns。

ssr

在react、vue占据前端的大半江山的背景下,我们的页面大多是CSR,即js在用户浏览器渲染好页面。如果业务对首屏速度有非常严苛的要求的话。需要采用SSR,由服务端拉好数据直接返回html到浏览器。这样可以节省接口请求时间和js加载解析的时间。当然也会带来服务端段的压力,利弊也需要具体业务去做抉择。

友好的loading提示

假设其他优化已经施展得差不多了之后,给用户一个有趣的加载提示是一个不错的主意。让用户知道页面不是处于顿卡状态,再者给用户一个等待时机的预期,增加继续等待的意向。

二次加载

缓存

304和强缓存的区别不再赘述。通常做法是,index.html不启用缓存。然后里面的所有静态资源打包的时候名称加入contenthash,也就是说如果文件名没有变化,文件内容肯定不会发生变化。然后对html之外的所有资源启用强缓存。

增量更新

如果业务上对一些弱网环境也有要求。我们则有必要做增量更新。增量更新也并非只是客户端才有的,纯前端也可以采用 serviceWorker 劫持静态资源请求,用indexDB/localStorage做资源存储来实现增量更新。

参考链接

html.spec.whatwg.org/multipage/l…

github.com/alibaba/pat…