リソースヒントを使用してブラウザをサポートする

リソースの読み込みの最適化に関する最後のモジュールでは、CSS や JavaScript などのさまざまなページ リソースがページの読み込み速度にどのように影響するか、また、それらのリソースとその配信を最適化してページのレンダリングを高速化する方法について学びました。リソース ヒントを使用してブラウザがリソースをより高速に読み込めるようにする、リソース読み込みのより高度な側面について学ぶには、今が絶好のタイミングです。

リソースヒントを使用すると、ブラウザにリソースの読み込み方法と優先順位を伝えることで、デベロッパーはページ読み込み時間をさらに最適化できます。preconnectdns-prefetch などのリソース ヒントの初期セットが最初に導入されました。しかし、その後 preload と Fetch Priority API が追加され、機能が拡張されました。

リソースヒントは、読み込みパフォーマンスを改善する可能性のある特定のアクションを事前に実行するようブラウザに指示します。リソース ヒントを使用すると、早期の DNS ルックアップの実行、サーバーへの事前接続、ブラウザが通常検出する前にリソースを取得するなどのアクションを実行できます。

リソース ヒントは、HTML(多くの場合、<head> 要素の冒頭)で指定するか、HTTP ヘッダーとして設定できます。このモジュールの範囲では、preconnectdns-prefetchpreload と、prefetch が提供する投機的フェッチの動作について説明します。

preconnect

preconnect ヒントは、重要なリソースを取得する別のオリジンへの接続を確立するために使用されます。たとえば、画像やアセットを CDN や他のクロスオリジンでホストしている場合などです。

<link rel="preconnect" href="https://example.com">

preconnect を使用すると、ブラウザが ごく近い将来に特定のクロスオリジン サーバーに接続する予定であることを予測し、ブラウザがその接続をできるだけ早く開くべきであることを示します。理想的には、HTML パーサーまたはプリロード スキャナが接続を開くのを待つ前に開くべきです。

ページに大量のクロスオリジン リソースがある場合は、現在のページにとって最も重要なリソースに preconnect を使用します。

Chrome DevTools のネットワーク パネルにあるリソースの接続タイミングのスクリーンショット。接続設定には、ストール時間、プロキシ ネゴシエーション、DNS ルックアップ、接続設定、TLS ネゴシエーションが含まれます。
Chrome DevTools のネットワーク パネルに表示される接続タイミングの可視化。赤い枠内のタイミングは、クロスオリジン サーバーとの接続設定に関わるものです。preconnect は、クロスオリジン リソースの検出時ではなく、より早いタイミングで接続を確立することで、このタイミングを短縮できます。

preconnect の一般的なユースケースは Google Fonts です。Google Fonts では、@font-face 宣言を提供する https://fonts.googleapis.com ドメインと、フォント ファイルを提供する https://fonts.gstatic.com ドメインに preconnect することをおすすめします。

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

crossorigin 属性は、クロスオリジン リソース シェアリング(CORS)を使用してリソースを取得する必要があるかどうかを示すために使用されます。preconnect ヒントを使用する場合、オリジンからダウンロードされるリソース(フォントファイルなど)が CORS を使用している場合は、preconnect ヒントに crossorigin 属性を追加する必要があります。

dns-prefetch

クロスオリジン サーバーへの接続を早期に開くことで、ページの初回読み込み時間を大幅に短縮できますが、多くのクロスオリジン サーバーへの接続を一度に確立することは合理的でも可能でもない場合があります。preconnect の過剰使用が懸念される場合は、dns-prefetch ヒントを使用すると、リソースのコストを大幅に削減できます。

名前のとおり、dns-prefetch はクロスオリジン サーバーへの接続を確立するのではなく、そのサーバーの DNS ルックアップを事前に実行するだけです。DNS ルックアップは、ドメイン名が基盤となる IP アドレスに解決されるときに発生します。デバイスとネットワーク レベルの DNS キャッシュのレイヤにより、一般的にこのプロセスは高速化されますが、それでもある程度の時間がかかります。

<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://fonts.gstatic.com">

DNS ルックアップは比較的安価であり、コストが比較的小さいため、場合によっては preconnect よりも適切なツールとなることがあります。特に、ユーザーがクリックする可能性が高いと思われる他のウェブサイトへのリンクがある場合に、使用すると望ましいリソースヒントです。dnstradamus は、JavaScript を使用してこれを自動的に行うツールの 1 つです。また、Intersection Observer API を使用して、他のウェブサイトへのリンクがユーザーのビューポートにスクロールされたときに、現在のページの HTML に dns-prefetch ヒントを挿入します。

preload

preload ディレクティブは、ページのレンダリングに必要なリソースの早期リクエストを開始するために使用されます。

<link rel="preload" href="/lcp-image.jpg" as="image" fetchpriority="high">

