衡量关键渲染路径

Ilya Grigorik
Ilya Grigorik

发布时间:2014 年 3 月 31 日

所有出色的效果策略都离不开良好的效果衡量和插桩。如果无法衡量,自然也就无从优化。本指南介绍了用于衡量关键渲染路径 (CRP) 性能的不同方法。

  • Lighthouse 方法会对网页运行一系列自动化测试,然后生成有关网页 CRP 性能的报告。此方法可快速提供浏览器中加载的特定网页的 CRP 效果的基本高级概览,让您能够快速测试、迭代和提升网页效果。
  • Navigation Timing API 方法可捕获实时用户监控 (RUM) 指标。顾名思义,这些指标是从真实用户与您网站的互动中捕获的,可准确反映真实世界中的 CRP 性能,因为它们是用户在各种设备和网络条件下体验到的。

一般来说,一个好的方法是使用 Lighthouse 找出明显的 CRP 优化机会,然后使用 Navigation Timing API 检测代码,以监控应用在实际环境中的表现。

使用 Lighthouse 审核网页

Lighthouse 是一款网页审核工具,可针对指定网页运行一系列测试,然后以汇总报告的形式显示该网页的结果。您可以将 Lighthouse 作为 Chrome 扩展程序或 NPM 模块运行,这有助于将 Lighthouse 与持续集成系统集成。

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

当您以 Chrome 扩展程序的形式运行 Lighthouse 时,网页的 CRP 结果应类似,其中列出了浏览器加载的链时长和文件顺序。

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

图中的每个标签都对应于浏览器针对其加载的每个网页跟踪的高分辨率时间戳。此图省略了所有与网络相关的时间戳。

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

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

HTML 规范针对每个事件规定了具体条件:何时应触发事件、应满足哪些条件以及其他重要注意事项

就本文而言,我们将重点介绍 CRP 的几个关键里程碑:

  • 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 事件触发,该事件会在 domInteractivedomContentLoadeddomComplete 之后触发。然后,计算各个时间戳之间的差值。

现在,我们有了一些要跟踪的具体里程碑,以及一个用于输出这些测量的基本函数。您可以修改此代码,以将这些指标发送到分析服务器,而不是打印结果。然后,您可以跟踪网页效果,并确定哪些网页可以通过优化来提升效果。

开发者工具呢?

虽然这些文档有时会使用 Chrome 开发者工具的“网络”面板来演示 CRP 概念,但开发者工具并不适合用于 CRP 测量,因为它没有用于隔离关键资源的内置机制。运行 Lighthouse 审核有助于识别此类资源。