使用 Early Hints 伺服器思考時間,加快網頁載入速度

瞭解您的伺服器如何傳送重要子資源的提示給瀏覽器。

Kenji Baheux
Kenji Baheux

什麼是早期提示?

網站變得越來越複雜。因此,伺服器需要執行重要工作 (例如存取資料庫,或是存取原始伺服器的 CDN) 來產生要求網頁的 HTML,這種情況並不常見。不幸的是,這種「伺服器思考時間」會導致瀏覽器開始轉譯網頁之前,發生額外的延遲。事實上,只要伺服器準備回應,連線就確實會處於閒置狀態。

圖片顯示伺服器思考載入網頁和載入其他資源之間的時間差為 200 毫秒。
如未及早提示,系統會全面封鎖伺服器上的所有內容,以決定如何回應主要資源。

早期提示是一個 HTTP 狀態碼 (103 Early Hints),用於在最終回應之前傳送初步 HTTP 回應。這樣一來,當伺服器忙於產生主要資源時,伺服器就能將重要子資源 (例如網頁的樣式表、重要的 JavaScript) 或來源,向瀏覽器傳送提示。瀏覽器可以在等待主要資源的同時,使用這些提示暖機連線及要求子資源。換句話說,早期提示可協助瀏覽器預先完成一些工作,加快網頁載入速度,利用「伺服器思考時間」的優勢。

這張圖片呈現了 Early Hints 如何讓頁面傳送部分回應。
採用早期提示:伺服器可提供資源提示的部分回應,同時決定最終回應

在某些情況下,如 Shopifyby Cloudflare 觀察到,最大內容繪製的效能改善速度可能從數百毫秒縮短,但也比較快上一秒,如以下比較結果所示:

比較兩個網站。
在測試網站上使用 WebPageTest (Moto G4 - DSL) 完成 Early Hints 的比較之前/之後

如何使用早期提示

想充分運用 Early Hints 的第一步,第一步就是找出熱門的到達網頁,也就是使用者造訪網站時通常進入的網頁。如果許多使用者從其他網站連到您的網站,這個首頁或熱門的產品資訊頁面可能就是首頁或熱門產品資訊頁面。相較於其他頁面,早期提示的重要性更勝以往,因為當使用者瀏覽網站時,早期提示的實用性會降低 (也就是說,瀏覽器較有可能在第二或第三個瀏覽動作中取得所有所需的子資源)。此外,也建議你留下良好第一印象!

設定到達網頁優先順序清單後,下一步就是找出適合顯示 preconnectpreload 提示的來源或子資源。一般而言,這些來源和子資源是影響主要使用者指標的來源和子資源,例如最大內容繪製首次顯示內容所需時間。更具體地找出會封鎖的子資源,例如同步 JavaScript、樣式表,甚至是網路字型。同樣地,找出代管子資源的來源,這些來源對於重要使用者指標的貢獻度都很高。

另請注意,如果您的主要資源已採用 preconnectpreload,不妨考慮這些來源或資源屬於早期提示的候選項目。詳情請參閱如何最佳化 LCP。不過,單純將 preconnectpreload 指令從 HTML 複製到早期提示可能未達到最佳效果

在 HTML 中使用這些功能時,一般會希望 Preload Scanner 無法在 HTML 中找到的 preconnectpreload 資源,例如以免遲到的字型或背景圖片。針對早期提示,我們不會提供 HTML,因此建議您改為將 preconnect 改為指向重要網域或 preload (用原本就在 HTML 中可能「早」可能發現的 preload」重要資源,例如預先載入 main.cssapp.js)。此外,並非所有瀏覽器都支援用於早期提示的 preload,請參閱瀏覽器支援

第二步是盡可能降低在可能過時或不再用於主要資源使用的資源或來源上使用早期提示的風險。舉例來說,經常更新且版本化的資源 (例如 example.com/css/main.fa231e9c.css) 可能不是最佳選擇。請注意,這個問題並非僅適用於早期提示,因此適用於任何可能存在的 preloadpreconnect。這是最適合處理自動化或範本作業的細節。舉例來說,手動程序較有可能在 preload 和使用資源的實際 HTML 標記之間產生不相符的雜湊或版本網址。

例如以下流程:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]

伺服器預測需要使用 main.abcd100.css,並建議使用早期提示預先載入該函式:

103 Early Hints
Link: </main.abcd100.css>; rel=preload; as=style
[...]

稍後,網頁 (包括連結的 CSS) 就會放送。很抱歉,這項 CSS 資源經常更新,而主要資源預測的 CSS 資源 (abcd100) 已有五個版本 (abcd105)。

200 OK
[...]
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.abcd105.css">

一般而言,請設計資源與來源相對穩定,且在大部分情況下與主要資源的結果無關。如有需要,建議您將主要資源分成兩個部分:與早期提示搭配使用的穩定部分,以及瀏覽器接收主要資源後要擷取的更動態部分:

<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">

