Early Hints とともにサーバーの思考時間を使用してページ読み込みを高速化

重要なサブリソースに関するヒントをサーバーからブラウザに送信する方法をご確認ください。

早期ヒントとは何ですか?

ウェブサイトは時間の経過とともに洗練されてきました。そのため、リクエストされたページの HTML を生成するためにサーバーが重要な作業(データベースへのアクセス、配信元サーバーにアクセスする CDN など)を実行する必要があることは珍しくありません。残念ながら、「サーバーの思考時間」により、ブラウザがページのレンダリングを開始できるようになるまでの待ち時間が長くなります。実際に、接続はサーバーがレスポンスを準備する間、事実上アイドル状態になります。

サーバーによるページ読み込みと他のリソースの読み込みとの間に 200 ミリ秒のタイムギャップがあることを示す画像。
早期ヒントを使用しない場合: メインリソースに対する応答方法の決定が、サーバーですべてブロックされます。

Early Hints は HTTP ステータス コード(103 Early Hints)で、最終的なレスポンスの前に仮の HTTP レスポンスを送信するために使用されます。これにより、サーバーがメインリソースの生成でビジー状態にあるときに、そのページで使用される可能性の高い重要なサブリソース(ページのスタイルシート、重要な JavaScript など)やオリジンに関するヒントをサーバーからブラウザに送信できます。ブラウザはこれらのヒントを使用して接続をウォームアップし、メインリソースを待つ間、サブリソースをリクエストできます。つまり、Early Hints は、事前になんらかの作業を行ってブラウザがこのような「サーバーの思考時間」を活用できるようにし、ページの読み込みを高速化します。

早期ヒントによってページが部分的なレスポンスを送信する仕組みを示す画像。
早期ヒントを使用する場合: サーバーは最終的なレスポンスを決定している間に、リソースヒントを使用した部分的なレスポンスを提供できます。

場合によっては、Largest Contentful Paint のパフォーマンスは、ShopifyCloudflare で測定された数百ミリ秒から最大 1 秒速く向上する場合があります。前後の比較をご覧ください。

2 つのサイトの比較。
WebPageTest で実施したテストウェブサイトの Early Hints 前後の比較(Moto G4 - DSL)

早期ヒントの使用方法

Early Hints を活用するための最初のステップは、上位のランディング ページ、つまりユーザーがウェブサイトにアクセスしたときに通常最初に表示されるページを特定することです。たとえば、ホームページや、他のウェブサイトから多くのユーザーがアクセスしている場合は人気の商品リスティング ページなどです。これらのエントリ ポイントが他のページよりも重要である理由は、ユーザーがウェブサイト内を移動すると早期ヒントの有用性が低下するためです(つまり、ブラウザは 2 回目または 3 回目のナビゲーションで必要なすべてのサブリソースを取得できる可能性が高くなります)。また、良い第一印象を与えるのも良いアイデアです。

ランディング ページの優先順位リストを取得したら、次のステップとして、preconnect または preload のヒントに適したオリジンまたはサブリソースを特定します。通常は、Largest Contentful PaintFirst Contentful Paint などの主要なユーザー指標に最も寄与するオリジンとサブリソースがこれに該当します。具体的には、同期 JavaScript、スタイルシート、ウェブフォントなど、レンダリングをブロックするサブリソースを探します。同様に、主要なユーザー指標に大きく寄与するサブリソースをホストするオリジンを探します。

また、メインのリソースがすでに preconnect または preload を使用している場合は、これらのオリジンやリソースを早期ヒントの候補として検討できます。詳しくは、LCP を最適化する方法をご覧ください。ただし、preconnect ディレクティブと preload ディレクティブを HTML から Early Hints にコピーすることは最適ではない場合があります

これらを HTML で使用する場合、プリロード スキャナでは HTML では検出されないリソース(フォントや背景画像など)を preconnectpreload で検出するのが一般的です。Early Hints では HTML がないため、代わりに HTML の早い段階で発見されるであろう重要なドメインや preload の重要なリソース(main.cssapp.js のプリロードなど)を代わりに preconnect できます。また、すべてのブラウザで Early Hints の preload がサポートされているわけではありません。ブラウザのサポートをご覧ください。

