サーバーの思考を先に読め!103 Early HintsとfetchpriorityでLCPを爆速化する

ウェブサイトの表示速度は、ユーザー体験とSEOの双方に大きな影響を与えます。特にLCP(Largest Contentful Paint)、つまりページのメインコンテンツが描画されるまでの時間は、サイトの第一印象を決めると言っても過言ではありません。
LCPを改善する上で最大の課題の一つが、「サーバー側の思考時間」です。サーバーがコンテンツを生成するまでの間、ブラウザは何もできず待機するしかありませんでした。しかし、この無駄な時間を有効活用する仕組みが103 Early Hintsです。
本記事では、この103 Early Hintsと、リソースの取得優先度をコントロールするfetchpriority
を組み合わせ、LCPを劇的に改善するための実践的な方法を解説します。
この記事でわかること
103 Early Hints
がウェブページの表示速度を改善する仕組み- CDNや最新のサーバー(Node.js, Nginx)での具体的な有効化方法
fetchpriority
を使ってLCP画像の読み込みを最優先にする方法- 実装時の注意点、ブラウザ対応状況、そしてデバッグ方法
1. サーバーの「思考時間」を有効活用する103 Early Hints
ウェブページをリクエストすると、サーバーはHTMLを生成し、200 OK
というステータスコードと共にレスポンスを返します。しかし、複雑な処理が必要なページでは、このHTML生成に数秒かかることがあります。
103 Early Hints
は、サーバーが200 OK
を返す前に、103 Early Hints
というステータスコードと共にLink
ヘッダーだけを先行して送信する仕組みです。
これにより、ブラウザは最終的なレスポンスを待つことなく、Link
ヘッダーで指定されたCSS、JavaScript、画像、フォントなどの重要リソースの読み込みをすぐに開始できます。サーバーの「思考時間」が長ければ長いほど、この効果は大きくなります。
Early Hintsの対象と制限
103 Early Hints
は、以下の点に注意して利用しましょう。
- 対象: トップレベルのナビゲーション(ブラウザのアドレスバーにURLを入力したり、リンクをクリックしたりする操作)への応答のみで有効です。
- 利用可能なヘッダー:
103 Early Hints
で指定できるのは、主にrel=preload
とrel=preconnect
です。prefetch
などはサポートされていません。 - リダイレクト: クロスオリジンへのリダイレクトが最終応答で発生した場合、ブラウザはEarly Hintsで取得したリソースを破棄します。
CDNでの有効化が最も手軽
多くの主要CDN(Cloudflare, Fastly, Akamaiなど)がEarly Hintsをサポートしています。最も手軽なのは、これらのCDNの設定画面からEarly Hintsを有効化することです。
例えばCloudflareでは、公式ドキュメントに従って設定するだけで有効化できます。
2. 実装パターン:最新のサーバー環境で103
を送る
Node.js(Express.js)の場合
Node.js v18.11以降では、response.writeEarlyHints()
という専用APIが用意されています。複数のLink
ヘッダーは配列で渡すのが推奨される方法です。
// Node.js (v18.11+) Express.jsのミドルウェア
app.use((req, res, next) => {
const links = [
'</styles.css>; rel=preload; as=style',
'</images/lcp-hero.jpg>; rel=preload; as=image'
];
// 103 Early Hints を送信
res.writeEarlyHints({ link: links });
next();
});
注意:
link
キーは小文字で記述し、値は文字列または配列で渡します。
Nginxの場合
Nginx 1.29.0以降では、early_hints
という専用ディレクティブが追加され、バックエンドからのEarly Hintsをプロキシできるようになりました。
HTTP/1.1クライアントではプロトコルエラーが発生する可能性があるため、HTTP/2 / HTTP/3クライアントにのみ送信するのがベストプラクティスです。
# nginx.conf の http, server, locationブロック内で設定
# HTTP/2/3クライアントにのみEarly Hintsを許可
map $http_sec_fetch_mode $send_early_hints {
default 0;
navigate 1; # トップレベルナビゲーションのみを対象
}
server {
listen 443 ssl http2;
# http3 も有効にする場合はlisten 443 quic; 等を追加
location / {
early_hints $send_early_hints;
proxy_pass http://backend;
}
}
キャッシュ前提の注意
Early Hintsで指定するリソースは、ブラウザのHTTPキャッシュに保存されます。このキャッシュが最終レスポンスで再利用されるため、Cache-Control
ヘッダーを適切に設定し、二重取得を避けるようにしましょう。
3. リソースの優先度を制御するfetchpriority
103 Early Hints
でリソースの読み込みを早く開始しても、ブラウザはリソースの「取り合い」をします。CSSやJavaScript、画像が同時に読み込まれる際、LCP画像などの本当に重要なリソースに優先度を与えるのがfetchpriority
です。
fetchpriority
は、<img>
, <link>
, <script>
タグに設定できる属性で、high
, low
, auto
の3つの値を持ちます。
値 | 説明 |
---|---|
high |
LCP画像など、重要なリソースに設定。ブラウザのデフォルト優先度よりも高くして、いち早く読み込ませます。 |
low |
ページの表示に必須ではないリソース(非同期のスクリプトなど)に設定。 |
auto |
デフォルト値。ブラウザの判断に任せます。 |
fetchpriority
の実装例
<img src="/images/hero.jpg" width="1200" height="800" fetchpriority="high" alt="ヒーロー画像">
<img src="/images/gallery-item.jpg" width="600" height="400" loading="lazy" fetchpriority="low" alt="ギャラリー画像">
<link rel="preload" as="image" href="/images/background.jpg" fetchpriority="high">
<script src="/js/analytics.js" async fetchpriority="low"></script>
Next.jsでの注意点 Next.jsの
<Image>
コンポーネントのpriority
プロパティは、プリロードを指示するもので、fetchpriority="high"
を付与するかはバージョンに依存します。確実に制御したい英雄画像は、<img fetchpriority="high">
と<link rel="preload">
を明示的に記述するのが最も確実です。React/Nextでは属性名を小文字のfetchpriority
にしましょう。
fetchpriority
の落とし穴
- ヒントであって規則ではない:
fetchpriority
はあくまでブラウザへのヒントです。最終的な優先度はブラウザのヒューリスティクスで決定されます。 - やりすぎ注意:
fetchpriority="high"
を多用すると、ブラウザのリソース競合が悪化し、かえってLCPが悪化する可能性があります。本当に必要な1~2点に絞りましょう。 - ブラウザ対応: 主要ブラウザは
fetchpriority
をサポートしていますが、Safariは現状rel=preconnect
のみの対応です。
4. 計測とデバッグ:効果を可視化する
設定が正しく機能しているかを確認するには、ブラウザのDevToolsが不可欠です。
-
Chrome DevTools -> Networkタブ:
103 Early Hints
で読み込まれたリソースには、Initiator
列にearly-hints
と表示されます。また、リクエストの詳細でEarly Hints Headers
を確認できます。fetchpriority
で変更された優先度は、Priority
列で確認できます。
-
cURLでの確認:
103
レスポンスが正しく送信されているかは、cURL
コマンドで簡単に確認できます。curl -L -s -o /dev/null -D - https://example.com
実行結果の先頭に、
"HTTP/2 103 Early Hints"
とLink
ヘッダーが表示されていれば成功です。
まとめ:103 Early Hints
とfetchpriority
のチェックリスト
この記事で解説した内容を、以下のチェックリストで確認しましょう。
- サーバー(またはCDN)が
103 Early Hints
を送信する設定になっている。 - HTTP/2/3クライアントにのみEarly Hintsを送る設定を入れている。
- Early Hintsの
Link
ヘッダーには、LCPに影響する最重要リソース(CSS、フォント、画像)を含めている。 - Early Hintsで指定するリソースに、適切な
Cache-Control
を設定している。 - LCP画像には
fetchpriority="high"
を指定し、優先度を上げている。 - DevToolsを使って、
103 Early Hints
とfetchpriority
が正しく機能しているか検証する。
この記事が、あなたのウェブサイトのLCP改善の一助となれば幸いです。ご覧いただきありがとうございました。