署名付きエクスチェンジを測定して最適化し、最大限に改善する方法
署名付きエクスチェンジ(SXG)は、ページ速度(主に Largest Contentful Paint(LCP))を改善する手段です。参照元サイト(現在は Google 検索)がページにリンクを設定する場合、ユーザーがリンクをクリックする前に、そのページをブラウザ キャッシュにプリフェッチできます。
プリフェッチ時に、ページのレンダリングに必要なクリティカル パスでネットワークを必要としないウェブページを作成できます。4G 接続では、このページの読み込み時間が2.8 秒から 0.9 秒に短縮されます(残りの 0.9 秒は主に CPU 使用量によるものです)。
現在、SXG を公開しているほとんどのユーザーは、Cloudflare の使いやすい自動署名交換(ASX)機能を使用しています(オープンソース オプションもあります)。
多くの場合、この機能を有効にするためのチェックボックスをオンにするだけで、上記のような大幅な改善が得られます。パイプラインの各ステージでこれらの SXG が意図したとおりに動作するようにし、プリフェッチを最大限に活用できるようにページを最適化するには、さらにいくつかの手順が必要になることがあります。
Cloudflare のリリースから数か月間、私はさまざまな フォーラムで質問を読み、回答してきました。また、SXG のデプロイを最大限に活用できるようにサイトにアドバイスする方法を学びました。この投稿では、私のアドバイスをまとめています。手順は次のとおりです。
- WebPageTest を使用して SXG のパフォーマンスを分析します。
- 分析ステップで機能していないことが示された場合は、SXG パイプラインをデバッグします。
- 最適な
max-age
の設定やレンダリングをブロックするサブリソースのプリロードなど、SXG プリフェッチ用にページを最適化します。 - 適切なテストグループとコントロール グループを選択して、Google アナリティクスを使用して SXG の改善を測定します。
はじめに
SXG は、URL、一連の HTTP レスポンス ヘッダー、レスポンス本文を含むファイルです。これらはすべて、Web PKI 証明書によって暗号署名されています。ブラウザが SXG を読み込むと、次のすべてが検証されます。
- SXG の有効期限が切れていない。
- 署名が URL、ヘッダー、本文、証明書と一致している。
- 証明書が有効で、URL と一致している。
検証に失敗すると、ブラウザは SXG を破棄し、代わりに署名付き URL を取得します。検証が成功すると、ブラウザは署名付きレスポンスを読み込み、署名付き URL から直接送信されたものとして扱います。これにより、署名後に期限切れになったり変更されたりしていない限り、任意のサーバーに SXG を再ホストできます。
Google 検索の場合、SXG により検索結果のページのプリフェッチが可能になります。SXG をサポートするページの場合、Google 検索は webpkgcache.com でホストされているページのキャッシュ コピーをプリフェッチできます。ブラウザは元の署名付き URL を尊重するため、これらの webpkgcache.com URL はページの表示や動作に影響しません。プリフェッチを使用すると、ページの読み込み時間を大幅に短縮できます。
分析
SXG のメリットを確認するには、まずラボツールを使用して、再現可能な条件で SXG のパフォーマンスを分析します。WebPageTest を使用して、SXG プリフェッチありとなしでのウォーターフォール(および LCP)を比較できます。
次のように、SXG のないテストを生成します。
- WebPageTest にアクセスしてログインします。ログインすると、テスト履歴が保存され、後で簡単に比較できます。
- テストする URL を入力します。
- [詳細設定] に移動します。(SXG テストには高度な構成が必要になるため、ここで使用するとテスト オプションが同じになります)。
- [テスト設定] タブで、[接続] を 4G に設定し、[実行するテストの数] を 7 に増やすとよいでしょう。
- [テストを開始] をクリックします。
上記と同じ手順で SXG を使用してテストを生成します。ただし、[テストを開始] をクリックする前に、[スクリプト] タブに移動し、次の WebPageTest スクリプトを貼り付け、指示に沿って 2 つの navigate
URL を変更します。
// Disable log collection for the first step. We only want the waterfall for the target navigation.
logData 0
// Visit a search result page that includes your page.
navigate https://google.com/search?q=site%3Asigned-exchange-testing.dev+image
// Wait for the prefetch to succeed.
sleep 10
// Re-enable log collection.
logData 1
// Navigate to the prefetched SXG on the Google SXG Cache.
navigate https://signed--exchange--testing-dev.webpkgcache.com/doc/-/s/signed-exchange-testing.dev/sxgs/valid-image-subresource.html
最初の navigate
URL で、ページがまだ Google 検索の検索結果に表示されていない場合は、このプリフェッチ ページを使用して、この目的のための疑似検索結果ページを生成できます。
2 番目の navigate
URL を確認するには、SXG Validator Chrome 拡張機能を使用してページにアクセスし、拡張機能アイコンをクリックしてキャッシュ URL を表示します。
テストが完了したら、[テスト履歴] に移動し、2 つのテストを選択して [比較] をクリックします。
比較 URL に &medianMetric=LCP
を追加して、WebPageTest が比較の両側で LCP の中央値が最も高い実行を選択するようにします。(デフォルトは Speed Index の中央値です)。
ウォーターフォールを比較するには、[ウォーターフォールの不透明度] セクションを開き、スライダーをドラッグします。動画を表示するには、[フィルムストリップの設定を調整] をクリックし、ダイアログ内で下にスクロールして [動画を表示] をクリックします。
SXG プリフェッチが成功すると、「with SXG」ウォーターフォールには HTML の行が含まれず、サブリソースの取得がより早く開始されます。たとえば、次の「前」と「後」を比較します。
デバッグ
WebPageTest で SXG がプリフェッチされていると表示される場合、パイプラインのすべてのステップが成功しています。[最適化] セクションに進んで、LCP をさらに改善する方法を確認してください。エラーがパイプラインのどの部分で発生し、なぜ発生したのかを特定する必要があります。方法については、以下をご覧ください。
公開
ページが SXG として生成されていることを確認します。そのためには、クローラーのふりをする必要があるのです。最も簡単な方法は、SXG Validator Chrome 拡張機能を使用することです。
拡張機能は、SXG バージョンを優先することを示す Accept
リクエスト ヘッダーを使用して現在の URL を取得します。[送信元] の横にチェックマーク(✅)が表示されている場合は、SXG が返されたことを意味します。インデックス処理のセクションに進むことができます。
バツ印(❌)が表示される場合は、SXG が返されなかったことを意味します。
Cloudflare ASX が有効になっている場合、クロスマーク(❌)が表示される最も一般的な理由は、キャッシュ制御レスポンス ヘッダーが原因でキャッシュに保存できないためです。ASX は、次の名前のヘッダーを参照します。
Cache-Control
CDN-Cache-Control
Surrogate-Control
Cloudflare-CDN-Cache-Control
これらのヘッダーのいずれかに次のヘッダー値が含まれている場合、SXG は生成されません。
private
no-store
no-cache
max-age
は 120 未満(120 以上のs-maxage
でオーバーライドしない限り)
このような場合、ASX は SXG を作成しません。SXG は複数回のアクセスや複数のユーザーに対してキャッシュに保存され、再利用される可能性があるためです。
クロスマーク(❌)が表示されるもう 1 つの理由として、Set-Cookie
を除くこれらのステートフル レスポンス ヘッダーのいずれかが存在することも考えられます。ASX は、SXG 仕様に準拠するために Set-Cookie
ヘッダーを削除します。
Vary: Cookie
レスポンス ヘッダーが存在することも原因として考えられます。Googlebot はユーザーの認証情報なしで SXG を取得し、複数の訪問者に配信することがあります。Cookie に基づいて異なるユーザーに異なる HTML を配信すると、ログアウトしたビューなど、正しくないエクスペリエンスが表示される可能性があります。
Chrome 拡張機能の代わりに、curl
などのツールを使用することもできます。
curl -siH "Accept: application/signed-exchange;v=b3" $URL | less
または dump-signedexchange
:
dump-signedexchange -verify -uri $URL
SXG が存在し、有効な場合は、SXG の判読可能な出力が表示されます。そうしないと、エラー メッセージが表示されます。
インデックス登録
SXG が Google Search によって正常にインデックスに登録されていることを確認します。Chrome DevTools を開き、ページを Google 検索します。SXG としてインデックスに登録されている場合、Google のページへのリンクには、webpkgcache.com のコピーを指す data-sxg-url
が含まれます。
ユーザーが検索結果をクリックする可能性が高いと Google 検索が判断した場合は、その検索結果もプリフェッチされます。
<link>
要素は、SXG をプリフェッチ キャッシュにダウンロードするようブラウザに指示します。ユーザーが <a>
要素をクリックすると、ブラウザはキャッシュに保存された SXG を使用してページをレンダリングします。
DevTools の [ネットワーク] タブに移動し、webpkgcache
を含む URL を検索すると、プリフェッチの証拠を確認することもできます。
<a>
が webpkgcache.com を参照している場合、署名付きエクスチェンジの Google 検索インデックス登録が機能しています。取り込みセクションに進んでください。
そうでない場合は、SXG を有効にした後、Google がまだページを再クロールしていない可能性があります。Google Search Console の URL 検査ツールをお試しください。
digest: mi-sha256-03=...
ヘッダーが存在する場合は、Google が SXG バージョンを正常にクロールしたことを示します。
digest
ヘッダーが存在しない場合、SXG が Googlebot に配信されていないか、SXG を有効にした後でインデックスが更新されていないことを示している可能性があります。
SXG が正常にクロールされてもリンクされていない場合は、SXG キャッシュ要件を満たしていない可能性があります。これらについては、次のセクションで説明します。
取り込み
Google 検索が SXG をインデックス登録すると、そのコピーが Google SXG キャッシュに送信され、キャッシュ要件に基づいて検証されます。Chrome 拡張機能に結果が表示されます。
チェックマーク(✅)が表示されている場合は、[最適化] に進んでください。
要件を満たしていない場合は、× マーク(❌)と、その理由を示す警告メッセージが表示されます。
この場合、ページは SXG を有効にする前と同じように動作します。Google は、SXG プリフェッチなしで元のホストのページにリンクします。
キャッシュに保存されたコピーの有効期限が切れ、バックグラウンドで再取得されている場合は、砂時計(⌛)が表示されます。
SXG に関する Google デベロッパー向けドキュメントには、キャッシュを手動でクエリする手順も記載されています。
最適化
Chrome 拡張機能の SXG Validator にすべてのチェックマーク(✅)が表示されている場合は、ユーザーに配信できる SXG が作成されています。SXG で LCP を最大限改善できるようにウェブページを最適化する方法については、以下をご覧ください。
max-age
SXG が期限切れになると、Google SXG キャッシュはバックグラウンドで新しいコピーを取得します。フェッチを待っている間、ユーザーは元のホストのページにリダイレクトされますが、このページはプリフェッチされません。Cache-Control: max-age
を長く設定すると、このバックグラウンド フェッチの頻度が低下し、プリフェッチによって LCP を短縮できる頻度が高くなります。
これはパフォーマンスと更新頻度のトレードオフです。キャッシュを使用すると、サイト所有者は各ページの特定のニーズに合わせて、2 分~ 7 日の範囲で SXG の有効期限を設定できます。経験則では、次のようなことがわかります。
max-age=86400
(1 日)以上はパフォーマンスに適していますmax-age=120
(2 分)は
今後、データをさらに調査し、この 2 つの値の間にある値について詳しく把握したいと考えています。
user-agent
プリフェッチされた SXG を使用した際に、LCP が増加したことがあります。WebPageTest を実行し、SXG プリフェッチありとなしでの中央値を比較しました。以下の [After] をクリックします。
プリフェッチが機能していることを確認しました。HTML がクリティカル パスから削除されるため、すべてのサブリソースをより早く読み込むことができます。一方、LCP(緑色の点線)は2 秒から 2.1 秒に増加しました。
この問題を診断するため、フィルム ストリップを確認しました。SXG ではページが異なる方法でレンダリングされることを確認しました。プレーン HTML では、Chrome は LCP の「最大要素」をヘッドラインと判断しました。しかし、SXG バージョンでは、ページに遅延読み込みバナーが追加され、ヘッドラインが折り返しの下に押しやられ、遅延読み込みの Cookie 同意ダイアログが新しい最大要素になりました。すべてが以前よりも速くレンダリングされたが、レイアウトが変更されたため、指標では遅く報告された。
詳しく調べたところ、レイアウトが異なる理由は、ページが User-Agent
によって異なり、ロジックにエラーがあったことがわかりました。SXG クロール ヘッダーがモバイルを示しているにもかかわらず、パソコン向けのページが配信されていました。この問題が修正されると、ブラウザはページの見出しを最大要素として正しく識別できるようになりました。
[After] をクリックすると、プリフェッチされた LCP が1.3 秒に短縮されました。
SXG はすべてのフォーム ファクタで有効になっています。そのためには、次のいずれかを確認してください。
- ページが
User-Agent
によってVary
されていない(レスポンシブ デザインやモバイルとパソコンの URL が別々になっているなど)。 - ページで動的配信を使用している場合は、
<meta name=supported-media content=...>
を使用して、モバイル専用またはパソコン専用としてアノテーションが付けられます。
サブリソース
SXG を使用すると、HTML とともにサブリソース(画像を含む)をプリフェッチできます。Cloudflare ASX は、HTML をスキャンして同じオリジン(ファーストパーティ)の <link rel=preload>
要素を検出し、SXG 互換のリンク ヘッダーに変換します。詳細については、こちらとこちらのソースコードをご覧ください。
正常に動作している場合は、Google 検索からの追加のプリフェッチが表示されます。
LCP を最適化するには、ウォーターフォールを詳しく調べ、最大要素のレンダリングに必要なクリティカル パス上にあるリソースを特定します。プリフェッチできない場合は、クリティカル パスから除外できるかどうかを検討します。読み込みが完了するまでページを非表示にするスクリプトに注意してください。
Google SXG キャッシュでは、最大 20 個のサブリソースのプリロードが許可され、ASX は、この上限が超過しないように保証します。ただし、サブリソースのプリロードを追加しすぎると、ブラウザは、クロスサイト トラッキングを防止するために、プリロードされたサブリソースをすべて取得が完了した場合のみ使用します。サブリソースが多いほど、ユーザーがページに移動する前にすべてのサブリソースのプリフェッチが完了する可能性は低くなります。
現在、SXG Validator はサブリソースをチェックしません。デバッグするには、curl
または dump-signedexchange
を使用してください。
測定
WebPageTest で LCP の改善を最適化したら、SXG プリフェッチがサイトの全体的なパフォーマンスに与える影響を測定することをおすすめします。
サーバーサイドの指標
最初の 1 バイトまでの時間(TTFB)などのサーバーサイド指標を測定する際は、サイトが SXG を提供するクロールツールは、その形式をサポートしているものだけであることを覚えておくことが重要です。TTFB の測定は、ボットではなく実際のユーザーからのリクエストに限定します。SXG を生成すると、クロール リクエストの TTFB が増加する場合があります。これは、訪問者のエクスペリエンスには影響しません。
クライアントサイドの指標
SXG は、クライアントサイドの指標(特に LCP)の速度向上に最も効果的です。効果を測定する場合は、Cloudflare ASX を有効にして Googlebot による再クロールが完了するのを待ってから、Core Web Vitals(CWV)の集計が完了するまでさらに 28 日間待ってから、新しい CWV の数値を確認します。ただし、この期間中に他の多くの変更が行われた場合は、その変化を見つけるのが難しい場合があります。
代わりに、影響を受ける可能性のあるページ読み込みに「ズームイン」し、「SXG はページビューの X% に影響し、75 パーセンタイルにおいて LCP を Y ミリ秒改善しました」というように表現することをおすすめします。
現在、SXG プリフェッチは特定の条件下でのみ行われます。
- Chromium ブラウザ(iOS を除く Chrome や Edge など)バージョン M98 以降
Referer: google.com
またはその他の Google 検索ドメイン。(Google アナリティクスでは、参照元タグはセッション内のすべてのページビューに適用されますが、SXG プリフェッチは Google 検索から直接リンクされた最初のページビューにのみ適用されます)。
「X% のページビュー」と「LCP を Y ミリ秒改善」を測定する方法については、最新の調査セクションをご覧ください。
現代の研究
リアルユーザー モニタリング(RUM)データを確認する際は、ページ読み込みを SXG と SXG 以外に分割する必要があります。選択バイアスを回避するには、SXG 以外の側が SXG の資格要件を満たすように、対象とするページ読み込みのセットを制限することが重要です。そうでない場合、次の要素はすべて、SXG 以外のページ読み込みのセットにのみ存在し、LCP が本質的に異なる可能性があります。
- iOS デバイス: これらのデバイスを使用しているユーザーのハードウェアやネットワーク速度が異なるためです。
- 古い Chromium ブラウザ: 同じ理由です。
- パソコンデバイス: 上記と同じ理由、またはページ レイアウトによって別の「最大要素」が選択されるため。
- 同一サイト内ナビゲーション(サイト内のリンクをたどる訪問者): 前回のページ読み込みでキャッシュに保存されたサブリソースを再利用できるからです。
Google アナリティクス(UA)で、スコープを「ヒット」に設定した2 つのカスタム ディメンションを作成します。1 つは「isSXG」、もう 1 つは「referrer」という名前にします。(組み込みの「参照元」ディメンションはセッション スコープであるため、同一サイト内ナビゲーションを除外しません)。
次のフィルタを AND 演算で結合して、「SXG 対照実験」という名前のカスタム セグメントを作成します。
- 「
referrer
」の先頭が「https://www.google.
」と一致 Browser
はChrome
と完全に一致するBrowser
バージョンが正規表現^(9[8-9]|[0-9]{3})
と一致するisSXG
はfalse
と完全に一致する
このセグメントのコピーを作成して「SXG」という名前を付けます。ただし、isSXG
は true
と完全に一致するようにします。
サイト テンプレートで、Google アナリティクスのスニペットの上に次のスニペットを追加します。これは、ASX が SXG の生成時に false
を true
に変更する特別な構文です。
<script data-issxg-var>window.isSXG=false</script>
Google アナリティクスのレポート スクリプトを推奨どおりカスタマイズして、LCP を記録します。gtag.js を使用している場合は、'config'
コマンドを変更してカスタム ディメンションを設定します('dimension1'
と 'dimension2'
は、Google アナリティクスで使用するよう指定されている名前に置き換えます)。
gtag('config', 'YOUR_TRACKING_ID', {
'dimension1': String(isSXG),
'dimension2': document.referrer,
});
analytics.js を使用している場合は、こちらに記載されているように 'create'
コマンドを変更します。
データが収集されるまで数日待ってから、Google アナリティクスのイベント レポートに移動し、SXG セグメントのドリルダウンを追加します。これにより、「SXG が X% のページビューに影響している」の X が入力されます。
最後に、ウェブ バイタル レポートに移動し、[セグメントを選択] を選択して、[SXG 対照群] と [SXG] を選択します。
[送信] をクリックすると、2 つのセグメントの LCP の分布が表示されます。これにより、「75 パーセンタイルにおいて LCP を Y ミリ秒改善」の Y が入力されます。
注意点
上記のフィルタをすべて適用すると、SXG の反実仮想ページ読み込みは次のような内容になります。
- キャッシュに一致するデータがない: 特定の URL の SXG の最新のコピーが Google SXG キャッシュにない場合、サイトの元の URL にリダイレクトされます。
- その他の検索結果タイプ: 現在、Google 検索でサポートされているのは、標準のウェブ検索結果とその他のいくつかのタイプの SXG のみです。一方、強調スニペットやトップニュース カルーセルなどでは、サイトの元の URL にリンクされます。
- 対象外の URL: サイト上の一部のページが SXG の対象外(キャッシュに保存できないなど)である場合、このセットに表示されることがあります。
SXG ページの読み込みと、上記の SXG 以外のページの読み込みの間に残るバイアスがある可能性がありますが、そのバイアスは最新の調査セクションの上部に記載されているバイアスよりも小さいはずです。たとえば、キャッシュに保存できないページがキャッシュに保存できるページよりも遅い場合や、速い場合があります。これが問題であると思われる場合は、特定の SXG 対象 URL に限定したデータを調べて、その結果が全体的な調査と一致しているかどうかを確認することをおすすめします。
サイトに AMP ページがある場合、Google 検索からすでにプリフェッチされているため、SXG を有効にしてもパフォーマンスが向上する可能性は低くなります。関連する変更をさらに「拡大」するには、そのようなページを除外するフィルタを追加することを検討してください。
最後に、選択バイアスをすべて解消しても、生存バイアスによって LCP の改善が RUM 統計情報の低下のように見えるリスクがあります。こちらの記事では、そのリスクについて詳しく説明しています。また、放棄が発生しているかどうかを検出するために、なんらかの放棄指標を確認することを提案しています。
前後比較調査
最新の調査結果を裏付けるために、SXG を有効にする前と後で LCP を比較すると役立つ場合があります。上記のバイアスが発生しないように、SXG ページビューに限定しないでください。代わりに、SXG の対象となる結果(上記のセグメント定義に isSXG
制約がない結果)を確認します。
なお、Google 検索がサイト上のすべてのページを再クロールして SXG が有効になっていることを確認するまでに、数週間かかることがあります。この数週間の間に、他にもバイアスが発生する可能性があります。
- 新しいブラウザのリリースやユーザーのハードウェアの改善により、ページの読み込み時間が短縮される場合があります。
- 祝日などの重要なイベントが原因で、トラフィックが通常とは異なる結果になる可能性があります。
また、上記の調査を確認するために、全体的な 75 パーセンタイル LCP の前後を確認することも有用です。母集団のサブセットについて学んだとしても、それが母集団全体についての情報になるとは限りません。たとえば、SXG によってページ読み込みの 10% が 800 ミリ秒短縮されたとします。
- これらのページの読み込みがすでに最速の 10% に含まれている場合、75 パーセンタイルにはまったく影響しません。
- ページの読み込みが最も遅い 10% に該当する場合でも、そもそも 75 パーセンタイル LCP よりも 800 ミリ秒以上遅い場合は、75 パーセンタイルにまったく影響しません。
これらは極端な例であり、現実を反映していない可能性がありますが、問題を説明するうえで役立つと思います。実際には、SXG はほとんどのサイトで 75 パーセンタイル(75% のサイトより上)に影響する可能性があります。クロスサイト ナビゲーションは最も遅い傾向があり、プリフェッチによって大幅な改善が見込めます。
一部の URL をオプトアウトする
最後に、SXG のパフォーマンスを比較する方法として、サイト上の一部の URL で SXG を無効にするという方法があります。たとえば、CDN-Cache-Control: no-store
ヘッダーを設定して、Cloudflare ASX が SXG を生成しないようにできます。おすすめしません。
他の調査方法よりも選択バイアスのリスクが高くなります。たとえば、サイトのホームページと同様の人気を誇る URL のどちらがコントロール グループとテストグループに選択されるかによって、結果に大きな違いが生じる可能性があります。
ホールドバック スタディ
影響の測定に最適な方法は、ホールドバック テストを実施することです。残念ながら、現在のところ、このようなテストは行えません。今後、このようなテストのサポートを追加する予定です。
ホールドバック テストには次のプロパティがあります。
- テストグループでは、SXG になるページビューの一部がランダムに「保留」され、代わりに SXG 以外のページビューとして配信されます。これにより、同等のユーザー、デバイス、シナリオ、ページを「同等」に比較できます。
- 抑制された(反事実的)ページビューは、アナリティクスでそのようにラベル付けされます。これにより、データを「ズームイン」して、コントロールの SXG ページ読み込みとテストの SXG 対照群を比較できます。これにより、SXG プリフェッチの影響を受けない他のページ読み込みによるノイズが軽減されます。
これにより、前述の選択バイアスの原因を排除できますが、LCP の存続バイアスのリスクを排除することはできません。どちらのプロパティも、ブラウザまたは参照元のいずれかを有効にする必要があります。
まとめ
ぜひここまでお読みいただき、ありがとうございました。ラボテストで SXG のパフォーマンスをテストする方法、ラボテストと緊密なフィードバック ループでパフォーマンスを最適化する方法、そして最終的に実環境でパフォーマンスを測定する方法について、より包括的な理解を深めていただければ幸いです。これらをすべて組み合わせることで、SXG を最大限に活用し、SXG がサイトとユーザーにメリットをもたらすようにすることができます。
SXG のパフォーマンスを高める方法について、他にご提案がございましたら、お気軽にお問い合わせください。改善案とともに developer.chrome.com にバグを報告します。
署名付きエクスチェンジの詳細については、web.dev のドキュメントと Google 検索のドキュメントをご覧ください。