2 つ目のステップでは、古くなった、またはメインリソースで使用されなくなったリソースやオリジンに早期ヒントを使用するリスクを最小限に抑える必要があります。たとえば、頻繁に更新およびバージョニングされるリソース(example.com/css/main.fa231e9c.css など)は最適な選択とならないことがあります。なお、この懸念は早期ヒントに固有のものではなく、preload または preconnect が使用されているすべての場所に適用されます。これは、自動化やテンプレート化に最適である、この種の詳細です(たとえば、手動プロセスでは、preload と、リソースを使用する実際の HTML タグとの間でハッシュまたはバージョン URL の不一致が生じる可能性が高くなります)。

例として、次のフローについて考えてみましょう。

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]

サーバーは main.abcd100.css が必要になると予測し、Early Hints を使用してプリロードするよう提案します。

103 Early Hints
Link: </main.abcd100.css>; rel=preload; as=style
[...]

しばらくすると、リンクされている CSS を含むウェブページが表示されます。残念ながら、この CSS リソースは頻繁に更新されています。メインリソースは、予測される CSS リソース(abcd100)よりもすでに 5 バージョン分前(abcd105)になっています。

200 OK
[...]
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.abcd105.css">

一般的に、かなり安定していて、メインリソースの結果とはほぼ無関係なリソースとオリジンをターゲットにします。必要に応じて、主要なリソースを 2 つに分割することを検討してください。1 つは初期ヒントで使用するように設計された安定した部分、もう 1 つはメインのリソースがブラウザによって返された後にフェッチされる動的な部分です。

<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">

最後に、サーバー側で、Early Hints をサポートしていることがわかっているブラウザから送信されたメインのリソース リクエストを探し、103 Early Hints ですぐに応答します。103 レスポンスには、関連する事前接続とプリロードのヒントを含めます。メインリソースの準備ができたら、通常のレスポンス(成功の場合は 200 OK など)でフォローアップします。下位互換性を確保するため、最終的なレスポンスに Link HTTP ヘッダーも含めることをおすすめします。これには、メインリソースの生成の一環として明らかになった重要なリソース(たとえば、「2 つに分割する」の推奨事項に従った場合のキーリソースの動的な部分)で強化することもできます。次のように表示されます。

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]
103 Early Hints
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script

しばらくすると、次のようになります。

200 OK
Content-Length: 7531
Content-Type: text/html; charset=UTF-8
Content-encoding: br
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script
Link: </experimental.3eab3290.css>; rel=preload; as=style
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">
   <script src="/common.js"></script>
   <link rel="preconnect" href="https://fonts.googleapis.com">

ブラウザ サポート

103 Early Hints はすべての主要なブラウザでサポートされていますが、Early Hints で送信できるディレクティブはブラウザによって異なります。

接続前のサポート:

対応ブラウザ

  • 103
  • 103
  • 120
  • 17

プリロードのサポート:

対応ブラウザ

  • 103
  • 103
  • 123
  • x

Chrome DevTools は 103 Early Hints をサポートしています。

サーバー サポート

一般的なオープンソース ソフトウェアの HTTP サーバー ソフトウェアにおける Early Hints のサポートレベルの概要は次のとおりです。

  • Apache: mod_http2 を使用してサポートされます。
  • H2O: 対応
  • NGINX: 試験運用版モジュール
  • Node: httphttp2 については 18.11.0 以降でサポートされています。

早期ヒントを有効にする簡単な方法

次のいずれかの CDN またはプラットフォームを使用している場合は、Early Hints を手動で実装する必要はありません。ソリューション プロバイダのオンライン ドキュメントを参照して、早期ヒントをサポートしているかどうかを確認してください。以下では、すべてのリストを網羅しているわけではありません。

早期ヒントをサポートしていないクライアントの問題を回避する方法

