ナビゲーション タイミングを用いてクリティカル レンダリング パスを測定する

最適化するには、測定できなければなりません。幸運なことに、Navigation Timing API によって、クリティカル レンダリング パスの各ステップを測定する上で必要なツールがすべて手に入ります。

TL;DR

  • ナビゲーション タイミングは、CRP 測定のための高分解能なタイムスタンプを提供します。
  • ブラウザによって発行された多数の消耗イベントが、CRP のさまざまなステージをキャプチャします。

確かなパフォーマンス戦略の基盤を形成するのは、正確な測定です。それこそ、まさに Navigation Timing API が実現するものです。

ナビゲーション タイミング

上記の図の各ラベルは、ブラウザが各ページを読み込んだときの高分解能タイムスタンプに対応します。ただし、ここでは、さまざまなタイムスタンプの一部しか表示しています。今はネットワーク関連タイムスタンプはすべて省略しており、後のトピックで扱います。

さて、各タイムスタンプは何を意味しているのでしょうか。

  • domLoading: これは、プロセス全体が開始するときのタイムスタンプで、間もなく、ブラウザが最初に受け取った HTML ドキュメントのバイトの解析を開始します。
  • domInteractive: ブラウザが HTML の解析をすべて完了して、DOM 構築が完了した時点を示します。
  • domContentLoaded: DOM の準備が整い、JavaScript の実行をブロックするスタイルシートが存在しない時点を示します。必要に応じて、レンダリング ツリーの構築が開始できる段階です。
  • 多くの JavaScript フレームワークは、このイベントを待ってから、自身のロジックの実行を開始します。このため、ブラウザは、EventStartEventEnd のタイムスタンプを取得することで、この実行にかかった時間をトラッキングできるようにしています。
  • domComplete: 名前が示すとおり、すべての処理が完了し、ページ上のすべてのリソース(画像など)がダウンロードを完了したことを示します。つまり、読み込み中のマークが回転を止めた状態です。
  • loadEvent: 各ページの読み込みの最終ステップとして、ブラウザが onload イベントを発行します。このイベントは、追加アプリケーション ロジックをトリガーできます。

HTML 仕様では、イベントを発行する際に満たすべき条件など、各イベントの具体的な条件が規定されています。ここでは、クリティカル レンダリング パスに関係する主な条件だけに焦点を当てます。

  • domInteractive: DOM の準備が整ったことを示します。
  • domContentLoaded: 通常、DOM と CSSOM が両方とも準備が整ったことを示します。
  • パーサー ブロック JavaScript が存在しない場合、DOMContentLoadeddomInteractive の直後に発行されます。
  • domComplete: ページとサブリソースがすべて準備が整った時点を示します。

^

<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 イベントは、domInteractive、domContentLoaded、domComplete の後に発行されます)。そして、さまざまなタイムスタンプの相違が計算されます。 NavTiming デモ

以上で、トラッキングする具体的な基点と、その測定値を出力するシンプルな関数が手に入りました。コードを修正すれば、このような指標をページに出力する代わりに、アナリティクス サーバーに送信することもできます(Google アナリティクスでは自動的にこの処理が行われます)。この方法は、ページのパフォーマンスを定期的に記録し、最適化でメリットが生じるページを特定する方法として優れています。