淘宝首页性能优化实践

依赖系统过多,数据的请求分为三块,其一是静态资源(如 js/css/image/iconfont 等);其二是推到 CDN 的静态数据(如运营填写的数据、前端配置信息等);其三是后端接口,不同的模块对应不同的业务,而且页面中还有不少的广告内容,粗略估计页面刚加载时首屏发出的接口请求就有 8 个,滚到最底下,得发出 20 多个请求。

最能反映页面性能的一个指标是 FPS(frame per second),一般系统设定屏幕的刷新率为 60fps,当页面元素动画、滚动或者渐变时绘制速率小于 60,就会不流畅,小于 24 就会卡顿,小于 12 基本认定卡爆了。

1 帧的时长约 16ms,除去系统上下文切换开销,每一帧中只留给我们 10ms 左右的程序处理时间,如果一段脚本的处理时间超过 10ms,那么这一帧就可以被认定为丢失,如果处理时间超过 26ms,可以认定连续两帧丢失,依次类推。我们不能页面中多次出现连续丢失五六帧的情况,也就是说必须想办法分拆执行时间超过 80ms 的代码程序,这个工作并不轻松。

页面在刚开始载入的时候,需要初始化很多程序,也可能有大量耗时的 DOM 操作,所以前 1s 的必要操作会导致帧率很低,我们可以忽略。当然,这是对 PC 而言,Mobile 内容少,无论是 DOM 还是 JS 脚本量都远小于 PC,1s 可能就有点长了。

DOM 加载并且解析完成才会触发 DOMContentLoaded 事件,倘若源码输出的内容过多,客户端解析 DOM 的时间也会响应加长,不要小看这里的解析时间,如果 DOM 数量增加 2000 个并且嵌套层级较深,解析时间也会相应增加 50-200ms,这个消耗对大多数页面来说其实是没必要的,首屏输出即可,后续的内容只保留钩子,利用 JS 动态渲染。

Load 时间可以用来衡量首屏加载中,客户端接受的信息总量,如果在首屏中充满了大尺寸图片或者客户端与后端建立连接次数较多,Load 时间也会相应被拖长。

流畅度是对 FPS 的视觉反馈,FPS 值越高,视觉呈现越流畅。为了保障页面的加载速度,很多内容不会在页面打开的时候全部加载到客户端。这里提到的流畅度是等待过程中的视觉缓冲,如下方是 Google Plus 页面的一个效果图:

由于平台,淘宝首页面临一个先天的性能缺陷,首屏的渲染需要从 7 个不同的后端取数据,这些数据请求是难以合并的,如果用户屏幕比较大,则首屏的面积也比较大,对应的后端平台数据接口就更多。数据是个性化内容或者为广告内容,故请求也不能缓存。

除必须立即加载的模块外,关键模块被加到懒加载,原因是,部分用户进入页面就可能急速往下拖拽页面,此时,没必要渲染这些首屏模块。

非关键模块统一送到lazyQueue队列,没有基于将非关键模块加入到懒加载,这里有两个原因:

如果用户没有交互,但是页面已经 onload 了,程序当然不能浪费这个绝佳的空档机会,趁机加载内容;经测试,部分情况下,onload 事件没有触发(原因尚不知),所以还设定了一个超时加载,5s 之后,不论页面加载情况如何,都会将剩下的非关键模块加入到懒加载。

如果说的优化叫做懒加载,那么这里的优化可以称之为懒执行。

首页上有几个模块是包含交互的,如头条区域的 tab ,便民服务的浮层和主题市场的浮层,部分用户进入页面可能根本不会使用这些功能,所以程序上并没有对这些模块做彻底的初始化,而是等到用户 hover 到这个模块上再执行全部逻辑。

首屏中有两个次要请求,一个是主题市场的 hot 标,将用户最常逛的三个类目打标;第二个是个人中心的背景,不同的城市会展示不同的背景图片,这里需要请求拿到城市信息。

这两处的渲染策略都是,在程序的 idle(空闲)时期,或者window.onload十秒之后去请求,然后将请求的结果缓存到本地,当用户第二次访问淘宝首页时能够看到效果。这是一种更懒的执行,用户刷新页面才看得到.这种优化是产品能够接受,也是技术上合理的优化手段。

代码的性能优化是一个精细活,如果你要在一个庞大的未经优化的页面上做性能优化,可能会面临一次重构代码。本文从淘宝首页个性化引出的问题出发,从微观到宏观讲述了页面的优化实践,提出了几条可以借鉴的优化标准,希望对你有所。优化的细节点描述的不够完善也不够全面,但是都是值得去优化的方向。

文章来源:淘宝前端团队(FED)