預載入

**預載入**指的是在實際訪問相關頁面之前執行導航操作(例如 DNS 獲取、獲取資源或渲染文件)的做法,這些操作基於對使用者最有可能訪問的下一個頁面的預測。

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

此頁面回顧了可用的預載入技術以及何時可以以及應該使用它們來提高效能。

預載入機制

預載入有幾種機制

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

**注意:**以上描述是高階和通用的。瀏覽器為實現預取和預渲染而執行的操作的確切內容取決於使用的功能。更精確的功能描述在下面的預載入功能部分提供。

預載入是如何實現的?

預載入主要透過兩種方式實現。

首先,一些瀏覽器會根據各種啟發式演算法自動預渲染頁面,以提供自動效能改進。執行方式的確切內容取決於瀏覽器實現。例如,Chrome 在位址列中鍵入匹配字串時會自動預渲染頁面——如果它非常確定您將訪問該頁面(請參閱檢視 Chrome 的位址列預測以瞭解更多詳細資訊)。此外,當在位址列中鍵入搜尋詞時,它可能會自動預渲染搜尋結果頁面,前提是搜尋引擎已指示這樣做。它使用與Speculation Rules 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 模組是高優先順序的,因此它可以儘早開始下載這些模組。

例如

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

它是JavaScript 模組<link rel="preload">的專門版本,並且工作方式基本相同。但是,也有一些區別

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

<link rel="prefetch"> 向瀏覽器提供提示,表明使用者可能需要目標資源用於未來的導航,因此瀏覽器可以透過搶先獲取和快取資源來提高使用者體驗。<link rel="prefetch"> 用於同站點導航資源,或同站點頁面使用的子資源。

例如

js
<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操作的獲取請求會產生一個 HTTP 請求,其中包含 HTTP 標頭Sec-Purpose: prefetch。伺服器可能會使用此標頭更改資源的快取超時,或執行其他特殊處理。該請求還將包含值為emptySec-Fetch-Dest標頭。請求中的Accept標頭將與正常導航請求中使用的值匹配。這允許瀏覽器在導航後找到匹配的快取資源。如果返回響應,則將其與請求一起快取在 HTTP 快取中。

**注意:**這項技術曾經僅在 Chrome 中可用,現在已棄用。您應該改用Speculation Rules API,它取代了此技術。

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

例如

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

它會獲取引用的文件,然後獲取所有可靜態查詢的連結資源並將其也獲取,並將結果儲存在磁碟上的 HTTP 快取中,並設定 5 分鐘的超時時間。例外情況是透過 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 預渲染 準備下一次導航 用於預載入同源的未來導航資源,以實現近乎即時的導航。在支援的情況下,將其用於高優先順序頁面;請確保這些頁面 安全可預渲染

另請參閱