推測性載入

推測性載入是指在實際訪問相關頁面之前執行導航操作(例如 DNS 獲取、獲取資源或渲染文件)的做法,其依據是對使用者最可能接下來訪問哪些頁面的預測。

這些預測可以由開發者提供(例如,網站上最受歡迎的目的地列表),也可以由瀏覽器啟發式地確定(例如,基於使用者歷史記錄中熱門網站)。如果使用成功,此類技術可以顯著提高效能,使頁面更快或在某些情況下即時可用。

本頁面回顧了可用的推測性載入技術,以及何時以及如何使用它們來提高效能。

推測性載入機制

推測性載入有幾種機制

  • 預取(Prefetching)涉及在需要文件(或文件的一部分)之前,預先獲取呈現文件所需的部分或全部資源,以便在需要呈現時,可以更快地完成呈現。
  • 預渲染(Prerendering)更進一步,實際渲染內容,使其在需要時即可顯示。根據實現方式的不同,這可能導致從舊頁面到新頁面的即時導航。
  • 預連線(Preconnecting)透過預先執行部分或全部連線握手(即 DNS + TCP + TLS),來加快從給定源的未來載入速度。

注意:以上描述是高層次和概括性的。瀏覽器為實現預取和預渲染所做的具體操作取決於所使用的功能。更精確的功能描述在下面的推測性載入功能部分提供。

如何實現推測性載入?

推測性載入主要透過兩種方式實現。

首先,一些瀏覽器會根據各種啟發式方法自動預渲染頁面,以提供自動的效能改進。具體如何實現取決於瀏覽器的實現。例如,Chrome 瀏覽器在位址列中輸入匹配字串時會自動預渲染頁面——如果它高度確信您會訪問該頁面(更多詳細資訊請參閱檢視 Chrome 的位址列預測)。此外,當在位址列中輸入搜尋詞時,如果搜尋引擎指示,它也可能自動預渲染搜尋結果頁面。它使用與推測規則 API 相同的機制來完成此操作。

其次,有幾種不同的平臺功能可供開發人員使用,以提供關於他們希望瀏覽器執行何種推測性載入的指令。這些將在下一節中進行回顧。

推測性載入特性

<link rel="preconnect"> 向瀏覽器提供了一個提示,即使用者可能需要來自指定資源源的資源,因此瀏覽器可以透過預先啟動與該源的連線來提高效能。支援的瀏覽器將預先執行部分或全部連線握手(即 DNS + TCP + TLS)。

例如

html
<link rel="preconnect" href="https://example.com" />

<link rel="preconnect"> 在瀏覽器中廣泛支援,並將為任何未來的跨域 HTTP 請求、導航或子資源帶來好處。它對同源請求沒有好處,因為連線已經開啟。

如果一個頁面需要連線到許多第三方域,預連線所有這些域可能會適得其反。<link rel="preconnect"> 提示最好只用於最關鍵的連線。對於其他連線,只需使用 <link rel="dns-prefetch"> 來節省第一步的時間——DNS 查詢。

您也可以將預連線作為 HTTP Link 標頭來實現,例如

http
Link: <https://example.com>; rel="preconnect"

<link rel="dns-prefetch"> 向瀏覽器提供了一個提示,即使用者可能需要來自指定資源源的資源,因此瀏覽器可能可以透過預先執行該源的 DNS 解析來提高效能。它與 <link rel="preconnect"> 相同,只是它只處理 DNS 部分。

同樣,瀏覽器支援廣泛,並且它對同源請求沒有好處,因為連線已經開啟。

例如

html
<link rel="dns-prefetch" href="https://example.com" />

注意:有關更多詳細資訊,請參閱使用 dns-prefetch

<link rel="preload"> 向瀏覽器提供提示,說明當前頁面上哪些資源具有高優先順序,以便在頁面<head>中看到<link>元素時可以儘早開始下載它們。

例如

html
<link rel="preload" href="main.js" as="script" />
<!-- CORS-enabled preload -->
<link
  rel="preload"
  href="https://www.example.com/fonts/cicle_fina-webfont.woff2"
  as="font"
  type="font/woff2"
  crossorigin />

結果儲存在每個文件的記憶體快取中。如果您預載入了當前頁面不作為子資源使用的內容,通常是浪費資源,儘管如果標頭允許,結果可能會填充 HTTP 快取。

您也可以將預載入作為 HTTP Link 標頭來實現,例如

http
Link: <https://www.example.com/fonts/cicle_fina-webfont.woff2>; rel="preload"

現代瀏覽器對 <link rel="preload">/<link rel="modulepreload"> 的支援廣泛。

<link rel="modulepreload"> 向瀏覽器提供提示,說明當前頁面上哪些 JavaScript 模組具有高優先順序,以便它可以儘早開始下載它們。

例如

html
<link rel="modulepreload" href="main.js" />

它是 <link rel="preload"> 的一個專用版本,用於JavaScript 模組,工作方式基本相同。但是,有一些區別:

  • 瀏覽器知道資源是一個 JavaScript 模組,因為不需要 as 屬性,並且它可以使用正確的憑據模式來避免重複獲取。
  • 瀏覽器不僅下載它並將其儲存在快取中,還會下載它,然後解析並直接編譯到記憶體模組對映中。
  • 瀏覽器還可以自動為模組依賴項執行相同的操作。

