衡量关键渲染路径

Ilya Grigorik
Ilya Grigorik

作为每个可靠性能策略的基础,准确的评估和插桩是所有测试的基础。无法衡量的对象也就无法优化。本文档介绍了衡量 CRP 性能的不同方法。

  • Lighthouse 方法会对网页运行一系列自动化测试,然后生成有关该网页的 CRP 性能的报告。此方法可让您快速轻松地大致了解浏览器中加载的特定网页的 CRP 性能,从而快速测试、迭代和提高其性能。
  • Navigation Timing API 方法会捕获真实用户监控 (RUM) 指标。顾名思义,这些指标是从用户与您网站的真实互动中捕获的,可让您准确了解用户在各种设备和网络状况下的真实 CRP 性能。

一般而言,一种不错的方法是使用 Lighthouse 发现明显的 CRP 优化机会,然后使用 Navigation Timing API 对代码进行插桩 (instrument) 处理,以监控应用在实际运行中的表现。

使用 Lighthouse 审核页面

Lighthouse 是一个 Web 应用审核工具,可以对给定页面运行一系列测试,然后在汇总报告中显示页面的结果。您可以将 Lighthouse 作为 Chrome 扩展程序或 NPM 模块运行,这对于将 Lighthouse 与持续集成系统集成非常有用。

要开始使用,请参阅使用 Lighthouse 审核 Web 应用

当您将 Lighthouse 作为 Chrome 扩展程序运行时,您网页的 CRP 结果将如以下屏幕截图所示。

Lighthouse 的 CRP 审核

如需详细了解此审核的结果,请参阅关键请求链

结合使用 Navigation Timing API 和网页加载时发出的其他浏览器事件,您可以捕获并记录任何网页的实际 CRP 性能。

Navigation Timing

上图中的每个标签都对应着浏览器为加载的每个页面所跟踪的高分辨率时间戳。事实上,在这个具体示例中,我们只显示了所有不同时间戳的一部分。目前,我们将跳过所有与网络相关的时间戳,但我们会在以后的课程中再介绍这些内容。

那么,这些时间戳是什么意思呢?

  • domLoading:这是整个过程的起始时间戳,浏览器将开始解析第一个收到的 HTML 文档字节。
  • domInteractive:表示浏览器已完成所有 HTML 解析并且 DOM 构建完成的时间点。
  • domContentLoaded:表示 DOM 准备就绪且没有样式表阻止 JavaScript 执行的时间点。这意味着我们现在(有可能)可以构建渲染树了。
    • 许多 JavaScript 框架都会等待此事件,然后才会开始执行自己的逻辑。因此,浏览器会捕获 EventStartEventEnd 时间戳,以便我们跟踪此次执行所用的时间。
  • domComplete:顾名思义,所有处理均已完成,网页上的所有资源(图片等)均已完成下载 - 换言之,正在加载的旋转图标已停止旋转。
  • loadEvent:作为每个网页加载的最后一步,浏览器会触发 onload 事件,该事件可以触发其他应用逻辑。

HTML 规范规定了每个事件的具体条件:应在何时触发、应满足哪些条件等等。为此,我们将重点关注与关键渲染路径相关的几个关键里程碑:

  • domInteractive 标记 DOM 就绪的时间点。
  • domContentLoaded 通常表示 DOM 和 CSSOM 均准备就绪的时间点。
    • 如果没有阻止解析器的 JavaScript,DOMContentLoaded 将在 domInteractive 后立即触发。
  • domComplete 标记网页及其所有子资源何时准备就绪。
<!DOCTYPE html>
<html>
  <head>
    <title>Critical Path: Measure</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <script>
      function measureCRP() {
        var t = window.performance.timing,
          interactive = t.domInteractive - t.domLoading,
          dcl = t.domContentLoadedEventStart - t.domLoading,
          complete = t.domComplete - t.domLoading;
        var stats = document.createElement('p');
        stats.textContent =
          'interactive: ' +
          interactive +
          'ms, ' +
          'dcl: ' +
          dcl +
          'ms, complete: ' +
          complete +
          'ms';
        document.body.appendChild(stats);
      }
    </script>
  </head>
  <body onload="measureCRP()">
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
  </body>
</html>

试试看

上面的例子乍一看可能有点令人望而生畏,但实际上很简单。Navigation Timing API 会捕获所有相关时间戳,而我们的代码只是等待 onload 事件触发(回想一下 onload 事件在 domInteractivedomContentLoadeddomComplete 之后触发),然后计算各个时间戳之间的差异。

NavTiming 演示

大功告成,现在我们有了可跟踪的特定里程碑,以及用于输出这些衡量结果的简单函数。请注意,您还可以修改代码以将这些指标发送到分析服务器(Google Analytics(分析)会自动执行此操作),而不是在网页上输出这些指标,这是监控网页效果的好方法,也是确定可从某些优化工作中受益的候选网页。

开发者工具怎么样?

尽管本文档有时会使用 Chrome 开发者工具的“Network”面板来说明 CRP 概念,但开发者工具目前并不适合 CRP 衡量,因为它没有用于隔离关键资源的内置机制。您可以运行 Lighthouse 审核,以帮助识别此类资源。

反馈