前端性能监控之Performance

2,865 阅读5分钟

为什么要监控页面性能 ?

一个页面性能的会很大地影响用户体验。用户打开页面等待的太久,可能会直接关掉页面,甚至就不再使用了。我们经常提到页面优化,其实就是要让页面更快地显示和响应。 通常一个页面有三个阶段:加载阶段交互阶段关闭阶段

  1. 加载阶段,是指从发出请求到渲染出完整页面的过程,影响到这个阶段的主要因素有网络和 JavaScript 脚本。
  2. 交互阶段,主要是从页面加载完成到用户交互的整合过程,影响到这个阶段的主要因素是 JavaScript 脚本。
  3. 关闭阶段,主要是用户发出关闭指令后页面所做的一些清理操作。 那么页面性能监控主要是监控页面加载阶段的情况。那么就要引入对页面性能监控数据采集尤为重要的Performance 接口。

Performance 接口

Performance 接口可以获取到当前页面中与性能相关的信息。它是 High Resolution Time API 的一部分,同时也融合了 Performance Timeline API、Navigation Timing API、 User Timing API 和 Resource Timing API

其中导航计时(Navigation Timing) API 是 Web 性能 API 的起点。 在[ NAVIGATION-TIMING ]中,通过访问 window.performance.navigation,您将获得一个 PerformanceNavigationTiming 实例,该实例提供有关页面性能的与时间相关的信息。

用户计时(User Timing)接口允许开发人员创建特定于应用程序的时间戳,这些时间戳是浏览器性能时间表的一部分。有两种类型的用户定义计时事件类型: “标记”事件类型和“度量”事件类型。

资源计时(Resource Timing)接口允许检索和分析与应用程序资源加载有关的详细网络定时数据。应用程序可以使用计时指标来确定加载特定资源(例如 XMLHttpRequest、 < svg > 、 image 或脚本)所需的时间长度。

  • 下图是 Navigation Timing 的处理模型。 image.png 按照如上图的顺序,我们来分别看下各个字段的含义如下:

navigationStart  同一个浏览器上一个页面卸载结束时的时间戳。如果没有上一个页面的话,那么该值会和fetchStart的值相同。

redirectStart:  第一个http重定向开始的时间戳,如果没有重定向,或者重定向到一个不同源的话,那么该值返回为0.

redirectEnd:  最后一个HTTP重定向完成时的时间戳。如果没有重定向,或者重定向到一个不同的源,该值也返回为0.

fetchStart:  浏览器准备好使用http请求抓取文档的时间(发生在检查本地缓存之前)。

domainLookupStart:  DNS域名查询开始的时间,如果使用了本地缓存或持久链接,该值则与fetchStart值相同。

domainLookupEnd:  DNS域名查询完成的时间,如果使用了本地缓存或持久链接,该值则与fetchStart值相同。

connectStart:  HTTP 开始建立连接的时间,如果是持久链接的话,该值则和fetchStart值相同,如果在传输层发生了错误且需要重新建立连接的话,那么在这里显示的是新建立的链接开始时间。

secureConnectionStart:  HTTPS 连接开始的时间,如果不是安全连接,则值为 0

connectEnd: HTTP完成建立连接的时间(完成握手)。如果是持久链接的话,该值则和fetchStart值相同,如果在传输层发生了错误且需要重新建立连接的话,那么在这里显示的是新建立的链接完成时间。

requestStart:  http请求读取真实文档开始的时间,包括从本地读取缓存,链接错误重连时。

responseStart:  开始接收到响应的时间(获取到第一个字节的那个时候)。包括从本地读取缓存。

responseEnd:  HTTP响应全部接收完成时的时间(获取到最后一个字节)。包括从本地读取缓存。

unloadEventStart:  前一个网页(和当前页面同域)unload的时间戳,如果没有前一个网页或前一个网页是不同的域的话,那么该值为0.

unloadEventEnd:  和 unloadEventStart 相对应,返回是前一个网页unload事件绑定的回调函数执行完毕的时间戳。

domLoading:  开始解析渲染DOM树的时间。

domInteractive:  完成解析DOM树的时间(只是DOM树解析完成,但是并没有开始加载网页的资源)。

domContentLoadedEventStart: DOM解析完成后,网页内资源加载开始的时间。
domContentLoadedEventEnd:  DOM解析完成后,网页内资源加载完成的时间。
domComplete:  DOM树解析完成,且资源也准备就绪的时间。Document.readyState 变为 complete,并将抛出 readystatechange 相关事件。

loadEventStart:  load事件发送给文档。也即load回调函数开始执行的时间,如果没有绑定load事件,则该值为0.
loadEventEnd:  load事件的回调函数执行完毕的时间,如果没有绑定load事件,该值为0.

Performance.timing 属性

window.performance.timing 获取一个 PerformanceTiming 对象,这个对象包括了页面相关的性能信息。

image.png 建议您使用 performance.getEntriesByType("Resource")方法为每个请求的资源获取一个资源计时对象数组。举个简单的栗子:

<!doctype html>
<html>
  <head>
  </head>
  <body onload="getResourceTiming()">
    <script>
       function getResourceTiming() {
           var resourceList = window.performance.getEntriesByType("resource");// 获取资源列表
           for (var i = 0; i < resourceList.length; i++) {
              // 计算请求图片资源的耗时
              if (resourceList[i].initiatorType == "img") {
                 alert("获取图片资源耗时: " + (resourceList[i].responseEnd - resourceList[i].startTime));
              }
           }
       }
    </script>
    <img id="image0" src="https://www.w3.org/Icons/w3c_home.png">
  </body>
</html>

白屏时间

用户看到页面展示出现一个元素的时间。
从W3C Navigation Timing Level 2 的方案设计,可以直接采用 domInteractive - fetchStart  获取耗时,此时页面资源加载完成,即将进入渲染环节。

首屏时间

首屏时间是指页面第一屏所有资源完整展示的时间。这是一个对用户来说非常直接的体验指标,但是对于前端却是一个非常难以统计衡量的指标。可以使用 domContentLoadedEventEnd - fetchStart 获取耗时,此时页面DOM树已经解析完成并且显示内容

参考文章链接:

  1. MDN Web API 接口参考: developer.mozilla.org/zh-CN/docs/…
  2. 10分钟彻底搞懂前端页面性能监控: zhuanlan.zhihu.com/p/82981365
  3. W3C github resource-timing: w3c.github.io/perf-timing…