<link rel="prefetch"> 向瀏覽器提供了一個提示,即使用者可能在未來的導航中需要目標資源,因此瀏覽器可以透過預先獲取和快取該資源來改善使用者體驗。<link rel="prefetch"> 用於同站導航資源,或用於同站頁面使用的子資源。

例如

html
<link rel="prefetch" href="main.js" />

預取可用於為可能的下一次導航獲取 HTML 和子資源。一個常見的用例是擁有一個簡單的網站著陸頁,該頁面獲取網站其餘部分使用的更“重型”資源。

html
<link rel="prefetch" href="/app/style.css" />
<link rel="prefetch" href="/landing-page" />

結果保留在磁碟上的 HTTP 快取中。因此,它對於預取子資源很有用,即使它們不被當前頁面使用。您也可以使用它來預取使用者可能訪問的下一個網站文件。但是,因此您需要小心標頭——例如,某些Cache-Control標頭可能會阻止預取(例如no-cacheno-store)。

許多瀏覽器現在都實現了某種形式的快取分割槽,這使得 <link rel="prefetch"> 對旨在供不同頂級網站使用的資源無用。這包括跨站點導航時的主文件。因此,例如,以下預取

html
<link rel="prefetch" href="https://news.example/article" />

將無法從 https://aggregator.example/ 訪問。

注意: <link rel="prefetch"> 在功能上等同於帶有 priority: "low" 選項的 fetch() 呼叫,只不過前者通常具有更低的優先順序,並且它會在請求中設定 Sec-Purpose: prefetch 標頭。

注意: prefetch 操作的 fetch 請求會生成一個包含 HTTP 標頭 Sec-Purpose: prefetch 的 HTTP 請求。伺服器可以使用此標頭更改資源的快取超時,或執行其他特殊處理。請求還將包含 Sec-Fetch-Dest 標頭,其值設定為 empty。請求中的 Accept 標頭將與用於正常導航請求的值匹配。這允許瀏覽器在導航後找到匹配的快取資源。如果返回響應,它將與請求一起快取到 HTTP 快取中。

注意:此技術僅在 Chrome 中可用,現已廢棄,並且不再執行其名稱所暗示的預渲染。您應該改用推測規則 API,它取代了此功能。

<link rel="prerender"> 向瀏覽器提供了一個提示,即使用者可能在下一次導航中需要目標資源,因此瀏覽器可能可以透過預渲染該資源來提高效能。prerender 用於未來的導航,僅限同站,因此對於多頁面應用程式 (MPA) 有意義,而不是單頁面應用程式 (SPA)。

例如

html
<link rel="prerender" href="/next-page" />

它將獲取引用的文件,然後獲取任何靜態可查詢的連結資源並也獲取它們,將結果儲存在磁碟上的 HTTP 快取中,超時時間為五分鐘。例外情況是透過 JavaScript 載入的子資源——它不會找到這些。它還有其他問題——像 <link rel="prefetch"> 一樣,它也可能被 Cache-Control 標頭阻止,並且由於瀏覽器快取分割槽而對旨在供不同頂級站點使用的資源無用。

推測規則 API

推測規則 API 用於指定一組規則,這些規則決定瀏覽器應預取或預渲染哪些未來的文件。這些規則以 JSON 結構的形式提供,位於內聯 <script type="speculationrules"> 元素中,以及由 Speculation-Rules 響應頭引用的外部文字檔案中。

何時使用每個特性?

下表總結了上面詳細介紹的功能,並提供了何時使用每個功能的指南。

推測性載入特性 用途 使用時機
<link rel="preconnect"> 跨域連線預熱 在最關鍵的跨域連線上使用,以便在連線時提供效能改進。
<link rel="dns-prefetch"> 跨域連線預熱 在所有跨域連線上使用,以便在連線時提供小的效能改進。
<link rel="preload"> 當前頁面子資源的高優先順序載入 用於在當前頁面上更快地載入高優先順序資源,以實現戰略性效能改進。不要預載入所有內容,否則您將看不到好處。還有一些其他有趣的用途——請參閱 Smashing Magazine 上的預載入:它有什麼用?(2016 年)
<link rel="modulepreload"> 當前頁面 JavaScript 模組的高優先順序載入 用於預載入高優先順序 JavaScript 模組,以實現戰略性效能改進。
<link rel="prefetch"> 預填充 HTTP 快取 用於預取同站未來導航資源或這些頁面上使用的子資源。使用 HTTP 快取,因此在文件預取方面存在許多問題,例如可能被 Cache-Control 標頭阻止。在支援的情況下,請改用 推測規則 API 進行文件預取。
<link rel="prerender"> 為下一次導航做準備 已廢棄;建議您不要使用此功能。在支援的情況下,請改用推測規則 API 預渲染。
推測規則 API 預取 為下一次導航做準備 用於預取相同或跨站的未來導航文件。建議在支援時廣泛採用;檢查以確保頁面可以安全預取。它不處理子資源預取;為此您需要使用 <link rel="prefetch">
推測規則 API 預渲染 為下一次導航做準備 用於預載入同源的未來導航資源,以實現近乎即時的導航。在支援的情況下,用於高優先順序頁面;檢查以確保頁面可以安全預渲染

另見