Preload、prefetch、preconnect:それぞれが本当に役立つ場面
Resource hints は、実際のブラウザーのボトルネックと一致しているときに有用です。むやみに使うと優先度のノイズが増え、ページが遅くなることさえあります。
目次
- Resource hints は魔法ではない
- ブラウザーがすでにうまくやっていること
- Preload:発見が遅すぎる現在ページのリソースに使う
- Preload と LCP 画像
- Prefetch:このページではなく、次のページのために使う
- Preconnect:重要な origin への高コストな接続に使う
- DNS-prefetch:より軽い親戚
- 判断方法:実践的なワークフロー
- 1. ボトルネックを特定する
- 2. ヒントは一度に 1 つだけ追加する
- 3. 優先度の副作用を確認する
- 4. ヘッダーとキャッシュを検証する
- よくある間違い
- Preload しすぎる
- 必須リソースに prefetch を使う
- すべてのサードパーティに preconnect する
- モバイル条件を忘れる
- シンプルな判断表
- 落ち着いたルール
Resource hints は魔法ではない
preload、prefetch、preconnect は、しばしばパフォーマンスのチェックリストのように扱われます。<head> にいくつかタグを追加し、Lighthouse を再実行し、少し安心する。しかし、これらはそのように機能するものではありません。
これらのヒントは、ブラウザーの読み込みパイプラインに対する指示です。ブラウザーが十分早く発見できないことをあなたが知っている場合には役立ちます。一方で、推測で使ったり、重要でない処理を過剰に優先したり、ユーザーが必要としない接続を事前に温めたりすると、悪影響を及ぼすことがあります。
要約すると次のとおりです。
preloadは、現在のページに必要だが発見が遅すぎるリソースに使う。prefetchは、現在ページに必須のものではなく、将来のナビゲーションで使われそうなリソースに使う。preconnectは、接続確立が実際の遅延になっている重要なサードパーティ origin に使う。
実践上の問いは「どのヒントが一番速いか?」ではありません。「ブラウザーは何を待っていて、このヒントはその待ち時間を取り除けるのか?」です。
ブラウザーがすでにうまくやっていること
現代のブラウザーは、受動的なファイルダウンローダーではありません。HTML を解析し、先読みスキャンでリソースを見つけ、優先度を割り当て、接続を再利用し、見えていない処理を遅らせ、ネットワーク状況に適応します。
つまり、Resource hints は選択的に使うべきです。スタイルシート、スクリプト、画像、フォントがすでに早い段階で発見され、適切な優先度を与えられているなら、ヒントを追加しても何も変わらないかもしれません。さらに悪い場合、より重要なリソースと競合します。
ヒントを追加する前に、DevTools の waterfall trace やラボレポートを確認してください。Lighthouse を使っているなら、スコアではなく diagnostics から見始めましょう。Lighthouse report を慌てずに読むための別ガイドもあります。ただし正しい URL は大文字小文字を区別するため、必要に応じてサイトナビゲーションからリンク先の記事を使ってください。
実際の証拠は、たいてい次の 3 か所に現れます。
- 重要なリソースの開始が遅い。ブラウザーがそれを発見するのが遅いためです。
- 重要な origin への接続が、最初のリクエスト前に目立つ時間を要している。
- 次ページのリソースが非常に予測しやすく、アイドル時間に安く取得できる。
どれにも当てはまらないなら、そのヒントはおそらく装飾です。
Preload:発見が遅すぎる現在ページのリソースに使う
preload はブラウザーにこう伝えます。「このリソースは現在のページで必要になるので、今すぐ取得してください」。
典型例は、CSS 内で参照される web font です。ブラウザーは HTML をダウンロードし、CSS を発見し、CSS をダウンロードし、それを解析し、フォントを発見してから、フォントをリクエストしなければなりません。そのフォントがファーストビューのテキストに重要であれば、発見が遅れて layout shifts やテキスト描画の遅延につながることがあります。
preload によって、そのリクエストを早められます。
<link rel='preload' href='/fonts/inter-var.woff2' as='font' type='font/woff2' crossorigin>
as 属性は重要です。これはそのリソースの種類をブラウザーに伝え、優先度、キャッシュ、content security policy、リクエストヘッダーに影響します。フォントは通常、同じサイトから配信される場合でも crossorigin が必要です。フォント取得は CORS mode を使うためです。
良い preload 候補には次のものがあります。
- 表示されるテキストに使われる主要な web font。
- Largest Contentful Paint 要素であり、早期に発見できない hero image。
- 間接的に読み込まれる critical CSS ファイル。
- 非常に早い段階で必要だが、別のスクリプトの背後に隠れている module や script。
悪い preload 候補には次のものがあります。
- デザインシステム内のすべての font weight。
- ファーストビューより下の画像。
- 初期描画に不要なスクリプト。
- ブラウザーが最初の HTML chunk ですでに発見しているリソース。
Preload は現在ページの優先度に影響するため強力です。だからこそ誤用もしやすいのです。大きな asset を 5 つ preload しているなら、もはやブラウザーを助けているのではありません。ブラウザーと競り合っているだけです。
フォントは典型的な例です。主要なフォントファイルを 1 つ preload することは役立つ場合があります。6 つの weight と italic を preload すると、たいてい悪化します。フォントがボトルネックなら、まずフォントセットを整理してください。web fonts are still the easiest performance win on most sites へのガイドでは、その整理についてさらに詳しく扱っています。
Preload と LCP 画像
LCP 画像の preload は、その画像が初期 HTML に見えていない場合に有用です。よくある原因は、CSS background images、client-rendered components、または遅れて現れる responsive image logic です。
ただし hero image がすでに HTML 内に <img> として存在し、妥当な srcset、sizes、dimensions があり、lazy loading されていないなら、ブラウザーはおそらくすぐに見つけられます。その場合は、ページによっては preload より fetchpriority='high' を追加する方が適切かもしれません。
良いテストはこうです。waterfall で画像リクエストの開始が遅く、その画像が LCP 要素になるなら、preload を検討します。開始は早いがダウンロードが遅いなら、問題はサイズ、フォーマット、CDN の挙動、またはサーバーレイテンシです。発見の問題ではありません。画像フォーマットの判断については、when AVIF beats WebP and when it does not を参照してください。
Prefetch:このページではなく、次のページのために使う
prefetch はブラウザーにこう伝えます。「このリソースは近いうちに必要になるかもしれないが、今すぐ必須ではありません」。
この区別は重要です。Prefetch は意図的に低優先度です。ブラウザーはアイドル時間に取得して、後で使うために保存することがあります。また、低速接続、データ節約モード、メモリ圧迫時にはスキップすることもあります。
ユーザーの意図が十分強く、次のリソースが必要になる可能性が高い場合に prefetch を使います。
良い prefetch 候補には次のものがあります。
- 複数ページにまたがる checkout の次のステップ。
- ユーザーがクエリを入力し始めた後の検索結果。ただし次の route が予測可能な場合。
- ユーザーが近くのコンテンツを積極的に読んでいるときの、目次からリンクされた documentation pages。
- single-page app で、ユーザーがナビゲーション項目を hover または focus した後の route chunks。
悪い prefetch 候補には次のものがあります。
- ナビゲーションツリー全体。
- 大きな動画や画像ギャラリー。
- 「念のため」のサードパーティスクリプト。
- ユーザーが次に訪れることがまれなページ。
Prefetch は、抑制が効くところです。取得されたのに使われないリソースは無料ではありません。帯域幅、サーバー容量、エネルギー、場合によってはユーザーデータを消費します。モバイルネットワークでは、投機的な取得は積極的に不親切になり得ます。
多くのサイトでは、最良の prefetch 戦略は意図ベースです。ホームページの読み込み直後に pricing page を prefetch しないでください。ユーザーが pricing menu を開いたとき、pricing link を hover したとき、またはナビゲーションを強く予測させる call-to-action の近くまでスクロールしたときに prefetch します。
また、ブラウザーの挙動はさまざまであることも覚えておいてください。prefetch に慎重なブラウザーもあります。一部のプライバシー設定は speculative loading を減らしたり無効にしたりします。prefetch は opportunistic な改善として扱い、正しさを保証する仕組みとして扱わないでください。
Preconnect:重要な origin への高コストな接続に使う
preconnect はブラウザーにこう伝えます。「この origin への接続確立を今から始めてください」。
これには DNS lookup、TCP connection、TLS negotiation が含まれる場合があります。サードパーティ origin では、このセットアップに数百ミリ秒かかることがあります。特に高レイテンシのネットワークでは顕著です。ページがまもなくその origin からの重要なリクエストを必要とするなら、preconnect は後続リクエストを速くできます。
例:
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
良い preconnect 候補には次のものがあります。
- render-blocking text に使われる font origin。
- 初期インタラクション中に必要な critical API origin。
- ファーストビューの asset を配信する CDN origin。
- ユーザー操作直後に必要な payments または identity provider。
悪い preconnect 候補には次のものがあります。
- ユーザーにとって重要ではない analytics や advertising endpoints。
- 一部のセッションでしか使われない origin。
- サードパーティの長いリスト。
- same-origin resources。ブラウザーはすでに接続を持っているか、すぐに開くためです。
Preconnect には保持コストがあります。開いた socket はメモリとネットワークリソースを消費します。ブラウザーは未使用の接続を閉じますが、それによって不要な preconnect が無害になるわけではありません。
有用なルールは、1 ページで確信度の高いサードパーティ origin を最大 1 つか 2 つまで preconnect することです。それ以上追加したくなるなら、必要なのはヒントの拡張よりも、サードパーティ構成の見直しである可能性が高いでしょう。
DNS-prefetch:より軽い親戚
dns-prefetch も見かけることがあります。
<link rel='dns-prefetch' href='https://example-cdn.com'>
これはドメイン名を解決するだけです。TCP や TLS 接続は開きません。preconnect より安価ですが、その分効果も小さくなります。
DNS-prefetch は、full preconnect では積極的すぎると感じる、確信度の低いサードパーティ origin に対して妥当な場合があります。実務では、origin が重要で、すぐに確実に使われるなら preconnect を選びます。単に可能性があるだけなら、DNS-prefetch を使うか、何もしないかのどちらかです。
判断方法:実践的なワークフロー
タグではなく、計測から始めます。
1. ボトルネックを特定する
performance trace を開き、発見の遅れを探します。フォント、hero image、または script request が、別のファイルのダウンロードと解析後にようやく開始されていませんか?それは preload 候補です。
サードパーティ origin への長い DNS/TCP/TLS セットアップ後にリクエストがようやく開始されるなら、それは preconnect 候補です。
現在のページは問題ないものの、次のナビゲーションが予測可能に遅いなら、prefetch が役立つ可能性があります。
2. ヒントは一度に 1 つだけ追加する
Resource hints は相互作用します。1 つ追加し、テストし、waterfall が改善し、ユーザー向け指標が悪化しない場合にだけ残します。
preload では、ヒントを出したリソースが実際にすぐ使われるかを確認します。Chrome は、preload されたリソースが load 後まもなく使われない場合に警告することがあります。その警告は真剣に受け止めてください。
3. 優先度の副作用を確認する
preload は、より重要な CSS、JavaScript、画像から帯域を奪うことがあります。preconnect は接続スロットを占有することがあります。prefetch はバックグラウンドトラフィックを増やすことがあります。
正しい結果は「ヒントを出したファイルが早く開始される」ことではありません。正しい結果は「ページがユーザーにとって意味のある形で良くなる」ことです。可能なところでは LCP、INP、CLS、real-user monitoring を見てください。
4. ヘッダーとキャッシュを検証する
ヒントは HTML または HTTP Link headers で送信できます。headers は、ページが必要とするものをサーバーが早い段階で知っている場合に有用ですが、気軽に確認しづらい面があります。本番環境でヒントが実際に存在するかをデバッグしているなら、生の headers が重要です。これはまさに our guide to debugging redirects and HTTP headers で扱っている種類の状況です。
キャッシュも重要です。credentials の不一致、誤った as、または異なる URL parameters を使ってリソースを preload すると、重複ダウンロードが発生することがあります。これは、善意の preload がパフォーマンスバグになる最も一般的な方法の 1 つです。
よくある間違い
Preload しすぎる
すべてが重要なら、何も重要ではありません。preload は初期描画または即時のインタラクティビティに必要なリソースに限定してください。一般的なページの preload は 0〜3 個であるべきで、20 個ではありません。
必須リソースに prefetch を使う
Prefetch は低優先度で任意です。現在ページに必要な asset には使わないでください。ページが今それを必要としているなら、preload または通常の HTML discovery を検討します。
すべてのサードパーティに preconnect する
サードパーティが多いページには、外部 origin が 10 個以上あることもよくあります。それらすべてに preconnect するとノイズが生まれます。重要で、かつ予測可能に使われる 1 つか 2 つを選んでください。
モバイル条件を忘れる
Resource hints は低速接続で最も価値がありますが、同時にそこで最も危険でもあります。高速なデスクトップ接続で無駄な prefetch があっても誤差かもしれません。制約のあるモバイルプランでは、悪いトレードオフです。
シンプルな判断表
| 状況 | 最適なヒント | 理由 | |---|---:|---| | CSS 経由で発見される critical font | preload | 現在ページが必要としており、発見が遅い | | CSS または client rendering の背後に隠れた hero image | preload | 画像開始が遅い場合に LCP を改善できる | | ユーザー意図の後にあり得る次の route | prefetch | 現在ページをブロックせず将来のナビゲーションを助ける | | Critical なサードパーティ font/API origin | preconnect | 接続セットアップを critical path から取り除く | | 可能性はあるが不確実なサードパーティ origin | dns-prefetch またはなし | 低コスト、低確信度 | | ファーストビューより下の画像 | なし | lazy loading とブラウザーの優先度に任せる |
落ち着いたルール
Resource hints は、退屈で具体的なときに最もよく機能します。フォント 1 つ。LCP 画像 1 つ。重要なサードパーティ origin 1 つ。意図が見えた後の、あり得る次の route 1 つ。
楽観として使うとうまく機能しません。ユーザーがこれを必要とするかもしれない。ブラウザーはあれを取得すべきかもしれない。ヒントが多いほど速くなるかもしれない。
ブラウザーはすでに積極的に最適化しています。あなたの仕事はすべてのリクエストを細かく管理することではありません。あなたの仕事は、ブラウザーが適切な瞬間に情報を欠いている、数少ないケースを補正することです。