前言
话不多说,先看效果:
是不是首屏数据一目了然~
当然 f12-performance也可以查看很多性能相关数据(本文暂不概述)
快速通道:直接划到底,CV 代码至项目根目录文件即可尝鲜~
window.performance的作用
是浏览器暴露给js的一个接口,可以通过这个接口查看用户访问网站的连接建立时间、dns时间等信息。window.performance属性则可以获得更为精确的原始数据,以毫秒为单位,精确到微秒。使用该api时需要在页面完全加载完成之后才能使用,最简单的办法是在window.onload事件中读取各种数据,因为很多值必须在页面完全加载之后才能得出。
window.performance.timing属性介绍
上图
window.performance.timing的执行顺序图
按触发顺序排列所有属性:
navigationStart:在同一个浏览器上下文中,前一个网页(与当前页面不一定同域)unload 的时间戳,如果无前一个网页 unload ,则与 fetchStart 值相等
unloadEventStart:前一个网页(与当前页面同域)unload 的时间戳,如果无前一个网页 unload 或者前一个网页与当前页面不同域,则值为 0
unloadEventEnd:和 unloadEventStart 相对应,返回前一个网页 unload 事件绑定的回调函数执行完毕的时间戳
redirectStart:第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0
redirectEnd:最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内的重定向才算,否则值为 0
fetchStart:浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前
domainLookupStart:DNS 域名查询开始的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
domainLookupEnd:DNS 域名查询完成的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
connectStart:HTTP(TCP) 开始建立连接的时间,如果是持久连接,则与 fetchStart 值相等,如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接开始的时间
connectEnd:HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等,如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接完成的时间
注意: 这里握手结束,包括安全连接建立完成、SOCKS 授权通过
secureConnectionStart:HTTPS 连接开始的时间,如果不是安全连接,则值为 0
requestStart:HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存,连接错误重连时,这里显示的也是新建立连接的时间
responseStart:HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存
responseEnd:HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存
domLoading:开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 loading,并将抛出 readystatechange 相关事件
domInteractive:完成解析 DOM 树的时间,Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件
注意: 只是 DOM 树解析完成,这时候并没有开始加载网页内的资源
domContentLoadedEventStart:DOM 解析完成后,网页内资源加载开始的时间,文档发生 DOMContentLoaded事件的时间
domContentLoadedEventEnd:DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕),文档的DOMContentLoaded 事件的结束时间
domComplete:DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete,并将抛出 readystatechange 相关事件
loadEventStart:load 事件发送给文档,也即 load 回调函数开始执行的时间,如果没有绑定 load 事件,值为 0
loadEventEnd:load 事件的回调函数执行完毕的时间,如果没有绑定 load 事件,值为 0
performance.timing和PerformanceNavigationTiming的区别
当我兴致勃勃的在项目中使用performance.timing coding时会提示timing 已弃用(???黑人问号,那还玩个锤子!整半天你们都准备扔掉了。)
那就先简单的看看新的替代方案吧:Level 2的PerformanceNavigationTiming
PerformanceNavigationTiming的获取方式:
1、window.performance.getEntriesByType(navigation)[0]
2、window.performance.getEntries()[0]
对比
window.performance.timing:
PerformanceNavigationTiming:
通过对比我们可以看到:
- performance.timing单位是时间戳(ms 级别)
- PerformanceNavigationTiming的单位是相对于文档开始的时间
- 其次PerformanceNavigationTiming中的数据会更全,精度更准确一些
- PerformanceNavigationTiming(Navigation Timing Level2)的兼容性可能还存在问题
再回过头仔细看下 W3C(W3C Editor's Draft)
emm。。。
既然如此我们接下来再补充下PerformanceNavigationTiming吧
PerformanceNavigationTiming
PerformanceNavigationTiming的执行顺序图(Navigation Timing Level2模型)
(更详细标准的解释请参看:W3C Editor's Draft)
PerformanceNavigationTiming属性简介
大多属性和上文的performance.timing基本类似,由上图可以看出PerformanceNavigationTiming中没有 navigationStart,取而代之的是 startTime(其实就是0),而其他属性不再以navigationStart为偏移值,而是以startTime 为偏移值。
duration 就是loadEventEnd 和 startTime 之间的差值,也就是我们的页面 load 总耗时。
常用计算性能指标
网页重定向的耗时:redirectEnd - redirectStart
检查本地缓存的耗时: domainLookupStart - fetchStart
DNS查询的耗时:domainLookupEnd - domainLookupStart
TCP连接的耗时:connectEnd - connectStart
从客户端发起请求到接收到响应的时间 / TTFB:responseStart - fetchStart
首次渲染时间/白屏时间:responseStart - pnt.startTime
下载服务端返回数据的时间:responseEnd - responseStart
request请求耗时:responseEnd - requestStart
解析dom树耗时:domComplete - domInteractive
dom加载完成的时间:domContentLoadedEventEnd
页面load的总耗时:duration
代码
可以 cv 至自己的项目根文件下试试
// performance
const times = () => {
const performance = window.performance;
if (performance) {
setTimeout(() => { //异步获取, 同步获取时duration等值可能获取不到
const pnt: any = performance.getEntriesByType('navigation')[0]
console.log(pnt, 'performance');
const column = [
{
key: 'Redirect',
desc: '网页重定向的耗时',
value: pnt.redirectEnd - pnt.redirectStart,
},
{
key: 'AppCache',
desc: '检查本地缓存的耗时',
value: pnt.domainLookupStart - pnt.fetchStart,
},
{
key: 'DNS',
desc: 'DNS查询的耗时',
value: pnt.domainLookupEnd - pnt.domainLookupStart,
},
{
key: 'TCP',
desc: 'TCP连接的耗时',
value: pnt.connectEnd - pnt.connectStart,
},
{
key: 'Waiting(TTFB)',
desc: '从客户端发起请求到接收到响应的时间 / Time To First Byte',
value: pnt.responseStart - pnt.fetchStart,
},
{
key: '白屏时间',
desc: '首次渲染时间/白屏时间',
value: pnt.responseStart - pnt.startTime,
},
{
key: 'Content Download',
desc: '下载服务端返回数据的时间',
value: pnt.responseEnd - pnt.responseStart,
},
{
key: 'request',
desc: 'request请求耗时',
value: pnt.responseEnd - pnt.requestStart,
},
{
key: 'dom树',
desc: '解析dom树耗时',
value: pnt.domComplete - pnt.domInteractive,
},
{
key: 'DOMContentLoaded',
desc: 'dom加载完成的时间',
value: pnt.domContentLoadedEventEnd,
},
{
key: 'Loaded',
desc: '页面load的总耗时',
value: pnt.duration
},
];
// tslint:disable-next-line:no-console
console && console.table && console.table(column);
}, 0)
}
}
window.addEventListener('load', times); // onload 事件触发