背景
作为一个内容类应用,看新闻读资讯一直是头条用户的核心需求,页面的打开速度直接关系到用户使用头条的核心体验,在头条中,为了更多的承载足够丰富的样式和逻辑下保持多端体验的统一,详情页的内容我们是通过 WebView 来承载的,但 WebView 本身的性能相比 Native 来说比较差,因此,今日头条技术团队一直致力于优化详情页的加载速度。
经过不断的优化,目前今日头条中详情页在线上的打开体验,从肉眼上基本已经感知不到加载过程。在接下来这篇文章里,我们会逐步拆解和介绍我们对详情页加载优化的思路和实践。
先让我们来看看优化前后的效果吧~

数据建立
性能
当我们开始着手优化页面加载速度之前,我们需要明确一个问题,怎样才是用户真正体验到的页面加载时间。
首先我们可以看下面这个公式:
页面加载时间 = 页面加载完成时间 - 页面开始加载时间
页面开始加载时间很好确定,当用户点击了 Feed 上的卡片,我们就可以认为页面开始加载了。
问题是怎么定义页面加载完成了呢?从客户端的角度上看,无论是 iOS 还是 Android,WebView 都提供了一个 loadFinsih 的回调,但在实际应用中我们发现,loadFinish 回调并不能反应用户的真实体验。
一般来说,WebView 渲染需要经过下面几个步骤
解析 HTML 文件
加载 JavaScript 和 CSS 文件
解析并执行 JavaScript
构建 DOM 结构
加载图片等资源
页面加载完毕
而 loadFinish 实际上是在页面加载完毕阶段,而 DOM 构建完成时页面结构就已经基本渲染完成,所以从用户真实体验的角度出发,我们以 DOM 结构构建完成(即 domReady)的时间点作为页面加载完成时间点。
白屏
在详情页浏览过程中,除了页面加载速度之外,还有一个特别影响用户体验的问题,就是页面的白屏,也是早期的时候用户反馈比较多的问题,但有很多场景都可能导致详情页发生白屏,比如说网络异常,WebView 异常等等,需要从用户体验的角度出发去检测用户发生白屏的情况。
目前可以想到最直观的方案就是对 WebView 进行截图,遍历截图的像素点的颜色值,如果非白屏颜色的颜色点超过一定的阈值,就可以认为不是白屏,目前需要考虑的是这个方案的性能问题和检测时机。
iOS 中提供了 WebView 快照的接口获取当前 WebView 渲染的内容,底层采用异步回调的实现方式,API 耗时 10ms 左右,用户基本无感知。
- (void)takeSnapshotWithConfiguration:(nullable WKSnapshotConfiguration *)snapshotConfiguration completionHandler:(void (^)(UIImage * _Nullable snapshotImage, NSError * _Nullable error))completionHandler API_AVAILABLE(ios(11.0));
Android 中系统提供的获取视图内容的接口为 getDrawingCache,API 耗时在 40ms 左右,性能损耗也不是特别大。
除了截图的性能损耗,像素点检测也是白屏检测中比较耗时的场景,经过实验,我们把 WebView 截图的图片进行缩小到原图的 1/6,遍历检测图片的像素点,当非白色的像素点大于 5% 的时候我们就认为是非白屏的情况,可以相对高效检测准确得出详情页是否发生了白屏。
指标建立
确定好口径之后,我们还有需要明确的一个问题是,什么指标可以反映用户刷头条时的真实体验。
最早的时候,我们用的是详情页页面的页面平均加载时长,也就是页面加载时长的总和/页面 pv,在开始的时候这个指标也的确可以明确我们的加载速度。
后来随着详情页的加载优化逐渐的深入,会发现平均加载时长虽然也可以反映详情页加载速度,但是因为详情页的 pv 比较高,如果使用平均加载速度化很多用户体验问题就被平均

最低0.47元/天 解锁文章
2万+

被折叠的 条评论
为什么被折叠?



