1. 摘要

  • 常见白屏原因:JS逻辑出错、核心资源加载失败、客户端或内核的问题、各种性能原因造成的短时白屏;
  • JS异常、资源加载异常、网络请求记录等白屏现场信息,结合业务场景分析,基本上就有了定位抓手,进而分析到原因;
  • 关键在于如何捕获和利用好有助于问题定位的现场信息。

    2. 白屏是什么

  • 首先,基线是在移动端H5这个载体上,不是Native App;

  • 其次,白屏的定位是指整个H5页面没有任何渲染内容,用户在终端屏幕上看到的WebView只有一片纯白色; 在上述前提下,白屏还分两种发生场景。一种是在页面加载过程中,由于网络延迟等因素,浏览器内核没有收到主文档的请求响应,这个时候自然是没有内容可渲染的;一种是主文档响应回来了,但是受各种预期之外的异常因素干扰,导致页面内容没有正常渲染出来。前者更多是网络环境的原因,例如高铁或电梯信号中断、网络上某台服务器突然抽风,这些在端上不可控。所以,后者才是我们的重点关注对象。

以上,我们明确了白屏的定义和范畴,下面简单介绍白屏检查原理,即如何判断当前webview显示是否白屏,以及线上事故的监控解决方案。

3. 白屏监控原理

从不同的业务角度出发,可以产生不同的检查手段。例如,前端可能去判断DOM树的结构(距离用户体感太远,准确度很差),客户端可能屏幕截图分析像素(成本过高,消耗性能)。对于H5页面,实际上是由浏览器内核来完成渲染绘制的,因此,在内核上去监控白屏具有天然的位置优势。

在渲染流程上,WebView在接收到WebContent(即HTML/CSS/JS)后,经过内核引擎的解析、排版、描绘等处理后,会转化成一棵图层树,然后再经过光栅化、合成、并最终显示在屏幕上。

内核检查白屏的主要思路,是在需要检查的时候,构造一个用于绘制分析的canvas,然后将当前的图层树画到这个canvas上(不会走到真正的绘制流程),通过分析绘制指令(是否存在纹理层、是否有绘制操作等)来判断是否白屏。因为图层树即是页面内容经过内核引擎处理后的表达方式,它更准确的描述了即将呈现用户的结果,而且通过分析指令的方式而不是抠像素,对性能也不会造成影响。

根据谷歌的研究,尽量在1秒内呈现页面内容,否则,用户的注意力会分散,他们处理任务的感觉会中断;超过10秒的话,用户感到失望,可能会放弃任务,或者不会再回来。实际上,考虑到低端机上的性能,一些逻辑比较复杂的页面,特别是走CSR(Client Side Rendering,即客户端渲染,指页面在浏览器环境中通过JS完成DOM树构建的渲染处理技术)的页面,会需要一段时间来完成页面的渲染。综合考虑,我们选择在页面内容加载完成(可以理解为触发window.onload事件的时机)后3秒的时间点,来检查判断此时是否“白屏”状态。强调一下,这个“白屏”只代表那一时刻的状态,有可能后面一直白屏,也有可能后面渲染出来了。但是不管哪一种情形,都是影响用户体验,甚至导致用户流失。

白屏监控的手段有了,我们还需要在保持性能和保护隐私的前提下,尽量全面的收集白屏现场信息,以便问题的分析。现场信息这个概念其实很大,具体应该收集哪些信息,怎样的形式来收集,这里不展开,在下面的实战分析环节,可以看到我们如何利用这些信息来还原现场进行定位分析。

最后,我们需要有一个查看平台,可以接收内核在各个客户端监控上报的线上白屏事故,对这些信息进行聚合计算,并提供一个操作界面给到业务方进行监控和问题的定位分析。

4. 线上白屏实战分析

我们的追求不仅是要发现问题,还要能够解决问题,闭环。

5. 白屏飙涨,第一时间发现问题并自动归结原因

比如:从平台收集并聚合出来的信息看,每次白屏事故都伴随一个同样的JS异常,仅这一点,我们几乎可以判断,应该是这个JS异常导致了页面的渲染罗集没有正常执行,结果白屏了。这里要说明下,在发生白屏的时候,内核会同时记录当前页面发生的资源加载失败和JS异常,这些信息会一起上报到平台。这些现场信息经过聚合计算,可以提炼总结出线上事故特征,从而帮助我们解决一类问题,而不只是单个case。

当然,问题原因还是要确认一下,先在本地尝试重现到白屏,确实也发生了同样的JS异常,分析下页面处理逻辑,可以看出来如果不是发生这个JS异常的话,后面会执行k.hidden=!1的操作,也就是让DOM树渲染出来。对于业务方前端来说,因为都是自己的逻辑,这个原因也是一目了然,站点很快就修复了这个问题。

6. V8引擎的bug导致的业务白屏

在这个案例中,我们也是先看到某个JS异常在白屏事件里占了大头的比例。 先确认下这个JS异常是不是导致白屏的直接原因。