最後,在伺服器端找出已知支援早期提示的瀏覽器傳送的主要資源要求,並立即以 103 Early Hints 做出回應。在 103 回應中,加入相關的預先連線和預先載入提示。主要資源準備就緒後,請透過一般回應進行後續追蹤 (例如,如果成功,則為 200)。為顧及回溯相容性,建議您在最終回應中一併加入 Link HTTP 標頭,甚至使用在產生主要資源時能明顯看出的重要資源進行擴增 (例如,依照「分割至二」建議時,金鑰資源的動態部分)。如下所示:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]
103 Early Hints
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script

稍後片刻:

200 OK
Content-Length: 7531
Content-Type: text/html; charset=UTF-8
Content-encoding: br
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script
Link: </experimental.3eab3290.css>; rel=preload; as=style
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">
   <script src="/common.js"></script>
   <link rel="preconnect" href="https://fonts.googleapis.com">

瀏覽器支援

雖然所有主要瀏覽器都支援 103 早期提示,但每個瀏覽器可傳送的指令各不相同:

預先連線支援:

瀏覽器支援

  • 103
  • 103
  • 120
  • 17

預先載入支援:

瀏覽器支援

  • 103
  • 103
  • 123
  • x

此外,Chrome 開發人員工具也提供 103 早期提示支援

伺服器支援

以下簡要說明在常見的開放原始碼軟體 HTTP 伺服器軟體中,早期提示的支援等級:

以更輕鬆的方式啟用早期提示

如果您使用的是下列 CDN 或平台,可能不需要手動導入早期提示。如要瞭解解決方案供應商是否支援早期提示,請參閱解決方案供應商的線上說明文件,或參閱此處僅列出部分項目:

如何避免對不支援早期提示的客戶發生問題

100 範圍中的資訊 HTTP 回應屬於 HTTP 標準,但部分較舊的用戶端或漫遊器可能會遇到這些問題,因為在 103 早期提示推出之前,這些回應很少用於一般網路瀏覽。

只有在回應傳送 sec-fetch-mode: navigate HTTP 要求標頭的用戶端時,才會發出 103 Early Hints,可確保只有在能夠等待後續回應的新客戶中,才會傳送這類提示。此外,由於只有瀏覽要求支援早期提示 (請參閱目前限制),因此這種做法還有無需在其他要求中傳送這類要求的好處。

此外,早期提示建議僅透過 HTTP/2 或 HTTP/3 連線傳送

進階模式

如果您已將「早期提示」完全套用至主要到達網頁,且想要尋找更多商機,不妨參考下列進階模式。

對於一般使用者歷程中的「第 n」nth個網頁要求,建議您針對網頁順序較低的內容 (也就是針對優先順序較低的資源,使用早期提示) 來設計早期提示。由於我們建議將重心放在高優先順序、會阻擋轉譯的子資源或來源,因此這聽起來或許合乎常理。但是,訪客瀏覽網站一段時間後,很有可能會他們的瀏覽器已擁有所有重要資源。接下來,您可以將注意力轉向優先順序較低的資源。比如使用 Early Hints 載入產品圖片,或使用不太常見的使用者互動時所需的額外的 JS/CSS。

目前限制

以下是 Chrome 內建的早期提示功能限制:

  • 僅適用於導覽要求 (也就是頂層文件的主要資源)。
  • 僅支援 preconnectpreload (也就是不支援 prefetch)。
  • 如果 Chrome 在最終回應後接著進行跨來源重新導向,將導致 Chrome 捨棄使用 Early Hints 取得的資源和連線。

其他瀏覽器的限制類似,有些還會進一步將 103 個早期提示設定為僅限 preconnect

後續步驟

我們可能會根據社群的喜好,運用下列功能擴大導入早期提示:

  • 在子資源要求時傳送早期提示。
  • 透過 iframe 主要資源要求傳送早期提示。
  • 支援在早期提示中預先擷取。

歡迎提供意見,協助我們瞭解應優先處理哪些面向,以及進一步改善早期提示。

與 H2/推送的關係

如果您熟悉已淘汰的 HTTP2/Push 功能,可能想知道早期提示的差異。儘管早期提示需要往返瀏覽器開始擷取重要子資源,使用 HTTP2/Push 時,伺服器仍可開始在回應推送子資源。雖然這聽起來很棒,但造成了關鍵的結構缺點:使用 HTTP2/Push 時,很難避免推送瀏覽器現有的子資源。這種「過度推送」的效果導致網路頻寬用量的效率下降,導致效能下降。整體而言,Chrome 資料顯示,HTTP2/Push 實際上並沒有降低網路效能的淨值。

相較之下,早期提示在實務上表現較佳,因為這項技術結合了傳送初步回應的功能,以及提示,避免瀏覽器擷取或連線至應用程式的實際需求。雖然 Early Hints 並未涵蓋 HTTP2/Push 理論上能解決的所有使用情境,但我們相信 Early Hints 是更實用的解決方案,可加快導覽速度。

Pierre Bamin 的縮圖圖片。