摘要:如何自动获取首屏时间作者刘远洋公司微店前端团队日期本文发表在微店前端团队背景在前端性能数据的获取方法上,现在业内大多使用手动埋点的方式,即在代码中,人工判断首屏完成的位置,并在该处添加首屏记录的代码,类似这样。
如何自动获取首屏时间
作者:刘远洋
公司:微店 - 前端团队
日期:2018-03-05
本文发表在 微店前端团队 blog
背景在前端性能数据的获取方法上,现在业内大多使用手动埋点的方式,即在代码中,人工判断首屏完成的位置,并在该处添加首屏记录的代码,类似:firstscreen.report() 这样。
这样做的简单省事,但缺点也很明显:
和业务代码混用
通用的监控需求混入了业务代码中
覆盖不完整
需要页面开发者自觉手动添加埋点代码,在业务中埋点覆盖率不一定能达到 100%
准确性不一定高
由于需要开发者自行判断统计脚本放置的位置,就会存在一些不准确的情况,因为每个人对首屏的理解不同
基于上面的分析,我们近期尝试了一些方案,试图将首屏时间计算自动化,节省人力、并提高准确性。
定义对首屏时间的定义,每个公司可能会有所不同,在本文中,首屏时间指的是:
如果页面首屏有图片
首屏时间 = 首屏图片全部加载完毕的时刻 - window.performance.timing.navigationStart
如果页面首屏没有图片
首屏时间 = 页面处于稳定状态前最后一次 dom 变化的时刻 - window.performance.timing.navigationStart实现原理
总体思路为:
从页面加载开始,按照一定的间隔打点,不断记录各个时刻下页面首屏图片列表和其他信息
问题:按照怎样的间隔打点?
找出页面首屏处于稳定状态的时刻 T1(到这个时刻为止,页面首屏可能已经稳定了一段时间)
问题:如何找出这个 T1?
以 T1 时刻的首屏图片数量为准,向前倒推,找到所有打点中最后一次和 T1 时刻首屏图片一致的打点时刻 T2
统计 T2 时刻的所有图片加载完成时间 T3
T3 即为首屏完成的时刻,进行上报
下面,一个个解决上文中提到的问题:
问题:如何找出首屏处于稳定状态的时刻 T1?
我们将页面从加载到渲染分为两大阶段:1. 获取数据;2. 数据获取完毕,渲染页面。
这个逻辑符合绝大部分的页面逻辑:先获取数据,再渲染页面。
解决方案:
通过 AOP 切面方式监听 XHR 的 send 对象,抓取页面中的第一个 XHR 请求,以第一个 XHR 请求发出的时刻为起点,统计在 1000ms 以内所有发出的请求到数组 Request 中。
我们认为可能影响首屏的请求在 [第一个 xhr 请求发出的时刻,第一个 xhr 请求发出的时刻 + 1000ms] 的时间段内均已发出。
针对串联型的请求(即下一个请求依赖上一个请求的返回数据),同时统计每个请求返回后,500ms 以内新发出的请求到数组 Request 中。
有些页面的数据请求方式是串行的,可能经过两个串联的请求后首屏的数据才能加载。
影响首屏的请求可能也会以这样的形式发出。
数组 Request 中统计到的请求,基本包含了所有影响首屏的数据请求,同时也包含了部分不影响首屏的数据请求。
针对上述统计到的请求,找到所有数据返回的时刻 T1,然后,T1 = T1 + 300ms,保证页面接收数据后渲染完毕(300ms 用于一次渲染足够了)。
此时的 T1 时刻,页面首屏被认为处于稳定状态。
问题:按照怎样的间隔打点?
MutationObserver
大家都知道 MutationObserver 对象用于捕捉页面 dom 变化,因此在脚本中,我们使用了 MutationObserver 监听 dom 变化,并在每次 dom 变化时触发一次打点(统计该时刻首屏图片信息)
setInterval
setInterval 也能实现定时打点
MutationObserver 和 setInterval 组合
但 MutationObserver 回调函数的触发时机开发者并不可控,有几种情况:
两次回调之间可能距离几百毫秒甚至 1秒多,导致统计误差较大
某些情况下,dom 不再变化,但页面元素中,img 的 src 发生了变化或元素的 background-image 发生了变化,并不会触发在 MutationObserver 的回调,导致统计失误
因此,我们现在的方案是结合 MutationObserver 和 setInterval,在 MutationObserver 回调的间歇,启动 setInterval,保证页面加载过程中打点间隔不会过长,提高统计准确率。
统计误差即使使用了上述复杂的打点与判断,误差仍然存在,那么,误差到底在哪里?
如下图所示:
不稳定状态(1 images) 稳定状态2(2 images) 稳定状态1(2 images) | | | |________________________|_______________________| t1 t2 t3
按照上面的理论,我们会取 t2 时刻为可以统计首屏的时刻,两张图片加载完成的时刻即为首屏完成的时刻。
t2 和 t1 时刻差了 1 张图片。
按照我们的理论,首屏完成时间一定在 t2 之后的某个时刻 t2.n。
而实际相差的那张图片,什么时候加载完成的,我们不得而知,可能在 t2 前已经加载完毕了,也可能已经发出请求,但还没加载完毕。
误差就在这里,它总会存在。
但我们需要统计的是在误差可以接受范围内的首屏数据,根据在公司业务实践的反馈来看,数据可靠性很高。
Talk is cheap, show me the code我们也开源了这个小工具:
github: auto-compute-first-screen-time
npm: auto-compute-first-screen-time
欢迎小伙伴们使用,吐槽,改进。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/93158.html
摘要:经过一系列优化后,在平台上,点击到页面首屏展示的耗时从平均多降低为,优化以上。而现在页面为了更好地为用户推荐喜欢的内容,我们后台引入机器学习和随机算法来做智能个性化推荐。另外还有部分的内容是随机算法推荐的。 VasSonic成长历程 前言 2017.8.8 14时,SNG增值产品部Vas团队研发的轻量级高性能Hybrid框架VasSonic通过了公司最终审核,作为腾讯开源组件分享给大...
摘要:关于首屏首屏时间是指从转向该页面到屏幕中该页面所有内容都可见时的时间。如在事件处理函数中,计算高度,如果大于屏幕高度则意味着首屏的结构已渲染完毕,开始计算首屏时间。 关于首屏 首屏时间是指从转向该页面到屏幕中该页面所有内容都可见时的时间。已经有太多的关于首屏时间的计算,在本文中并不重复阐述这些已经被提出或者实现的方案,而旨在探索与讨论更多的首屏自动化采集方案,扩大思考范围,你我思想之间...
摘要:关于首屏首屏时间是指从转向该页面到屏幕中该页面所有内容都可见时的时间。如在事件处理函数中,计算高度,如果大于屏幕高度则意味着首屏的结构已渲染完毕,开始计算首屏时间。 关于首屏 首屏时间是指从转向该页面到屏幕中该页面所有内容都可见时的时间。已经有太多的关于首屏时间的计算,在本文中并不重复阐述这些已经被提出或者实现的方案,而旨在探索与讨论更多的首屏自动化采集方案,扩大思考范围,你我思想之间...
阅读 1608·2021-11-23 10:07
阅读 2603·2019-08-30 11:10
阅读 2819·2019-08-29 17:08
阅读 1757·2019-08-29 15:42
阅读 3128·2019-08-29 12:57
阅读 2379·2019-08-28 18:06
阅读 3508·2019-08-27 10:56
阅读 363·2019-08-26 11:33