100 の範囲の情報 HTTP レスポンスは HTTP 標準の一部ですが、103 Early Hints がリリースされる前は、一般的なウェブ ブラウジングにはほとんど使用されなかったため、一部の古いクライアントや bot はこれに苦労する可能性があります。

sec-fetch-mode: navigate HTTP リクエスト ヘッダーを送信するクライアントに応答して 103 の Early Hints のみを出力することで、後続のレスポンスを待つことを理解している新しいクライアントにのみ、このようなヒントが送信されるようになります。また、Early Hints はナビゲーション リクエストでのみサポートされているため(現在の制限事項を参照)、他のリクエストで不必要にこれらのヒントを送信しないというメリットもあります。

また、早期ヒントは HTTP/2 接続または HTTP/3 接続経由でのみ送信することをおすすめします

高度なパターン

主要なランディング ページに早期ヒントを完全に適用済みで、さらなる機会をお探しの場合は、次の高度なパターンがご参考になります。

一般的なユーザー ジャーニーの一環として nth ページ目をリクエストしたユーザーについては、ページの下の方にあるコンテンツ、つまり、優先度の低いリソースで早期ヒントを使用するという方法に、早期ヒントのレスポンスを適用するとよいでしょう。優先度が高く、レンダリングをブロックするサブリソースやオリジンに重点を置くことをおすすめしていることを考えると、直感に反しているように思えるかもしれません。しかし、訪問者がしばらく操作を行っている頃には、そのブラウザに重要なリソースがすでにすべて揃っている可能性が高いと考えられます。ここからは、優先度の低いリソースに注意を向ける方が合理的です。たとえば、Early Hints を使用して商品画像を読み込む場合や、あまり一般的でないユーザー操作にのみ必要な JS/CSS を追加する場合などです。

現在の制限事項

Chrome に実装されている Early Hints の制限事項は次のとおりです。

  • ナビゲーション リクエスト(最上位のドキュメントのメインリソース)でのみ使用できます。
  • preconnectpreload のみをサポートしています(prefetch はサポートされていません)。
  • Early Hints が使用された後に、最終的なレスポンスでクロスオリジン リダイレクトが行われた場合、Chrome は Early Hints を使用して取得したリソースと接続を破棄します。

他のブラウザにも同様の制限があり、さらに 103 早期ヒントを preconnect のみに制限しているブラウザもあります。

次のステップ

コミュニティからの関心に応じて、次の機能によって早期ヒントの実装を補強する場合があります。

  • サブリソース リクエストで早期ヒントが送信されます。
  • iframe のメインリソース リクエストで早期のヒントが送信されました。
  • Early Hints のプリフェッチのサポート。

どの側面を優先するか、また、早期ヒントをさらに改善する方法について、皆様のご意見をお待ちしております。

下半期/push との関係

非推奨の HTTP2/push 機能を使い慣れている方は、Early Hints との違いに気付くかもしれません。Early Hints では、ブラウザが重要なサブリソースの取得を開始するために往復が必要ですが、HTTP2/push では、サーバーがレスポンスとともにサブリソースの push を開始する可能性があります。これは驚くべきことに聞こえますが、その結果、構造上の重要なデメリットがあります。HTTP2/Push では、ブラウザがすでに持っているサブリソースのプッシュを避けるのが極めて困難でした。この「押しすぎる」効果により、ネットワーク帯域幅の使用効率が低下し、パフォーマンス上のメリットが大幅に低下しました。全体として、Chrome のデータによると、HTTP2/Push はウェブ全体のパフォーマンスにおいて実質的にマイナスであることがわかりました。

一方、Early Hints は、予備レスポンスを送信する機能と、実際に必要なものの取得や接続をブラウザが担うヒントを組み合わせたものであるため、パフォーマンスが向上します。Early Hints は理論上は HTTP2/Push で対処できるすべてのユースケースを網羅しているわけではありませんが、Early Hints はナビゲーションを高速化するためのより実用的なソリューションであると考えています。

Pierre Bamin 氏によるサムネイル画像。