preload ディレクティブは、後から検出された重要なリソースに限定する必要があります。最も一般的なユースケースは、フォントファイル、@import 宣言で取得される CSS ファイル、Largest Contentful Paint(LCP)候補になる可能性が高い CSS background-image リソース、または初期 HTML で検出できないその他の LCP リソース(JavaScript で読み込まれる場合など)です。このような場合、リソースが外部リソースで参照されているため、プリロード スキャナでこれらのファイルが検出されることはありません。

preconnect と同様に、preload ディレクティブでは、フォントなどの CORS リソースをプリロードする場合は crossorigin 属性が必要です。crossorigin 属性を追加しない場合、または CORS 以外のリクエストに追加した場合、リソースはブラウザによって 2 回ダウンロードされ、他のリソースに有効活用できたはずの帯域幅が無駄になります。

<link rel="preload" href="/font.woff2" as="font" crossorigin>

上記の HTML スニペットでは、/font.woff2 が同じドメインにある場合でも、CORS リクエストを使用して /font.woff2 をプリロードするようにブラウザに指示しています。

prefetch

prefetch ディレクティブは、今後のナビゲーションで使用される可能性のあるリソースに対する低優先度リクエストを開始するために使用されます。

<link rel="prefetch" href="/next-page.css" as="style">

このディレクティブは、preload ディレクティブとほぼ同じ形式ですが、<link> 要素の rel 属性は "prefetch" の値を使用します。ただし、preload ディレクティブとは異なり、prefetch は投機的です。つまり、将来のナビゲーション(発生する可能性もあれば、発生しない可能性もある)のリソースのフェッチを開始します。

prefetch が有効な場合もあります。たとえば、ウェブサイトでほとんどのユーザーが完了までたどるユーザーフローを特定した場合、それらの将来のページでレンダリングに不可欠なリソースの prefetch を使用すると、読み込み時間を短縮できます。

Fetch Priority API

Fetch Priority APIfetchpriority 属性を使用すると、リソースの優先度を上げることができます。この属性は、<link><img><script> の各要素で使用できます。

<div class="gallery">
  <div class="poster">
    <img src="img/poster-1.jpg" fetchpriority="high">
  </div>
  <div class="thumbnails">
    <img src="img/thumbnail-2.jpg" fetchpriority="low">
    <img src="img/thumbnail-3.jpg" fetchpriority="low">
    <img src="img/thumbnail-4.jpg" fetchpriority="low">
  </div>
</div>

デフォルトでは、画像は低い優先度で取得されます。レイアウト後、画像が初期ビューポート内にあることが判明した場合、優先度は High に引き上げられます。上記の HTML スニペットでは、fetchpriority によって、ブラウザは優先度「高」でより大きな LCP 画像をすぐにダウンロードするよう指示されます。一方、重要度の低いサムネイル画像は優先度が低い状態でダウンロードされます。

最新のブラウザは、リソースを 2 つのフェーズで読み込みます。最初のフェーズは重要なリソース用に予約されており、すべてのブロッキング スクリプトがダウンロードされて実行されると終了します。このフェーズでは、優先度の低いリソースのダウンロードが遅れることがあります。fetchpriority="high" を使用すると、リソースの優先度を上げて、ブラウザが最初のフェーズでリソースをダウンロードできるようにすることができます。

リソースヒントのデモ

理解度テスト

preconnect リソースヒントの機能

ブラウザが通常検出する前に、DNS ルックアップ、接続、TLS ネゴシエーションなど、クロスオリジン サーバーへの接続を開きます。
正解です。
クロスオリジン サーバーの DNS ルックアップのみを実行します。
もう一度お試しください。

Fetch Priority API で何ができるようになりますか?

現在のページの HTML がダウンロードされる優先度を指定します。
もう一度お試しください。
<link><img><script> 要素の相対優先度を指定します。
正解です。

prefetch ヒントはどのような場合に使用すべきですか?

ユーザーが必要とする可能性のあるすべてのリソースまたはページ(実際に必要になるかどうかは問わない)。
もう一度お試しください。
プリフェッチするリソースやページがユーザーに必要であると確信できる場合。
正解です。
ユーザーがデータ使用量の削減を明示的に希望していない場合。
正解です。

次のステップ: 画像のパフォーマンス

この時点で、ページの HTML、<head> 要素、リソースヒントに関する一般的なパフォーマンスの考慮事項について、かなり自信がついてきたのではないでしょうか。ただし、ページで一般的に読み込まれるさまざまなリソースタイプに固有の最適化が他にもあります。次のモジュールでは、画像のパフォーマンスについて説明します。このモジュールでは、ユーザーのデバイスに関係なく、ウェブサイトの画像を可能な限り高速に読み込む方法を学びます。