如何評估及最佳化簽署交換,以充分發揮其效益
Signed Exchange (SXG) 是改善網頁速度的方式,主要是最大內容繪製 (LCP)。參照網站 (目前為 Google 搜尋) 連結至網頁時,可以先在使用者點選連結前,將該網頁預先擷取至瀏覽器快取。
預先擷取的網頁可能在轉譯網頁的關鍵路徑上不需要透過網路即可執行。在 4G 連線下,這個網頁的載入時間從 2.8 秒縮短為 0.9 秒 (剩餘的 0.9 秒主要是 CPU 使用時間):
目前大多數發布 SXG 的使用者都會使用 Cloudflare 的 自動簽署交換機制 (ASX) 功能 (但也有開放原始碼選項):
在許多情況下,只要勾選核取方塊啟用這項功能,就能獲得上述大幅改善的效果。有時,您可能需要額外執行幾個步驟,確保這些 SXG 在管道各個階段都能正常運作,並充分發揮預先載入的優勢。
在 Cloudflare 推出後的幾個月內,我一直在各種 論壇上閱讀並回覆問題,並學習如何建議網站如何確保充分發揮 SXG 部署的效益。這篇文章收錄了我的建議。我會逐步說明以下步驟:
- 使用 WebPageTest 分析 SXG 成效。
- 如果「分析」步驟顯示 SXG 管道無法運作,請對 SXG 管道進行偵錯。
- 針對 SXG 預先載入最佳化網頁,包括設定最佳
max-age
和預先載入會阻斷轉譯的子資源。 - 選取適當的實驗和控制組,使用 Google Analytics 評估 SXG 改善幅度。
簡介
SXG 檔案包含網址、一組 HTTP 回應標頭和回應主體,所有內容都經過 Web PKI 憑證的加密簽署。瀏覽器載入 SXG 時,會驗證下列所有項目:
- SXG 尚未過期。
- 簽名會比對網址、標頭、內文和憑證。
- 憑證有效且與網址相符。
如果驗證失敗,瀏覽器會捨棄 SXG,改為擷取已簽署的網址。如果驗證成功,瀏覽器會載入已簽署的回應,並將該回應視為直接來自已簽署的網址。只要未過期或經過修改,即可在任何伺服器上重新代管 SXG。
以 Google 搜尋為例,SXG 可啟用搜尋結果中的網頁預先擷取功能。如果網頁支援 SXG,Google 搜尋可預先擷取網頁的快取副本,並代管在 webpkgcache.com 上。這些 webpkgcache.com 網址不會影響網頁的顯示或行為,因為瀏覽器會遵循原始的已簽署網址。預先載入可讓網頁載入速度大幅提升。
分析
如要瞭解 SXG 的優點,請先使用實驗室工具,在可重現的情況下分析 SXG 效能。您可以使用 WebPageTest 比較有無使用 SXG 預先載入功能的瀑布圖和 LCP。
如要產生不含 SXG 的測試,請按照下列步驟操作:
- 前往 WebPageTest 並登入。登入後,系統會儲存測試記錄,方便您日後進行比較。
- 輸入要測試的網址。
- 前往「進階設定」。(SXG 測試需有進階設定,因此在這裡使用有助於確保測試選項相同)。
- 在「測試設定」分頁中,建議您將「連線」設為 4G,並將「要執行的測試次數」增加至 7 次。
- 按一下「開始測試」。
請按照上述步驟使用 SXG 產生測試,但在點選「Start Test」之前,請前往「Script」分頁,貼上以下 WebPageTest 指令碼,並依指示修改兩個 navigate
網址:
// 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
網址,如果您的網頁尚未顯示在任何 Google 搜尋結果中,您可以使用這個預先載入網頁產生假搜尋結果網頁。
如要判斷第二個 navigate
網址,請使用 SXG Validator Chrome 擴充功能造訪網頁,然後按一下擴充功能圖示,查看快取網址:
完成這些測試後,請前往「測試記錄」,選取兩項測試,然後按一下「比較」:
將 &medianMetric=LCP
附加至比較網址,讓 WebPageTest 針對比較的每一側選取採用 LCP 的執行作業。(預設為 Speed Index 中位數)。
如要比較瀑布,請展開「Waterfall Opacity」 部分,然後拖曳滑桿。如要查看影片,請按一下「調整膠卷設定」,然後在對話方塊中向下捲動,並點選「查看影片」。
如果 SXG 預先擷取成功,您會看到「with SXG」刊登序列未包含 HTML 資料列,且子資源的擷取作業會更快開始。例如,比較此處的「之前」和「之後」:
偵錯
如果 WebPageTest 顯示 SXG 正在預先載入,表示管道中的所有步驟都已成功完成;您可以略過「最佳化」一節,瞭解如何進一步改善 LCP。否則,您必須找出管道中失敗的位置和原因。請繼續閱讀,瞭解如何進行。
發布中
確認網頁是以 SXG 格式產生。為此,您必須假裝是檢索器。最簡單的方法是使用 SXG Validator Chrome 擴充功能:
擴充功能會使用 Accept
要求標頭擷取目前的網址,並指出偏好 SXG 版本。如果 Origin 旁邊顯示勾號 (✅),表示已傳回 SXG;您可以跳至「索引」部分。
如果畫面上顯示叉號 (❌),表示系統未傳回 SXG:
如果啟用了 Cloudflare ASX,出現 X 號 (❌) 的可能性最高的原因,是因為快取控制回應標頭阻止了快取。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。
另一個可能導致出現叉號 (❌) 的原因,是存在 Set-Cookie
以外的這些有狀態回應標頭。ASX 會移除 Set-Cookie
標頭,以符合 SXG 規格。
另一個可能的原因是存在 Vary: Cookie
回應標頭。Googlebot 會擷取 SXG,但不會擷取使用者憑證,因此可能會向多位訪客提供這些內容。如果您根據不同使用者的 Cookie 放送不同 HTML 版本,使用者可能會看到不正確的體驗 (例如未登入帳戶)。
或者,您也可以使用 curl
這類 Chrome 擴充功能:
curl -siH "Accept: application/signed-exchange;v=b3" $URL | less
dump-signedexchange -verify -uri $URL
如果 SXG 存在且有效,您會看到 SXG 的易讀列印內容。否則系統會顯示錯誤訊息。
建立索引
請確認 Google 搜尋已成功編入索引你的 SXG。開啟 Chrome 開發人員工具,然後在 Google 搜尋中搜尋您的網頁。如果已將其索引為 SXG,Google 連結至您網頁的連結就會包含 data-sxg-url
,指向 webpkgcache.com 的副本:
如果 Google 搜尋認為使用者可能會點選某個結果,也會預先擷取該結果:
<link>
元素會指示瀏覽器將 SXG 下載至預先擷取快取。使用者點選 <a>
元素時,瀏覽器會使用快取的 SXG 轉譯網頁。
您也可以前往開發人員工具的「網路」分頁,搜尋含有 webpkgcache
的網址,藉此查看預先載入的證據。
如果 <a>
指向 webpkgcache.com,表示 Signed Exchange 的 Google 搜尋索引已開始運作。您可以直接跳到「擷取」部分。
否則,可能是 Google 尚未重新檢索網頁,因為你已啟用 SXG。請嘗試使用 Google Search Console 網址檢查工具:
如果有 digest: mi-sha256-03=...
標頭,表示 Google 已成功檢索 SXG 版本。
如果找不到 digest
標頭,可能表示 SXG 並未提供給 Googlebot,或是您啟用 SXG 後索引還沒有更新。
如果系統成功檢索 SXG,但仍未連結至該檔案,則可能是未符合 SXG 快取規定。下一節會說明這些內容。
擷取
Google 搜尋在為 SXG 建立索引時,會將副本傳送至 Google SXG 快取,並根據快取規定驗證副本。Chrome 擴充功能會顯示結果:
如果不符合規定,您會看到一個叉號 (❌) 和警告訊息,說明原因:
在這種情況下,網頁會像啟用 SXG 前一樣運作。Google 會連結至原始主機上的網頁,但不會預先擷取 SXG。
如果快取的副本已過期,且系統正在背景重新擷取,您會看到一個沙漏圖示 (⌛):
您也可以參考 SXG 上的 Google 開發人員說明文件,瞭解如何手動查詢快取。
最佳化
如果 SXG Validator Chrome 擴充功能顯示所有勾號 (✅),您可以向使用者提供 SXG 版本!請繼續閱讀,瞭解如何最佳化網頁,以便充分運用 SXG 改善 LCP。
max-age
SXG 到期後,Google SXG 快取會在背景擷取新副本。在等待擷取時,系統會將使用者導向至原始主機上的網頁,系統不會預先擷取主機。設定 Cache-Control: max-age
的時間越長,這項背景擷取作業的發生頻率就越低,進而導致 LCP 因預先擷取而減少的頻率。
這是效能和新鮮度之間的取捨,快取可讓網站擁有者為 SXG 提供 2 分鐘至 7 天的最大年齡,以符合每個網頁的特定需求。我們發現以下情況:
max-age=86400
(1 天) 或更長的時間,可有效提升成效max-age=120
(2 分鐘) 不會
我們希望在進一步研究資料後,能進一步瞭解這兩者之間的差異。
user-agent
我發現使用預先擷取的 SXG 時, LCP 出現上升的情況。我執行了 WebPageTest,比較未使用和已使用 SXG 預先載入功能的中位數結果。點選下方的「後續步驟」:
我發現預先載入功能運作正常。系統會從關鍵路徑中移除 HTML,因此所有子資源都能提早載入。不過,LCP (綠色虛線) 從 2 秒增加到 2.1 秒。
為了診斷這個問題,我查看了膠卷片。我發現網頁在 SXG 中呈現的結果不同。在純 HTML 中,Chrome 判定 LCP 的「最大元素」是標題。不過,在 SXG 版本中,頁面新增了延後載入的橫幅,導致標題被推到下方,並使新的最大元素成為延後載入的 Cookie 同意聲明對話方塊。所有項目的算繪速度都比之前快,但版面配置變更導致指標回報的速度變慢。
經過深入調查,我發現版面配置不同的原因是因為網頁會根據 User-Agent
而有所不同,而且邏輯中出現錯誤。雖然 SXG 檢索標頭指出行動裝置,但該網址仍是電腦版網頁。修正後,瀏覽器再次正確將網頁標題識別為最大元素。
點選「After」後,我發現預先擷取的 LCP 降至 1.3 秒:
所有板型規格都已啟用 SXG。為因應這種情況,請確認符合下列其中一項條件:
- 您的網頁並未由
User-Agent
Vary
(例如,使用回應式設計或不同的行動版/電腦版網址)。 - 如果您的網頁使用動態服務,可使用
<meta name=supported-media content=...>
加註為行動裝置或電腦專用。
子資源
您可以使用 SXG 預先載入子資源 (包括圖片) 和 HTML。Cloudflare ASX 會掃描 HTML 中的同源 (第一方) <link rel=preload>
元素,並將其轉換為 SXG 相容的 Link 標頭。詳情請參閱原始碼,請見這裡和這裡。
如果運作正常,您會在 Google 搜尋中看到其他預先載入內容:
如要針對 LCP 進行最佳化調整,請仔細查看時間軸,找出在轉譯最大元素時,哪些資源位於關鍵路徑上。如果無法預先擷取,請考慮能否從重要路徑移除。請留意是否有隱藏網頁的指令碼,直到載入完成為止。
Google SXG 快取允許最多 20 個子資源預先載入,ASX 則「確保」未超過此上限。不過,加入過多子資源預先載入項目可能會有風險。瀏覽器只會在所有子資源都已完成擷取時使用預先載入的子資源,以防止跨網站追蹤。子資源越多,在使用者點按前往網頁前,子資源完成預先載入的機率就越低。
SXG Validator 目前不會檢查子資源;如要進行偵錯,請在此期間使用 curl
或 dump-signedexchange
。
測量
最佳化 WebPageTest 中的 LCP 改善項目後,建議評估 SXG 預先擷取功能對網站整體效能的影響。
伺服器端指標
評估伺服器端指標 (例如第 1 個位元組時間 (TTFB)) 時,請務必注意,您的網站只會向接受該格式的檢索器提供 SXG。請將 TTFB 的評估範圍限制在來自真人使用者的要求,而非機器人。您可能會發現,產生 SXG 會增加檢索器要求的 TTFB,但這不會影響訪客體驗。
用戶端指標
對用戶端指標 (尤其是 LCP) 而言,SXG 可帶來最大的速度效益。如要評估影響程度,只需啟用 Cloudflare ASX,等待 Googlebot 重新檢索該 AX 並等待 28 天,讓系統再次執行 Core Web Vitals (CWV) 匯總資料,然後查看新的 CWV 數據即可。不過,如果在這個時間範圍內發生其他變化,就很難發現這項變化。
相反地,我發現針對可能受到影響的網頁載入作業「放大檢視」很有幫助,並將其定義為「SXG 會影響 X% 的網頁瀏覽量,在第 75 百分位數改善 LCP 達 Y 毫秒」。
目前,只有在特定情況下才會執行 SXG 預先載入:
- Chromium 瀏覽器 (例如 Chrome 或 Edge,但不適用於 iOS),M98 以上版本
Referer: google.com
或其他 Google 搜尋網域。(請注意,在 Google Analytics 中,參照來源代碼會套用至工作階段中的所有網頁瀏覽次數,而 SXG 預先載入功能只會套用至透過 Google 搜尋直接連結的第一個網頁瀏覽次數)。
請參閱當代研究專區,瞭解如何評估「X% 的網頁瀏覽量」和「將 LCP 縮短 Y 毫秒」。
當代研究
查看實際使用者監控 (RUM) 資料時,請將網頁載入作業分為 SXG 和非 SXG。進行這項操作時,請務必限制要查看的網頁載入組合,以便非 SXG 端符合 SXG 的資格條件,避免出現選取偏誤。否則,下列所有設定「只會」存在於非 SXG 網頁載入組合中,且 LCP 可能與原始版本不同:
- iOS 裝置:由於擁有這些裝置的使用者在硬體或網路速度上的差異。
- 舊版 Chromium 瀏覽器:原因相同。
- 電腦裝置:同樣的原因,或是因為網頁版面配置導致系統選擇不同的「最大元素」。
- 同網站瀏覽 (訪客在網站上點選連結):因為使用者可以重複使用先前載入網頁時快取的子資源。
在 Google Analytics (通用 Analytics) 中,建立兩個自訂維度,範圍為「Hit」,一個名稱為「isSXG」,另一個命名為「referrer」。(內建的「來源」維度具有工作階段範圍,因此不會排除同一網站的導覽)。
建立名為「SXG 對照組」的自訂區隔,並將下列篩選器以 AND 運算結合:
referrer
開頭是https://www.google.
Browser
與Chrome
完全相符Browser
版本與規則運算式^(9[8-9]|[0-9]{3})
相符isSXG
與false
完全相符
建立這個區隔的副本 (命名為「SXG」),不過其中 isSXG
與「true
」完全相符。
在網站範本中,將下列程式碼片段新增至 Google Analytics 程式碼片段上方。這是 ASX 在產生 SXG 時會將 false
變更為 true
的特殊語法:
<script data-issxg-var>window.isSXG=false</script>
請按照建議自訂 Google Analytics 報表指令碼,以便記錄 LCP。如果您使用的是 gtag.js,請修改 'config'
指令來設定自訂維度 (將 'dimension1'
和 'dimension2'
替換為 Google Analytics 建議使用的名稱):
gtag('config', 'YOUR_TRACKING_ID', {
'dimension1': String(isSXG),
'dimension2': document.referrer,
});
如果您使用的是 analytics.js,請按照這裡的說明修改 'create'
指令。
等待幾天收集到一些資料後,請前往 Google Analytics 事件報表,為 SXG 區隔新增細查。這樣應該就會填寫「SXG 影響 X% 網頁瀏覽次數」的 X:
最後,請前往「Web Vitals 報表」,選取「選擇區隔」,然後選取「SXG 對照組」和「SXG」。
按一下「提交」,您應該會看到這兩個區隔的 LCP 分布情形。這應該會填入「第 75 百分位數的 LCP 改善幅度為 Y 毫秒」的 Y 值:
注意事項
套用上述所有篩選器後,SXG 反事實網頁載入就會包含下列項目:
- 快取未命中:如果 Google SXG 快取中沒有特定網址的最新 SXG 副本,系統會重新導向至網站的原始網址。
- 其他結果類型:Google 搜尋目前僅支援標準網頁結果和幾種其他類型的 SXG。其他內容 (例如精選摘要和焦點新聞輪轉介面) 則會連結至網站上的原始網址。
- 不符合資格的網址:如果網站上的部分網頁不符合 SXG 資格 (例如無法快取),就可能會出現在這組中。
在 SXG 網頁載入作業與上述非 SXG 網頁載入作業之間,可能仍會存在偏差,但其幅度應低於「當代研究」一節開頭提到的偏差。舉例來說,可能無法快取的網頁比可快取的網頁慢或快。如果您認為這可能是問題所在,建議您檢視僅限特定 SXG 適用網址的資料,看看結果是否與整體研究相符。
如果您的網站有部分 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 百分位數。跨網站瀏覽通常速度最慢,而且預先擷取的改善能力往往十分重要。
取消訂閱部分網址
最後,您可以為網站上的部分網址停用 SXG,藉此比較 SXG 成效。舉例來說,您可以設定 CDN-Cache-Control: no-store
標頭,避免 Cloudflare ASX 產生 SXG。我不建議這麼做。
相較於其他研究方法,這類研究可能會產生更大的選樣偏差。舉例來說,如果您將網站首頁或類似的熱門網址選入控制組或實驗組,結果可能會大不相同。
區隔劃分研究
評估影響力的理想做法是進行保留研究。很抱歉,您目前無法執行這類測試。我們預計日後支援這類測試。
預留性研究具備以下特性:
- 在實驗組中,部分隨機網頁瀏覽量「會」成為 SXG,但會「延後」,並改為以非 SXG 形式放送。如此一來,就能比對同等使用者、裝置、情境和網頁的「對等」比較結果。
- 這些未顯示的網頁瀏覽 (又稱為反事實) 會在數據分析中標示為「未顯示」。這可讓我們「放大」檢視資料,比較控制組的 SXG 網頁載入情形,以及實驗中的 SXG 對照組。這麼做可減少其他網頁載入作業的雜訊,這些作業不會受到 SXG 預先載入的影響。
雖然這麼做可以消除上述可能的選擇偏誤來源,但無法消除 LCP 維持偏見的風險。這兩項屬性都需要由瀏覽器或參照來源啟用。
結論
大功告成!講了這麼多,希望這篇文章能讓您更全面地瞭解如何在實驗室測試中測試 SXG 效能、如何透過實驗室測試在緊密的回饋循環中提升效能,以及如何評估實際效能。將這些元素結合起來,就能充分運用 SXG,並確保 SXG 能為你的網站和使用者帶來好處。
如果您有其他關於如何擷取 SXG 成效的建議,歡迎與我們聯絡!在 developer.chrome.com 上提出錯誤,並附上改善建議。
如要進一步瞭解已簽署的交換機制,請參閱 web.dev 說明文件和 Google 搜尋說明文件。