前端性能监控的关注点有很多,这篇文章主要介绍Web API之performance属性和使用。
一、属性
在浏览器下方打印window可以看到里面的performance属性,展开后可以看到里面有数十条属性,下面用表格的形式列一下对应属性的说明。
| 属性 | 说明 | 用途 |
| --------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| performance.eventCounts | 它记录了所有已经分发过的 Event,处理时间是否大于 50ms。 | |
| performance.memory | 记录内存属性 | |
| performance.memory.jsHeapSizeLimit | 上下文内可用堆的最大体积,以字节计算。 | |
| performance.memory.totalJSHeapSize | 已分配的堆体积,以字节计算。 | |
| performance.memory.usedJSHeapSize | 当前 JS 堆活跃段(segment)的体积,以字节计算。 | |
| performance.navigation | 表示出现在当前浏览上下文的 navigation 类型,比如获取某个资源所需要的重定向次数。 | |
| performance.navigation.redirectCount | 表示在到达这个页面之前重定向了多少次。 | |
| performance.navigation.type | 表示是如何导航到这个页面的。 | 检测页面时如何跳转过来的 |
| performance.onresourcetimingbufferfull | 一个回调的 [`EventTarget`](https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget),当触发 `resourcetimingbufferfull` 事件的时候会被调用。 | 一个回调函数 |
| performance.timeOrigin | 返回性能测量开始时的时间的高精度时间戳。 | |
| performance.timing | 包含延迟相关的性能信息。根据w3c标准,该属性将来会被performanceTiming取代。 | 可以从该属性下获取浏览器首屏渲染期间发生各事件的时间戳,用于页面性能分析。 |
| performance.timing.navigationStart | 表征了从同一个浏览器上下文的上一个文档卸载(unload)结束时的UNIX时间戳。如果没有上一个文档,这个值会和PerformanceTiming.fetchStart相同。 | |
| performance.timing.unloadEventStart | 表征了`unload (en-US)`事件抛出时的UNIX时间戳。在没有上一个文档、重定向、不同源的情况下, 这个值会返回0。 | |
| performance.timing.unloadEventEnd | 表征了`unload (en-US)`事件处理完成时的UNIX时间戳。在没有上一个文档、重定向、不同源的情况下, 这个值会返回0。 | |
| performance.timing.redirectStart | 表征了第一个HTTP重定向开始时的UNIX时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0。 | |
| performance.timing.redirectEnd | 表征了最后一个HTTP重定向完成时(也就是说是HTTP响应的最后一个比特直接被收到的时间)的UNIX时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0。 | |
| performance.timing.fetchStart | 表征了浏览器准备好使用HTTP请求来获取(fetch)文档的UNIX时间戳。这个时间点会在检查任何应用缓存之前。 | 可作为性能检测的起始时间点 |
| performance.timing.domainLookupStart | 表征了域名查询开始的UNIX时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 `PerformanceTiming.fetchStart一致。` | |
| performance.timing.domainLookupEnd | 表征了域名查询结束的UNIX时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 `PerformanceTiming.fetchStart一致。` | DNS解析完成的时间点 |
| performance.timing.connectStart | 返回HTTP请求开始向服务器发送时的Unix毫秒时间戳。如果使用持久连接(persistent connection),则返回值等同于fetchStart属性的值。 | |
| performance.timing.connectEnd | 返回浏览器与服务器之间的连接建立时的Unix毫秒时间戳。如果建立的是持久连接,则返回值等同于fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。 | |
| performance.timing.secureConnectionStart | 返回浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳。如果当前网页不要求安全连接,则返回0。 | |
| performance.timing.requestStart | 返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的Unix毫秒时间戳。 | 开始发送http请求(获取资源文件)的时间点 |
| performance.timing.responseStart | 返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的Unix毫秒时间戳。如果传输层在开始请求之后失败并且连接被重开,该属性将会被数制成新的请求的相对应的发起时间。 | |
| performance.timing.responseEnd | 返回浏览器从服务器收到(或从本地缓存读取,或从本地资源读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的Unix毫秒时间戳。 | html文件获取完成的时间点 |
| performance.timing.domLoading | 返回当前网页DOM结构开始解析时(即[`Document.readyState`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState)属性变为“loading”、相应的 `readystatechange (en-US)`事件触发时)的Unix毫秒时间戳。 | |
| performance.timing.domInteractive | 返回当前网页DOM结构结束解析、开始加载内嵌资源时(即[`Document.readyState`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState)属性变为“interactive”、相应的`readystatechange (en-US)`事件触发时)的Unix毫秒时间戳。 | |
| performance.timing.domContentLoadedEventStart | 返回当解析器发送`DOMContentLoaded (en-US)` 事件,即所有需要被执行的脚本已经被解析时的Unix毫秒时间戳。 | 注意,这里并不是说JS脚本开始执行的时间,而是说html文档加载完毕,并且 html 所引用的内联 js、以及外链 js 的同步代码都执行完毕后触发。 |
| performance.timing.domContentLoadedEventEnd | 返回当所有需要立即执行的脚本已经被执行(不论执行顺序)时的Unix毫秒时间戳。 | 需要执行的JS脚本执行完毕的时间 |
| performance.timing.domComplete | 返回当前文档解析完成,即[`Document.readyState`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/readyState) 变为 `'complete'且相对应的``readystatechange (en-US)` 被触发时的Unix毫秒时间戳。 | |
| performance.timing.loadEventStart | 返回该文档下,`load (en-US)`事件被发送时的Unix毫秒时间戳。如果这个事件还未被发送,它的值将会是0。 | |
| performance.timing.loadEventEnd | 返回当`load (en-US)`事件结束,即加载事件完成时的Unix毫秒时间戳。如果这个事件还未被发送,或者尚未完成,它的值将会是0。 | 可作为首屏渲染完成时间 |
二、用途
从上面表格里记录的参数用途来看,我们应该在页面渲染完成后使用该参数,避免loadEventEnd为0,获取对应参数信息并上传到日志中去。
下面做一个测试,对应的html如下。
```
let sum1 = 0
for (let i = 0; i < 99999999; i++) {
sum1 += 1
}
let sum2 = 0
for (let i = 0; i < 99999999; i++) {
sum2 += 2
}
learn
.my-div {
font-size: 20px;
}
let sum3 = 0
for (let i = 0; i < 99999999; i++) {
sum3 += 1
}
window.onload = function () {
let t = performance.timing
console.log('DNS查询耗时 :' + (t.domainLookupEnd - t.domainLookupStart).toFixed(0))
console.log('TCP链接耗时 :' + (t.connectEnd - t.connectStart).toFixed(0))
console.log('request请求耗时 :' + (t.responseEnd - t.responseStart).toFixed(0))
console.log('解析dom树耗时 :' + (t.domComplete - t.domInteractive).toFixed(0))
console.log('白屏时间 :' + (t.responseStart - t.navigationStart).toFixed(0))
console.log('js脚本执行时间 :' + (t.domContentLoadedEventEnd - t.domContentLoadedEventStart).toFixed(0))
console.log('首屏渲染时间 :' + (t.loadEventEnd - t.navigationStart).toFixed(0))
console.log('js内存使用占比 :' + (t.usedJSHeapSize / t.totalJSHeapSize * 100).toFixed(2) + '%')
}
```
查看对应结果
DNS查询耗时 :0
test-html.html:42 TCP链接耗时 :0
test-html.html:43 request请求耗时 :1
test-html.html:44 解析dom树耗时 :0
test-html.html:45 白屏时间 :0
test-html.html:46 js脚本执行时间 :0
test-html.html:47 首屏渲染时间 :2183
js内存使用占比 :100.00%
可以看到脚本的执行耽误了首屏渲染的时间。这样也可以指引我们在工作中的一些优化。