發布日期:2025 年 3 月 7 日
Speculation Rules API 可讓使用者透過預先載入或預先轉譯未來的網頁導覽,獲得更快 (甚至是即時) 的網頁導覽體驗。
這個 API 的設計理念是為了讓您輕鬆實作,但複雜網站在使用前,仍需考量一些事項。本指南可協助網站擁有者瞭解這些考量因素。
規劃
在實作推測規則前,建議您考慮如何實作 API (因為有幾種選擇),以及推測的成本 (可協助您判斷要推測哪些網頁)。
決定如何實作推測規則
您首先需要決定如何在網站上實作投機規則,因為您可以使用多種方法:
- 直接在網頁的 HTML 中
- 使用 JavaScript
- 使用 HTTP 標頭
最終,每種方法都會產生相同的效果,但在實作難度和彈性方面,某些方法可能會更勝一籌。
網站應選擇最適合的選項,必要時甚至可以同時使用多種選項。您也可以使用外掛程式 (例如 WordPress 的 Speculative Loading 外掛程式) 或程式庫/平台來實作,這些工具可能會為您做出選擇,但還是建議您瞭解可用的選項。
直接在網頁的 HTML 中加入推測規則
只要在 HTML 中加入 <script type="speculationrules">
元素,即可直接在網頁上實作投機規則。您可以使用範本,在靜態網站的建構時間新增這項資訊,也可以在伺服器收到網頁要求時,在執行階段新增這項資訊。邊緣工作站甚至可以將這些資訊插入 HTML 中 (不過,本指南稍後會討論的 HTTP 標頭方法可能更容易操作)。
這樣一來,您就能在整個網站中加入靜態規則,但文件規則仍可保持動態,因為您可以使用由 CSS 類別觸發的規則,選擇要從網頁中轉譯的網址:
<script type="speculationrules">
{
"prerender": [{
"where": { "selector_matches": ".prerender" }
}],
"prefetch": [{
"where": { "selector_matches": ".prefetch" }
}]
}
</script>
先前的指令碼會使用 prerender
類別預先轉譯連結,並在連結具有 prefetch
類別時進行預先擷取。這可讓開發人員在 HTML 中加入這些類別,以觸發推測。
除了在網頁的初始 HTML 中加入這些類別的連結,如果這些類別是由應用程式動態新增,連結也會一併推測,讓應用程式可視需要觸發 (及移除) 推測。這比建立或移除更具體的推測規則更簡單。如果您希望大部分網站使用相同的基本規則,以及特定網頁的規則,也可以在每個網頁中加入多個推測規則。
或者,如果您需要使用更具體的推測規則,您可以使用特定網頁或範本規則,為特定網頁或網頁類型設定不同的規則。
最後,伺服器端轉譯的網頁也可以根據伺服器可用的任何資訊,設定更多動態規則,例如該網頁的分析資訊,或特定網頁的常見使用者歷程。
使用 JavaScript 新增推測規則
除了在網頁指令碼中加入規則,您也可以使用 JavaScript 插入規則。這樣一來,您可能就不需要頻繁更新網頁範本。舉例來說,代碼管理工具可用來插入規則,快速推出推測規則,並在必要時快速關閉這些規則。
這個選項也允許根據使用者與網頁的互動方式,設定動態的用戶端規則。舉例來說,如果使用者將商品加入購物車,您可以預先轉譯結帳頁面。或者,您也可以使用這項功能,根據特定條件觸發投機交易。雖然 API 包含積極性設定,可允許基本互動式規則,但 JavaScript 可讓開發人員使用自己的邏輯,決定何時在哪些網頁上進行推測。
如先前所述,另一種插入新規則的方法是在網頁上設定基本文件規則,並在連結中加入適當的類別,讓 JavaScript 觸發文件規則,以便與規則相符。
使用 HTTP 標頭新增推測規則
開發人員的最後一個選項是使用 HTTP 標頭加入規則:
Speculation-Rules: "/speculationrules.json"
關於規則資源 (本例中的 /speculationrules.json
) 的提交和使用方式,有其他規定。
這個選項可讓 CDN 更輕鬆地部署,無需變更文件內容。這表示您無法使用 JavaScript 動態變更推測規則。不過,使用 CSS 選取器觸發條件的文件規則仍可允許動態變更,例如從連結中移除 prerender
類別。
與 JavaScript 選項類似,使用 HTTP 標頭導入推測規則時,可讓規則獨立於網站內容實作,方便您新增及移除規則,而無須重新建構整個網站。
考量成本影響
在導入投機規則前,請先花點時間考量使用者和網站透過這個 API 的成本影響。費用包括頻寬 (使用者和網站都需要付費) 和處理費用 (用戶端和伺服器端)。
考量使用者成本
預測式載入是指根據使用者可能前往的新頁面,做出有根據的預測。不過,如果沒有進行導覽,您可能會浪費資源。因此,您應特別留意對使用者的影響,包括:
- 下載這些未來導覽所需的額外頻寬,特別是在頻寬可能較受限的行動裝置上。
- 使用預先算繪時,需要額外的處理成本來算繪這些網頁。
由於訪客會在下一個階段造訪這些頁面,因此完全準確的預測結果不會產生額外費用,唯一的差異在於這些費用會提前支付。不過,我們無法完全準確預測未來,而且投機策略越激進,浪費資源的風險就越高。
Chrome 已仔細考量這項問題,因此 API 內含多項功能,這表示成本遠低於您預期。特別是重複使用 HTTP 快取,且不載入跨來源 iframe,在同一網站上預先算繪導覽的成本通常會比沒有快取資源的完整網頁小得多,因此推測載入的成本可能比預期的低。
不過,即使有這些防護措施,網站仍應謹慎考量要推測哪些網頁,以及這類推測對使用者造成的成本。適合使用預測載入的內容包括:可合理預測且有高度信心的內容 (可能根據分析或一般使用者歷程),以及成本較低的內容 (例如較不豐富的網頁)。
您也可以考慮哪些 JavaScript 應延遲至啟用。這與延後載入內容 (直到需要時才載入) 類似,可降低預先轉譯的成本,但提供更優質的使用者體驗。由於投機成本較低,您可能會更頻繁地投機,或更積極地投機。
如果無法採用上述做法,建議您採用採用溫和或保守的急迫度規則的較溫和策略。或者,您也可以使用預先載入功能,在信心程度偏低時,其成本遠低於預先顯示,然後在信心程度提高時升級為完整預先顯示,例如當使用者將滑鼠游標懸停在連結上或實際點選連結時。
考量額外的後端負載
除了考量使用者支付的額外費用,網站擁有者也應考量自己的基礎架構成本。如果每個網頁都會導致兩次、三次甚至更多次的網頁載入,使用這個 API 可能會導致後端成本增加。
確保網頁和資源可快取,可大幅減少來源負載量,進而降低整體風險。搭配使用 CDN 時,來源伺服器應會看到最少的額外負載,但請考慮任何 CDN 費用增加情形。
伺服器或 CDN 也可以用來控制 sec-purpose HTTP 標頭所識別的推測結果。舉例來說,Cloudflare 的 Speed Brain 產品只允許在 CDN 邊緣伺服器上快取的推測,不會將要求傳回來源。
不過,由於預測載入通常用於同源網頁載入,使用者在瀏覽器快取中已擁有共用資源 (假設這些資源一開始可快取),因此預測載入通常不會像完整網頁載入那麼耗費資源。
平衡過度或過少的推測
要充分運用投機規則 API,關鍵在於在過度投機 (也就是不必要支付成本且未使用投機) 和過度保守 (投機太少或太晚,無法實現效益) 之間取得平衡。
如果成本較低 (例如在 CDN 邊緣節點快取的靜態產生的小型網頁),您可以更積極地使用推測。
不過,如果是較大且內容豐富的網頁,可能無法在 CDN 邊緣快取,因此應更加小心。同樣地,資源密集的網頁可能會耗用網路頻寬或處理效能,進而對目前的網頁造成負面影響。API 的目標是提升效能,因此效能回歸絕對不是我們想要的!這也是為何我們建議最多只預先載入一或兩個網頁的原因 (請注意,Chrome 會根據急迫程度限制一次最多預先載入兩個或十個網頁)。
導入推測規則的步驟
決定如何實作推測規則後,您需要規劃要推測哪些內容,以及如何推出這些內容。較簡單的網站 (例如靜態個人網誌) 可能可以直接跳至特定網頁的完整預先載入作業,但較複雜的網站則需要考量其他複雜因素。
從預先擷取開始
預先擷取通常是實作大多數網站的相對安全做法,許多大型推出計畫 (例如 Cloudflare 和 WordPress) 都是採用這種做法。
請注意,如果預先載入網址會導致任何狀態變更和伺服器端成本,特別是無法快取的網頁。理想狀態下,狀態變更 (例如預先載入 /logout
頁面) 不應實作為 GET
連結,但很遺憾,這在網路上並不少見。
您可以將這類網址從規則中排除:
<script type="speculationrules">
{
"prefetch": [{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": {"href_matches": "/logout"}}
]
},
"eagerness": "moderate"
}]
}
</script>
預先載入功能可限制在從一個網頁到另一個網頁的常見導覽,或是使用 moderate
或 conservative
eagerness
設定,針對所有同源連結的滑鼠游標或點擊動作進行預先載入。conservative
設定的風險最低,但潛在報酬也最低。如果您從這裡開始,請務必至少進展到 moderate
,但最好能進展到 eager
,這樣才能獲得更多成效 (並視情況進一步升級至 prerender
)。
低風險預先顯示
預先擷取推測內容較容易部署,但 API 的最終效能優勢來自預先顯示。在推測後不久未造訪網頁時,這可能需要額外考量 (我們會在下一節說明),但如果使用 moderate
或 conservative
預先算繪,在推測後不久可能會發生導覽,因此這可能是相對低風險的下一步。
<script type="speculationrules">
{
"prerender": [{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": {"href_matches": "/logout"}}
]
},
"eagerness": "moderate"
}]
}
</script>
預先擷取常見網頁,改善非急切預先載入功能
常見的做法之一,是在載入時使用 eager
設定預先載入較少數經常造訪的下一頁 (可在網址清單中指定,或使用 selector_matches
),然後使用 moderate
設定預先算繪。由於 HTML 預先擷取作業在滑鼠游標懸停在連結上時可能已完成,因此這項功能比起只在滑鼠游標懸停時進行預先算繪,更能提升效能。
<script type="speculationrules">
{
"prefetch": [{
"urls": ["next.html", "next2.html"],
"eagerness": "eager"
}],
"prerender": [{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": {"href_matches": "/logout"}}
]
},
"eagerness": "moderate"
}]
}
</script>
提早預先算繪
雖然 moderate
文件規則可讓您以相對低風險的方式使用 API,並且實作方式也相當簡單,但這通常無法提供足夠的時間進行完整預先顯示。如要實現這個 API 允許的即時導覽功能,您可能需要做得更多,並更積極地預先轉譯網頁。
您可以透過靜態網址清單 (例如先前提到的預先載入示例) 或 selector_matches
來識別少數網址 (最好是 1 或 2 個網頁),並使用文件規則涵蓋其他網址:
<script type="speculationrules">
{
"prerender": [
{
"where": {
"selector_matches": : ".prerender"
},
"eagerness": "eager",
},
{
"where": {
"and": [
{ "href_matches": "/*" },
{ "not": {"href_matches": "/logout"}}
]
},
"eagerness": "moderate"
}
]
}
</script>
這可能需要進行流量分析,才能提高準確預測下一個導覽的機會。瞭解消費者在網站上的典型歷程,也有助於找出適合使用預測載入的資源。
改用更積極的預先算繪功能時,也可能需要考量更多分析、廣告和 JavaScript相關事項,並保持預先算繪的網頁保持最新狀態,甚至取消或重新整理推測狀態變更。
Analytics、廣告和 JavaScript
使用預先算繪功能時,較複雜的網站也必須考量對數據分析的影響。一般而言,您不應在網頁 (或廣告) 遭到推測時記錄瀏覽次數,而應在推測功能啟用時才記錄。
部分數據分析供應商 (例如 Google Analytics) 和廣告供應商 (例如 Google 發布商廣告代碼) 已支援推測規則,因此網頁必須啟用,系統才會記錄觀看次數。不過,您導入的其他供應商或自訂分析工具可能需要額外考量。
您可以為 JavaScript 新增檢查項目,在網頁啟用或顯示前,防止執行特定程式碼位元,甚至在這些檢查中包裝整個 <script>
元素。如果網頁使用代碼管理工具來插入這類指令碼,您可以延遲代碼管理工具指令碼,一次解決所有問題。
同樣地,同意聲明管理工具可延遲第三方指令碼,直到啟用為止。Google 一直與各種同意聲明管理工具平台合作,讓這些平台支援預先顯示功能,我們也樂意協助其他人採用這項做法。PubTech 就是這類公司之一,可讓開發人員選擇在預先算繪期間執行或封鎖 JavaScript。
對於應用程式程式碼,您也可以以類似的方式新增變更,將程式碼的執行作業延後至啟用時才執行,尤其是在頁面不需要 JavaScript 程式碼轉譯時。這是較快速且安全的選項,但這代表所有程式碼都會在啟用時一次執行。這可能會在啟用期間造成大量工作,進而影響 INP,尤其是當網頁看起來已完全載入且可供互動時。
此外,如果任何內容都依賴 JavaScript (例如用戶端算繪的內容),延遲這項作業會降低預先算繪對 LCP 和 CLS 的正面影響。採用更精準的方法,讓更多 JavaScript 在預先算繪階段執行,可提供更優質的使用體驗,但實作方式可能較為複雜。
對於較複雜的網站,一開始採用延遲大量指令碼標記的策略,可能是不錯的做法。不過,為了充分發揮 API 的效益,最終目標應是讓 JavaScript 在預先算繪期間執行盡可能多的程式碼。
有分析或廣告疑慮的網站也許也想先從預先載入開始,因為這類網站不太需要擔心這些問題,同時也能考慮如何支援預先算繪。
更新預先轉譯推測
在導覽前預先算繪頁面,可能會導致預先算繪的頁面過時。舉例來說,電子商務網站的預先算繪頁面可能會包含結帳購物籃,包括完整的購物籃,甚至只是在其他頁面顯示購物籃中的商品數量計數器。如果有更多商品加入購物車,然後導向預先算繪的頁面,使用者會看到舊的結帳狀態,因此會感到困惑。
這並非新問題,當使用者在瀏覽器中開啟多個分頁時,就會遇到相同的問題。不過,由於使用者並未刻意啟動預先算繪,因此在預先算繪的頁面中,這種情況更有可能發生,也更令人意外。
Broadcast Channel API 是一種方法,可讓瀏覽器中的一個網頁向其他網頁廣播更新。這麼做也可以解決多個分頁的問題。預先算繪的網頁可以收聽廣播訊息,但在啟用前無法傳送自己的廣播訊息。
或者,預先算繪的網頁可以使用伺服器 (使用定期 fetch()
或 WebSocket
連線) 取得更新,但更新可能會延遲。
取消或重新整理預先顯示的推測
建議您更新預先算繪的頁面,以便繼續使用預先算繪的頁面,同時避免使用者感到混淆。如果無法這樣做,則可以取消推測。
如果網站想要預先轉譯其他較有可能造訪的網頁,也可以使用這個選項,確保符合 Chrome 的限制。
如要取消推測,您必須從網頁中移除推測規則,或是移除類別或其他比對條件 (如果使用這種方法)。或者,如果系統偵測到推測頁面已過時,則該頁面可以呼叫 window.close()
。不過,如果網頁能夠偵測到這項情況,建議您更新網頁狀態,讓網頁保持最新狀態。
您也可以重新插入這些規則 (或比對條件),讓網頁重新預先呈現 (不過,再次提醒,讓現有網頁保持最新狀態通常是較佳的做法,因為這樣不浪費資源)。移除推測規則後,必須在新的微型工作或更晚的時間重新插入,讓瀏覽器注意到移除作業並取消推測。下方範例說明如何刪除及移除所有推測規則指令碼:
async function refreshSpeculations() {
const speculationScripts = document.querySelectorAll('script[type="speculationrules"]');
for (const speculationScript of speculationScripts) {
// Get the current rules as JSON text
const ruleSet = speculationScript.textContent;
// Remove the existing script to reset prerendering
speculationScript.remove();
// Await for a microtask before re-inserting.
await Promise.resolve();
// Reinsert rule in a new speculation rules script
const newScript = document.createElement('script');
newScript.type = 'speculationrules';
newScript.textContent = ruleSet;
console.log(newScript);
// Append the new script back to the document
document.body.appendChild(newScript);
}
}
移除規則會取消現有的預設值 (或預先擷取),但重新插入規則只會推測即時或急切規則 (包括使用預設即時值的網址清單規則)。不過,系統會移除中度或保守的推測內容,但不會自動重新觸發,除非使用者再次與連結互動。
這個重新整理選項不限於 JavaScript 插入的規則。由於這是標準的 DOM 變更,因此您也可以以相同方式移除或變更 HTML 中的靜態規則。您無法移除 HTTP 預測規則,但可以移除符合條件的條件 (例如 prerender
類別),並透過 JavaScript 重新加入。
Chrome 也正在考慮新增 Clear-Site-Header 支援功能,讓伺服器回應取消預先顯示 (例如在提出更新籃子要求時)。
評估成效影響
實作推測規則後,您應評估成效,而非僅假設推測機制會自動加快速度。如先前所述,如果用戶端或伺服器超載,過度推測實際上可能會導致效能倒退。
實作多個步驟 (預先載入、低風險預先算繪,然後是早期預先算繪) 時,請針對每個步驟進行評估。
如何評估成效
推測規則應可對 LCP 等主要成效指標 (可能也會對 CLS 和 INP 產生影響) 產生正面影響,但在整體網站層級指標中可能不會明顯看出。這是因為網站可能主要由其他導覽類型 (例如到達網頁) 組成,或是因為同源導覽速度已經夠快,即使大幅改善,也可能不會影響 Chrome 使用者體驗報告 (CrUX) 中所列的第 75 百分位指標。
您可以使用 CrUX 中的網頁導覽類型,查看導覽活動中有多少百分比是 navigate_cache
或 prerender
,以及這類導覽活動是否會隨著時間增加。不過,如要進行詳細分析,您可能需要使用「真實使用者監控」功能,將資料區隔為推測導覽,以便瞭解這些導覽比其他導覽快多少。
如何評估用量和浪費
另一個重要考量事項是評估您是否在正確的網頁上進行推測。這麼做可避免浪費資源,並確保您指定的目標網頁是可從這個 API 獲得最佳成效的網頁。
很抱歉,啟動推測的網頁無法直接查看推測嘗試的狀態。此外,由於瀏覽器可能會在特定情況下保留推測,因此無法假設嘗試已觸發。因此必須在網頁上進行評估。您也必須檢查兩個 API,瞭解網頁是否正在推測或已推測:
if (document.prerendering) {
console.log("Page is prerendering");
} else if (performance.getEntriesByType("navigation")[0]?.activationStart > 0) {
console.log("Page has already prerendered");
} else {
console.log("This page load was not using prerendering");
}
這個頁面接著可將推測嘗試記錄到後端伺服器。
分析工具的供應商 (例如 Google Analytics) 會在預先算繪時偵測並忽略分析呼叫,直到網頁啟動為止,甚至會忽略個別的事件呼叫。因此,Google Analytics 使用者必須使用其他伺服器端記錄選項。
您也可以在用戶端執行這項操作,讓每個預先算繪的網頁在共用儲存空間中記錄預先算繪作業,然後由呼叫的網頁讀取這些記錄。localStorage
最適合用於此處,因為它可以在離開網頁時讀取 (請注意,sessionStorage
無法使用,因為它針對預先轉譯的網頁有特殊處理)。不過,請注意 localStorage
並非交易安全,如果有多個網頁預先轉譯,其他網頁可能會在同一時間更新此值。這個示範使用不重複的雜湊和個別項目,可避免發生這類問題。
結論
推測規則可大幅提升網頁成效。本指南提供實作此 API 時的考量事項,協助您避免任何潛在問題,並充分運用 API。
預先規劃導入作業,就能避免重複作業。特別是對於較複雜的網站,應先從預先擷取開始,然後再逐步推出低風險預先處理和提早預先處理。最後,請務必評估改善情形,以及任何使用和浪費情況,確保您能妥善運用 API。