这节我们了解一下获取用户访问网页速度和Web应用程序的性能,那如何来获取这些数据呢?我们项目中使用PerformanceTiming 接口来获取当前页面中与时间相关的信息。PerformanceTiming 可以通过只读属性Performance.timing 获得实现该接口的一个对象。
我们先来看一张图,timing API的提供了整个请求的各个阶段的时间信息
PerformanceTiming.navigationStart
- 是一个无符号long long 型的毫秒数,表征了从同一个浏览器上下文的上一个文档卸载(unload)结束时的UNIX时间戳。如果没有上一个文档,这个值会和PerformanceTiming.fetchStart相同。
PerformanceTiming.unloadEventStart
- 是一个无符号long long 型的毫秒数,表征了unload事件抛出时的UNIX时间戳。如果没有上一个文档,or if the previous document, or one of the needed redirects, is not of the same origin, 这个值会返回0.
PerformanceTiming.unloadEventEnd
- 是一个无符号long long 型的毫秒数,表征了unload事件处理完成时的UNIX时间戳。如果没有上一个文档,or if the previous document, or one of the needed redirects, is not of the same origin, 这个值会返回0.
PerformanceTiming.redirectStart
- 是一个无符号long long 型的毫秒数,表征了第一个HTTP重定向开始时的UNIX时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0.
PerformanceTiming.redirectEnd
- 是一个无符号long long 型的毫秒数,表征了最后一个HTTP重定向完成时(也就是说是HTTP响应的最后一个比特直接被收到的时间)的UNIX时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0.
PerformanceTiming.fetchStart
- 是一个无符号long long 型的毫秒数,表征了浏览器准备好使用HTTP请求来获取(fetch)文档的UNIX时间戳。这个时间点会在检查任何应用缓存之前。
PerformanceTiming.domainLookupStart
- 是一个无符号long long 型的毫秒数,表征了域名查询开始的UNIX时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 PerformanceTiming.fetchStart一致。
PerformanceTiming.domainLookupEnd
- 是一个无符号long long 型的毫秒数,表征了域名查询结束的UNIX时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 PerformanceTiming.fetchStart一致。
PerformanceTiming.connectStart
- 是一个无符号long long 型的毫秒数,返回HTTP请求开始向服务器发送时的Unix毫秒时间戳。如果使用持久连接(persistent connection),则返回值等同于fetchStart属性的值。
PerformanceTiming.connectEnd
- 是一个无符号long long 型的毫秒数,返回浏览器与服务器之间的连接建立时的Unix毫秒时间戳。如果建立的是持久连接,则返回值等同于fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。
PerformanceTiming.secureConnectionStart
- 是一个无符号long long 型的毫秒数,返回浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳。如果当前网页不要求安全连接,则返回0。
PerformanceTiming.requestStart
- 是一个无符号long long 型的毫秒数,返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的Unix毫秒时间戳。
PerformanceTiming.responseStart
- 是一个无符号long long 型的毫秒数,返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的Unix毫秒时间戳。如果传输层在开始请求之后失败并且连接被重开,该属性将会被数制成新的请求的相对应的发起时间。
PerformanceTiming.responseEnd
- 是一个无符号long long 型的毫秒数,返回浏览器从服务器收到(或从本地缓存读取,或从本地资源读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的Unix毫秒时间戳。
PerformanceTiming.domLoading
- 是一个无符号long long 型的毫秒数,返回当前网页DOM结构开始解析时(即Document.readyState属性变为“loading”、相应的 readystatechange事件触发时)的Unix毫秒时间戳。
PerformanceTiming.domInteractive
- 是一个无符号long long 型的毫秒数,返回当前网页DOM结构结束解析、开始加载内嵌资源时(即Document.readyState属性变为“interactive”、相应的readystatechange事件触发时)的Unix毫秒时间戳。
PerformanceTiming.domContentLoadedEventStart
- 是一个无符号long long 型的毫秒数,返回当解析器发送DOMContentLoaded 事件,即所有需要被执行的脚本已经被解析时的Unix毫秒时间戳。
PerformanceTiming.domContentLoadedEventEnd
- 是一个无符号long long 型的毫秒数,返回当所有需要立即执行的脚本已经被执行(不论执行顺序)时的Unix毫秒时间戳。
PerformanceTiming.domComplete
- 是一个无符号long long 型的毫秒数,返回当前文档解析完成,即Document.readyState 变为 'complete'且相对应的readystatechange 被触发时的Unix毫秒时间戳。
PerformanceTiming.loadEventStart
- 是一个无符号long long 型的毫秒数,返回该文档下,load事件被发送时的Unix毫秒时间戳。如果这个事件还未被发送,它的值将会是0。
PerformanceTiming.loadEventEnd
- 是一个无符号long long 型的毫秒数,返回当load事件结束,即加载事件完成时的Unix毫秒时间戳。如果这个事件还未被发送,或者尚未完成,它的值将会是0.
重点来了!!!看了以上参数,我们想要的数据来源有了,现在要做的便是去整理这些数据,将他变成我们项目中使用的数据。我们将要收集的时间归为两类:
1.区间阶段耗时
DNS 解析耗时
dns: timing.domainLookupEnd - timing.domainLookupStart
TCP 连接耗时
tcp: timing.connectEnd - timing.connectStart
SSL 安全连接耗时
ssl: timing.connectEnd - timing.secureConnectionStart
Time to First Byte(TTFB),网络请求耗时 TTFB 有多种计算方式,ARMS 以 Google Development 定义为准
ttfb: timing.responseStart - timing.requestStart
数据传输耗时
trans: timing.responseEnd - timing.responseStart
DOM 解析耗时
dom: timing.domInteractive - timing.responseEnd
资源加载耗时
res: timing.loadEventStart - timing.domContentLoadedEventEnd
2.关键性能指标
首包时间
firstbyte: timing.responseStart - timing.domainLookupStart
First Paint Time, 首次渲染时间 / 白屏时间
fpt: timing.responseEnd - timing.fetchStart
Time to Interact,首次可交互时间
tti: timing.domInteractive - timing.fetchStart
HTML 加载完成时间, 即 DOM Ready 时间
ready: timing.domContentLoadedEventEnd - timing.fetchStart
页面完全加载时间
load:timing.loadEventEnd - timing.fetchStart
现在这两部分数据有了,我们就可以将这些数据上传到我们后台服务上去了,是不是很简单呢,^_^。对于如何展示我们收集的数据,请前往hubing.online 瞅一眼哦。
不是很明白?那我再附上一些源码吧
//监听perf
let performanceTime = function () {
var timing = performance.timing;
var loadTime = timing.loadEventEnd - timing.navigationStart;//过早获取时,loadEventEnd有时会是0
if (loadTime <= 0) {
// 未加载完,延迟200ms后继续times方法,直到成功
setTimeout(function () {
performanceTime();
}, 200);
return;
}
uploadUserData(1, {
// 1.区间阶段耗时
// DNS 解析耗时
dns: formatTime(timing.domainLookupEnd - timing.domainLookupStart),
// TCP 连接耗时
tcp: formatTime(timing.connectEnd - timing.connectStart),
// SSL 安全连接耗时
ssl: formatTime(timing.connectEnd - timing.secureConnectionStart),
// Time to First Byte(TTFB),网络请求耗时 TTFB 有多种计算方式,ARMS 以 Google Development 定义为准
ttfb: formatTime(timing.responseStart - timing.requestStart),
// 数据传输耗时
trans: formatTime(timing.responseEnd - timing.responseStart),
// DOM 解析耗时
dom: formatTime(timing.domInteractive - timing.responseEnd),
// 资源加载耗时
res: formatTime(timing.loadEventStart - timing.domContentLoadedEventEnd),
// 2.关键性能指标
// 首包时间
firstbyte: formatTime(timing.responseStart - timing.domainLookupStart),
// First Paint Time, 首次渲染时间 / 白屏时间
fpt: formatTime(timing.responseEnd - timing.fetchStart),
// Time to Interact,首次可交互时间
tti: formatTime(timing.domInteractive - timing.fetchStart),
// HTML 加载完成时间, 即 DOM Ready 时间
ready: formatTime(timing.domContentLoadedEventEnd - timing.fetchStart),
// 页面完全加载时间
load: function () {
return formatTime(timing.loadEventEnd - timing.fetchStart);
}(),
navt: (function () {
let type = "";
switch (performance.navigation.type) {
case 0:
type = 'NAVIGATE';
break;
case 1:
type = 'RELOAD';
break;
case 2:
type = 'BACK_FORWARD';
break;
case 255:
type = 'RESERVED';
break;
}
return type;
})()
});
}
window.addEventListener("load", function () {
performanceTime();
});
喜欢请点个赞呗
或者去github地址Star一下