借助渐进式 Web 应用,开发者可以构建一类全新的应用,以提供可靠、高性能的用户体验。 但为了确保 Web 应用实现所需的性能目标,开发者需要访问高分辨率的性能衡量数据。W3C 性能时间轴规范定义了一个此类接口,供浏览器以编程方式访问低层级时间数据。这就打开了一些有趣的用例的大门:
- 离线和自定义性能分析
- 第三方效果分析和可视化工具
- 将性能评估集成到 IDE 和其他开发者工具中
在大多数主流浏览器中,已经可以在导航时间、资源计时和用户计时方面访问此类计时数据。最新增加的是 Performance Observer 接口,它本质上是一个流式传输接口,用于根据浏览器收集的低级时间信息异步收集低级时间信息。与以前的时间轴访问方法相比,这个新接口具有许多关键优势:
- 如今,应用必须定期轮询和区分存储的测量值,成本很高。该接口会为它们提供回调。(换句话说,不需要轮询)。因此,使用此 API 的应用响应速度更快、效率更高。
- 它不受缓冲区限制的约束(大多数缓冲区默认设置为 150 个项),并且可以避免可能需要修改缓冲区的不同使用方之间的竞态条件。
- 性能观察者通知以异步方式传送,浏览器可以在空闲时间调度这些通知,以避免与关键渲染工作发生争用。
从 Chrome 52 开始,性能观察器界面默认处于启用状态。我们来看看如何使用它。
<html>
<head>
<script>
var observer = new PerformanceObserver(list => {
list.getEntries().forEach(entry => {
// Display each reported measurement on console
if (console) {
console.log("Name: " + entry.name +
", Type: " + entry.entryType +
", Start: " + entry.startTime +
", Duration: " + entry.duration + "\n");
}
})
});
observer.observe({entryTypes: ['resource', 'mark', 'measure']});
performance.mark('registered-observer');
function clicked(elem) {
performance.measure('button clicked');
}
</script>
</head>
<body>
<button onclick="clicked(this)">Measure</button>
</body>
</html>
下面这个简单的网页以定义一些 JavaScript 代码的脚本代码开头:
- 我们会实例化一个新的
PerformanceObserver
对象,并将事件处理脚本函数传递给对象构造函数。该构造函数会初始化该对象,以便每次准备好处理一组新的测量数据(测量数据作为对象列表进行传递)时,系统都会调用我们的处理程序。此处的处理程序定义为匿名函数,仅用于在控制台中显示格式化的测量数据。在实际场景中,这些数据可能会存储在云端以进行后续分析,或传输到交互式可视化工具中。 - 我们通过
observe()
方法注册感兴趣的计时事件类型,并调用mark()
方法以标记注册时间点,我们将这一时间视为计时间隔的开始时间。 - 我们为页面正文中定义的按钮定义了一个点击处理程序。此点击处理程序会调用
measure()
方法以捕获有关何时点击按钮的时间数据。
在页面的正文中,我们定义一个按钮,为 onclick
事件分配点击处理程序,然后就可以开始了。
现在,如果我们加载页面并打开 Chrome 开发者工具面板以查看 JavaScript 控制台,则每次点击该按钮时,系统都会进行性能测量。由于我们已针对此类测量结果进行注册,因此它们会被异步转发到我们的事件处理脚本,而无需轮询时间轴,时间轴会在测量结果发生时将其显示在控制台中:
start
值表示 mark
类型的事件(此应用只有一个事件)的开始时间戳。measure
类型的事件没有固有的开始时间;它们表示相对于上一个 mark
事件进行的时间测量。因此,此处看到的时长值表示调用 mark()
(用作公共间隔的起点)与多次后续调用 measure()
之间的间隔时间。
如您所见,此 API 非常简单,它无需轮询即可收集经过过滤的高分辨率实时性能数据,这可以为 Web 应用开启更高效的性能工具的大门。