公開日: 2014 年 3 月 31 日
確固としたパフォーマンス戦略の基盤には、常に正確な計測があります。測定できないものは最適化できない。このガイドでは、CRP パフォーマンスを測定するさまざまな方法について説明します。
- Lighthouse のアプローチでは、自動化された一連のテストをページに対して実行し、ページの CRP パフォーマンスに関するレポートを生成します。この方法では、ブラウザに読み込まれた特定のページの CRP パフォーマンスの大まかな概要を簡潔に把握できるため、パフォーマンスを迅速にテスト、反復、改善できます。
- Navigation Timing API のアプローチでは、RUM(リアル ユーザー モニタリング)メトリクスを取得します。名前が示すように、これらの指標はサイトとの実際のユーザー インタラクションから取得され、さまざまなデバイスやネットワーク状態でユーザーが体験する実際の CRP パフォーマンスを正確に把握するのに役立ちます。
一般的には、Lighthouse を使用して明らかな CRP 最適化の機会を特定し、Navigation Timing API でコードをインストルメント化して、実際のアプリのパフォーマンスをモニタリングすることをおすすめします。
Lighthouse を使用したページの監査
Lighthouse は、指定したページに対して一連のテストを実行し、ページの結果をレポートにまとめて表示するウェブアプリの監査ツールです。Lighthouse は Chrome 拡張機能または NPM モジュールとして実行できるため、Lighthouse を継続的インテグレーション システムと統合する場合に便利です。
使用を開始するには、Lighthouse によるウェブアプリの監査をご覧ください。
Lighthouse を Chrome 拡張機能として実行すると、ページの CRP 結果は次のスクリーンショットのようになります。
この監査の結果の詳細については、クリティカル リクエスト チェーンをご覧ください。
Navigation Timing API でコードを計測する
Navigation Timing API と、ページの読み込み時に発生するその他のブラウザ イベントを組み合わせることで、任意のページの実際の CRP パフォーマンスをキャプチャして記録できます。
上の図の各ラベルは、ブラウザが読み込むすべてのページについてトラックする、詳細なタイムスタンプに相当します。実は、この具体例では、さまざまなタイムスタンプの一部だけを表示しています。ここではネットワーク関連タイムスタンプはすべて省略してあります。ただし、後の演習で扱う予定です。
では、これらのタイムスタンプは何を意味するのでしょうか。
domLoading
: これは、プロセス全体の始動タイムスタンプであり、ブラウザが最初に受け取った HTML ドキュメントのバイトの解析を開始する時点を示します。domInteractive
: ブラウザがすべての HTML の解析と DOM の構築が完了したポイントをマークします。domContentLoaded
: DOM の準備が整い、JavaScript の実行をブロックするスタイルシートが存在しなくなった時点を示します。つまり、これ以降、レンダリング ツリーの構築を開始できます。- 多くの JavaScript フレームワークでは、このイベントを待ったうえで、それ自体のロジックの実行を開始します。このため、ブラウザでは、
EventStart
とEventEnd
のタイムスタンプをキャプチャすることで、この処理の所要時間をトラッキングできるようにしています。
- 多くの JavaScript フレームワークでは、このイベントを待ったうえで、それ自体のロジックの実行を開始します。このため、ブラウザでは、
domComplete
: 名前が示すように、すべての処理が完了し、ページ上のすべてのリソース(画像など)のダウンロードが完了しました。つまり、読み込みスピナーの回転が停止しました。loadEvent
: ページごとの読み込みの最終ステップとして、ブラウザはonload
イベントを発行します。これにより、追加のアプリケーション ロジックがトリガーされることがあります。
HTML 仕様では、イベントを発行するタイミング、満たすべき条件など、すべてのイベントごとに具体的な条件が規定されています。ここでは、クリティカル レンダリング パスに関連するいくつかの重要なマイルストーンに焦点を当てます。
domInteractive
は DOM の準備ができた時点を示します。domContentLoaded
は通常、DOM と CSSOM の両方の準備が完了していることを示します。- パーサー ブロック JavaScript が存在しない場合、
DOMContentLoaded
はdomInteractive
の直後に発行されます。
- パーサー ブロック JavaScript が存在しない場合、
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
イベントは、domInteractive
、domContentLoaded
、domComplete
の後で発行)、さまざまなタイムスタンプ間の差を計算しています。
こうして、追跡すべき具体的なマイルストーンと、これらの測定値を出力するための基本関数が用意できました。なお、これらの指標をページに出力する代わりに、コードに変更を加えてアナリティクス サーバーに送ることもできます(これは Google アナリティクスで自動的に行われます)。これにより、ページのパフォーマンスを継続的に把握し、最適化の効果が見込まれるページを特定できます。
DevTools はどうですか?
このようなドキュメントでは、Chrome DevTools の [Network] パネルを使用して、CRP のコンセプトを説明している場合がありますが、DevTools は現在、CRP の測定に最適というわけではありません。クリティカルなリソースを特定する仕組みが組み込まれていないためです。このようなリソースを特定するには、Lighthouse 監査を実行します。