使用 Paint Timing API 提高性能

yellowleopard 发布于1年前
0 条问题

使用 Paint Timing API 提高性能

本文为译文,原文地址:[ Improving Performance with the Paint Timing API ] ,作者,@Umar Hansa

介绍

传统上,前端性能主要集中在页面加载时间上,来作为重要的性能指标。商业网站性能将显示后端方面的粒度级的性能指标,如数据库查找时间、模板编译、服务器响应时间等等。

然而,当涉及到客户端的时候,性能信息是有限的。这在一定程度上是由于有限的性能指标和浏览器提供的 API 。讽刺的是,一些非标准的性能跟踪技术本身会对性能产生负面影响。由于新的面向性能的 API 出现,目前这种情况正在发生转变:

两个重要时刻:首次渲染(First Paint )和首次内容渲染(First Contentful Paint)。

对于用户界面,绘制指标回答了两个有用的问题:

  • 发生了什么?(首次渲染)
  • 这个有用么?(首次内容渲染)

测量性能非常重要,但是更重要的是测量用户最终感知性能,这通常受到这两个指标的影响。

首次渲染

这是屏幕的首次渲染,这个指标不包括默认的背景绘制,但它包括了任何用户自定义的背景绘制,它是首先将像素绘制到屏幕的点。

首次内容渲染

这就是浏览器将第一个 DOM 渲染到屏幕的时间。该指标报告了浏览器首次呈现任何文本、图像、画布或者 SVG 的时间。

它代表用户开始使用内容的第一个点。例如,Twitter 和 Nest 主页可能如下所示:

使用 Paint Timing API 提高性能

了解代码的区别

为了巩固你对首次渲染和首次内容渲染的理解,请思考以下示例代码,该代码也在 Github 上。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Paint delay example</title>
    <script>
        const observer = new window.PerformanceObserver(list => {
            list.getEntries().forEach(({name, startTime}) => {
                console.log({name, startTime});
            });
        });
 
        observer.observe({
            entryTypes: ['paint']
        });
 
        function sleep(ms = 1000) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }
 
        // This triggers first-paint
        sleep().then(() => document.body.style.backgroundColor = 'lightgrey');
 
        // This triggers first-contentful-paint
        sleep(2000).then(() => document.body.innerHTML += '<p>Hi there!</p>');
    </script>
</head>
<body>
 
</body>
</html>

注意:上述代码不会以任何方式强调最佳实践!例如,应该避免这种方式设置内联样式。它只作为演示。

在浏览页面之前,请注意 `PerformanceObserver()` API 的使用情况。此 API 允许你观察应用程序源代码中的各种性能指标,然后对其执行操作,例如通过将指标发送到服务器进一步处理。

下面是访问页面时控制台的返回结果

使用 Paint Timing API 提高性能

注意以下指标:

  • 首次渲染发生在一秒钟左右
  • 首次内容渲染发生在两秒左右

这些指标可以直接链接到触发这些指标发生的代码。这个代码特别是触发首次渲染:

sleep().then( () => document.body.style.backgroundColor = 'lightgrey'

从用户对性能的感知上来说,首次渲染并不总是提供很好的价值,但是它被正确地标识为像素绘制到屏幕的第一个点。

下面的 code 将会触发首次内容渲染。

sleep(2000).then(() => document.body.innerHTML += '<p>Hi there!</p>')

在这种情况下,真实的内容在两秒钟之后被渲染到页面上。

虽然这是一个简单的例子,它应该演示了首次渲染和首次内容渲染的各种触发。

1. 从 JavaScript 评估绘制指标

方法1:查询绘制指标

评估绘制指标有两种方法。对于第一种方法,你现在可以打开 Chrome DevTools,并在控制台面板中尝试如下代码:

performance.getEntriesByType('paint')

使用 Paint Timing API 提高性能

你可以使用 Performance API,特别是 `Performance.getEntriesByType()` 来检索可用的性能指标。对于首次渲染指标,单个绩效条目如下:

{
  "name": "first-paint",
  "entryType": "paint",
  "startTime": 1494.9050000000002,
  "duration": 0
}

作为调用 `Performance.getEntriesByType()` 方法返回的 JSON 对象的一部分,有四个属性:

  • Name: 单个指标名称
  • Entry Type: 所属类别类型(注意:这是用于过滤属于特定类别的度量的关键:`Performance.getEntriesByType(‘paint’)`)
  • Start Time: 度量发生时间的高分辨率时间戳
  • Duration: 对于绘制指标,这将始终为零,因为首次绘制和首次内容绘制指标不代表持续时间,而是具体时间点

方法2:监听绘制指标

获取绘制度量事件的第一种技术是在 JavaScript 中调用目标方法来返回所有可以的绘制指标。第二种方法涉及通过注册观察者监听变化。实际上,这意味着创建一个性能观察器实例:

const observer = new PerformanceObserver(list => {
    // `list` provides access to performance metrics
});
 
observer.observe({entryTypes: ['paint']});

性能观察器界面允许你观察特定类型的性能指标。在上面的代码中,我们监听绘制指标。这种观察者模式遵循与 JavaScript 中可观察的建议类似的特征,这是一个允许你随着时间的推移收集数据的接口。

2. 报告绘制渲染时间给服务器

要从绘制指标中获取价值,你可以自动从客户端获取指标,并将其报告给你的服务器进行分支和处理。我们将介绍两种方法,第一种涉及使用 Google Analytics,第二种方法更普通一点,使用 Node.js 来发送。

方法1:Google Analytics

使用 Google Analytics,你可以将绘制指标发送到分析仪表盘:

ga('send', 'event', {
    eventCategory: 'Paint Metrics',
    eventAction: 'first-paint',
    eventValue: 100,
    nonInteraction: true,
});

更具体的文档在 Leveraging the Performance Metrics that Most Affect User Experience 。Google Analytics 还提供用于报告时间信息的专用用户计时文档。

方法2:向 Node.js 服务器报告

这种方法涉及在客户端 JavaScript 代码中收集绘制时间指标,然后使用适当的 API 将指标发送到 Web 服务器。完整的代码在 Github 上。

下面是客户端页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Reporting to Node.js</title>
    <script>
        const observer = new window.PerformanceObserver(list => {
            list.getEntries().forEach(({name, startTime}) => {
                console.log({name, startTime});
 
                // Need to report to a server here
                const data = {
                    name,
                    startTime
                };
 
                navigator.sendBeacon('http://127.0.0.1:3000', JSON.stringify(data));
            });
        });
 
        observer.observe({
            entryTypes: ['paint']
        });
    </script>
</head>
<body>
 
    <p>Hi there</p>
 
</body>
</html>

`forEach()` 回调最终使我们可以访问绘制时间指标。在这一点上,使用 Fetch API 执行 `fetch()` 请求并将绘制时间指标作为查询字符串参数或 POST 有效内容提交是相当微不足道的。几乎所有现代浏览器 Beacons API 中都支持这种用例的另一种 API,它为服务器的指标提供了极好的选择。

  • Beacons 即使页面关闭了也可以发送
  • Beacons 是异步发送,这意味着它在调用 API 时不会阻塞主线程
  • Beacons 请求由浏览器计划,不与高优先级的网络请求竞争
  • Beacons 请求可以由浏览器合并,以便在低功率设备上更加有效的发送
  • Beacons 请求不阻塞用户交互

使用来自客户端 JavaScript 的 Beacons API 与性能观察器相对来说比较简单:

list.getEntries().forEach(({name, startTime}) => {
    const data = {
        name,
        startTime
    };
 
    navigator.sendBeacon('http://127.0.0.1:3000', JSON.stringify(data));
});

服务器组件(Node.js)可以使用 Micro 组件接收数据:

const {json} = require('micro');
 
module.exports = async req => {
    console.log(await json(req));
    return 200;
};

注意到这个简单的示例工作所需的源代码非常少!

使用 Paint Timing API 提高性能

上图看到的最终结果:在后端检索结构化性能数据。你可以将这些技术合到生产中,并使用它来提供团队中绘制性能的意识。例如,从Node.js 可以:

  • 将绘制指标发送到可视化平台,如 Graphite
  • 加入到警报或监控平台中,如 ZMON
  • 在自动化测试中包含 first-contentful-paint ,以便于当页面超过可接受的首次内容渲染时间时,页面测试失败。你可以使用像 Intern 工具来做到这一点。

3. 从 Chrome DevTools 查看

Chrome DevTools 可以让你查看覆盖在性能面板录制中的绘制时间指标。

使用 Paint Timing API 提高性能

上图中,请注意垂直线下拉的方向。这些垂直线表示页面加载中的重要里程碑。可以包括:

  • First paint
  • First meaningful paint / First contentful paint
  • Page load

你可以将鼠标悬停在虚线垂直线的最上部分,以确定该虚线属于哪个度量。

使用 Paint Timing API 提高性能

下图中,虚线垂直线表示第一个有意义的画面。你可以在此时间点查看相关的截图,以了解页面上的哪些可视化组件。在此实例中,绘制了标题和页标题。

使用 Paint Timing API 提高性能

如你你想自己尝试,请确保在 Chrome DevTools 中启用了 “Timeline: paint timing markers” 实验。该功能在 Chrome 63 中验证。

你还应该在性能面板中启用 Screenshots ,以便你可以将页面的视觉完整性与绘制时间标记相关联。

4. 浏览器实施

有绘制时间的网页平台测试。在针对浏览器供应商的同时,他们可以为你提供一个 Web 开发人员,了解绘制如何运作。例如:

扩展阅读

结尾

我们涵盖了与绘制时间相关的广泛主题。我们深入了解了首次渲染和首次内容渲染的指标,以及与页面的视觉完整性的关系。我们看到了如何在 JavaScript 中检索这些指标,并将其发送到具有 Beacons API 的远程Web 服务器上。

最后,我们看到了一个实验性的 Chrome DevTools 功能,可以将绘制时间指标覆盖到性能面板中,从而更轻松地绘制事件与页面活动对齐。

Paint Timing API 允许网站创建者跟踪和监视感知效果的重要指标。如果加载源需要超过3秒的时间,那么 53% 的用户将放弃网站。能够将绘制时间保持在低水平可能会使你的用户感到高兴,并提高你网站的访问率。

查看原文: 使用 Paint Timing API 提高性能

  • ticklishpeacock
  • beautifulmouse
  • orangefish
需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。