意义
Find out how you stack up to new industry benchmarks for mobile page speed曾提到随着页面加载时间从1秒增加到10秒,移动站点访问者跳转的概率增加了123%。
相关指标计算
Navigation Timing Level 2
为了帮助开发者更好的衡量和改进前端页面性能,W3C性能小组引入了PerformanceNamvaigationTime API(IE和Safari)不支持。其处理模型如下:
指标解读:
指标 | 含义 |
---|---|
navigationStart | 当卸载提示在同一浏览上下文中的上一个文档终止时. 如果没有以前的文档,则此值将与PerformanceTiming.fetchStart相同 |
unloadEventStart | 引发了unload >事件后,指示窗口中上一个文档开始卸载的时间. 如果没有先前的文档,或者先前的文档或所需的重定向之一不是同一来源,则返回的值为0 |
unloadEventEnd | unload事件处理程序完成时. 如果没有先前的文档,或者先前的文档或所需的重定向之一不是同一来源,则返回的值为0 |
redirectStart | 当第一个HTTP重定向开始时. 如果没有重定向,或者其中一个重定向源不同,则返回值为0 |
redirectEnd | 当最后一个HTTP重定向完成时,即已收到HTTP响应的最后一个字节. 如果没有重定向,或者其中一个重定向源不同,则返回值为0 |
fetchStart | 当浏览器准备好使用HTTP请求获取文档时. 此刻在检查任何应用程序缓存之前 |
domainLookupStart | 域查找开始时. 如果使用持久连接,或者信息存储在缓存或本地资源中,则该值将与PerformanceTiming.fetchStart相同 |
domainLookupEnd | 域查找完成后. 如果使用持久连接,或者信息存储在缓存或本地资源中,则该值将与PerformanceTiming.fetchStart相同. |
connectStart | 当打开连接的请求发送到网络时. 如果传输层报告错误,并且连接建立再次开始,则给出最后的连接建立开始时间. 如果使用持久连接,则该值将与PerformanceTiming.fetchStart相同 |
connectEnd | 打开连接网络时. 如果传输层报告错误,并且连接建立再次开始,则给出最后的连接建立结束时间. 如果使用持久连接,则该值将与PerformanceTiming.fetchStart相同. 当所有安全连接握手或SOCKS身份验证终止时,连接被视为已打开 |
secureConnectionStart | 安全连接握手开始时. 如果不请求此类连接,则返回0 |
responseStart | 当浏览器从服务器从缓存或本地资源接收到响应的第一个字节时 |
responseEnd | 当浏览器收到响应的最后一个字节时,或者如果第一次发生则关闭连接时,包括来自服务器,缓存或本地资源 |
domLoading | 解析器开始工作时,即其Document.readyState更改为'loading'并且引发了相应的readystatechange事件 |
domInteractive | 解析器完成对主文档的工作时,即其Document.readyState更改为'interactive'并且引发了相应的readystatechange事件 |
domContentLoadedEventStart | DOM解析完成后,在解析器发送DOMContentLoaded事件之前,网页内资源开始加载的时间 |
domContentLoadedEventEnd | DOM解析完成后,在所有需要尽快执行的脚本(无论是否按顺序执行)之后 |
domComplete | 解析器完成对主文档的工作时,即其Document.readyState更改为'complete'并且引发了相应的readystatechange事件 |
loadEventStart | 为当前文档发送load事件的时间. 如果尚未发送此事件,则返回0 |
loadEventEnd | 当load事件处理程序终止时,即加载事件完成时. 如果此事件尚未发送或尚未完成,则返回0 |
页面性能相关指标
首字节(time to first byte, TTFB)
主文档返回第一个字节的时间,是页面加载性能比较重要的指标。对用户来说一般无感知,对于开发者来说,则代表访问网络后端的整体响应耗时。
let ttfb = time.responseStart - time.navigationStart
白屏时间 (first paint, FP)
用户看到页面展示出现一个元素的时间。很多人认为白屏时间是页面返回的首字节时间,但这样其实并不精确,因为头部资源还没加载完毕,页面也是白屏。
相对来说具备「白屏时间」统计意义的指标,可以取 domLoading - fetchStart,此时页面开始解析DOM树,页面渲染的第一个元素也会很快出现。
从W3C Navigation Timing Level 2 的方案设计,可以直接采用 domInteractive - fetchStart ,此时页面资源加载完成,即将进入渲染环节。
let firstPaint = (t.domInteractive || t.domLoading) - t.fetchStart;
首屏时间
首屏时间是指页面第一屏所有资源完整展示的时间。这是一个对用户来说非常直接的体验指标,但是对于前端却是一个非常难以统计衡量的指标。
具备一定意义上的指标可以使用,domContentLoadedEventEnd - fetchStart,甚至使用loadEventStart - fetchStart,此时页面DOM树已经解析完成并且显示内容。
页面加载时间(page load time)
let pageloadtime = time.loadEventStart - time.navigationStart
dom ready time
let domReadyTime = time.domContentLoadedEventEnd - time.fetchStart
dome ready和page load两个指标有相应的事件监听,即document的DOMContentLoaded和window.onload,也可以直接在事件回调里打点。
重定向时间
let redirectTime = time.redirectEnd - time.redirectStart
卸载页面的时间
let unloadTime = time.unloadEventEnd - time.unloadEventStart
解析dom树耗时
let analysisTime = time.domComplete - time.domInteractive
DNS查找时间
let dns = time.domainLookupEnd - time.domainLookupStart
TCP
tcp = time.connectEnd - time.connectStart
SSL negotiation
如果不可用,则secureConnectionStart将是undefined;如果未使用https,则将为0;如果已使用,则将使用时间戳。
ssl = time.requestStart - time.secureConnectionStart
SPA
但随着 SPA 模式的盛行,页面内容渲染的时机被改变了,W3C 标准无法完全满足原来的监控意义。可以参考谷歌力推的以用户为中心的性能指标:
视觉反馈 | 页面状态 | 性能指标 |
---|---|---|
是否发生? | 导航是否成功启动?服务器是否有响应? | 首次绘制 (FP)/首次内容绘制 (FCP) |
是否有用? | 是否已渲染可以与用户互动的足够内容? | 首次有效绘制 (FMP)/主角元素计时 |
是否可用? | 用户可以与页面交互,还是页面仍在忙于加载? | 可交互时间 (TTI) |
是否令人愉快? | 交互是否顺畅而自然,没有滞后和卡顿? | 耗时较长的任务(在技术上不存在耗时较长的任务) |
对应的指标如下图所示:
Google也提供了一些新的API,来获取相应的指标值。计算方式可参考以用户为中心的性能指标
数据上报方式
测量好时间后,就需要将数据发送给服务端。页面性能统计数据对丢失率要求比较低,且性能统计应该在尽量不影响主流程的逻辑和页面性能的前提下进行。
使用的img标签get请求
- 不存在AJAX跨域问题,可做跨源的请求
- 很古老的标签,没有浏览器兼容性问题
var i = new Image();
i.onload = i.onerror = i.onabort = function () {
i = i.onload = i.onerror = i.onabort = null;
}
i.src = url;
navigator.sendBeacon
- 大部分现代浏览器都支持
- navigator.sendBeacon方法。这个方法可以用来发送一些统计和诊断的小量数据,特别适合上报统计的场景。
- 数据可靠,浏览器关闭请求也照样能发
- 异步执行,不会影响下一页面的加载
- API使用简单
window.addEventListener('unload', logData, false);
function logData() {
navigator.sendBeacon("/log", analyticsData);
}
所以,当浏览器支持sendBeacon方法时,优先使用该方法,否则使用img方式上报。
参考文档
- 阿里 UC 团队」如何在10 分钟内,彻底搞懂前端页面性能监控?
- 以用户为中心的性能指标
- Find out how you stack up to new industry benchmarks for mobile page speed
- Navigation Timing API
- Navigation Timing Level 2