開啟網頁時,瀏覽器會向伺服器要求 HTML 文件、剖析內容,並針對任何參照的資源提交個別要求。身為開發人員,您已瞭解網頁所需的所有資源,以及哪些資源最為重要。您可以運用這些知識,提前要求關鍵資源,加快載入程序。本文將說明如何使用 <link rel="preload">
達成這項目標。
預先載入的運作方式
預先載入最適合用於瀏覽器通常較晚才會發現的資源。
預先載入特定資源,表示您想讓瀏覽器提早擷取該資源,因為您確定該資源對目前網頁很重要。
關鍵要求鏈結代表瀏覽器優先取得的資源順序。Lighthouse 會將這個鏈結的第 3 層資產視為較晚發現的資產。您可以使用預先載入關鍵要求稽核,找出要預先載入的資源。
您可以在 HTML 文件的標頭中加入含有 rel="preload"
的 <link>
標記,藉此預先載入資源:
<link rel="preload" as="script" href="critical.js">
瀏覽器會快取預先載入的資源,以便在需要時立即使用。(不會執行指令碼或套用樣式表單)。
資源提示 (例如 preconnect
和 prefetch
) 會在瀏覽器認為適當的情況下執行。另一方面,preload
是瀏覽器的必要元素。現代瀏覽器已能很好地將資源排序,因此請盡量避免使用 preload
,並只預先載入最重要的資源。
未使用的預先載入內容會在 load
事件發生後約 3 秒,觸發 Chrome 中的控制台警告。
用途
預先載入 CSS 中定義的資源
瀏覽器必須先下載及剖析 CSS 檔案,才能發現以 @font-face
規則定義的字型,或在 CSS 檔案中定義的背景圖片。預先載入這些資源,可確保在 CSS 檔案下載前擷取這些資源。
預先載入 CSS 檔案
如果您採用重要 CSS 方法,CSS 會分成兩部分。轉譯捲動畫面上方內容所需的重要 CSS 會內嵌在文件的 <head>
中,而非必要的 CSS 通常會透過 JavaScript 延遲載入。在載入非必要 CSS 之前等待 JavaScript 執行作業,可能會導致使用者捲動時轉譯延遲,因此建議您使用 <link rel="preload">
提早啟動下載作業。
預先載入 JavaScript 檔案
由於瀏覽器不會執行預先載入的檔案,因此預先載入功能可將擷取與執行分開,進而改善互動時間等指標。分割 JavaScript 套件,並只預先載入重要的片段,就能發揮預先載入的最佳效益。
如何導入 rel=preload
實作 preload
最簡單的方法,就是在文件的 <head>
中加入 <link>
標記:
<head>
<link rel="preload" as="script" href="critical.js">
</head>
提供 as
屬性有助於瀏覽器根據資源類型設定預先擷取資源的優先順序、設定正確的標頭,以及判斷資源是否已存在快取中。這個屬性可接受的值包括:script
、style
、font
、image
和「其他」。
某些類型的資源 (例如字型) 會以匿名模式載入。對於這些屬性,您必須使用 preload
設定 crossorigin
屬性:
<link rel="preload" href="ComicSans.woff2" as="font" type="font/woff2" crossorigin>
<link>
元素也接受 type
屬性,其中包含連結資源的 MIME 類型。瀏覽器會使用 type
屬性的值,確保只有在支援的檔案類型時,才會預先載入資源。如果瀏覽器不支援指定的資源類型,就會忽略 <link rel="preload">
。
您也可以透過 Link
HTTP 標頭預先載入任何類型的資源:
Link: </css/style.css>; rel="preload"; as="style"
在 HTTP 標頭中指定 preload
的好處是,瀏覽器不必剖析文件即可發現它,在某些情況下可帶來小幅改善。
使用 webpack 預先載入 JavaScript 模組
如果您使用模組套件封裝器來建立應用程式的建構檔案,請確認該套件是否支援預先載入標記的插入作業。在 webpack 4.6.0 以上版本中,您可以透過在 import()
中使用魔法註解來支援預先載入功能:
import(_/* webpackPreload: true */_ "CriticalChunk")
如果您使用的是舊版 webpack,請使用第三方外掛程式,例如 preload-webpack-plugin。
預先載入對 Core Web Vitals 的影響
預先載入是一項強大的效能最佳化功能,可影響載入速度。這類最佳化作業可能會導致網站的 Core Web Vitals 發生變化,因此請務必留意。
最大內容繪製 (LCP)
在字型和圖片方面,預先載入功能對最大內容繪製 (LCP) 有顯著的影響,因為圖片和文字節點都可能是LCP 候選項。使用網路字型算繪的首要圖片和大量文字,如果能搭配適當的預先載入提示,就能獲得顯著的效益。因此,如果有機會能更快地將這些重要內容傳遞給使用者,就應使用預先載入提示。
不過,請務必謹慎使用預先載入和其他最佳化功能!特別是避免預先載入過多資源。如果優先順序中有太多資源,實際上就沒有任何資源是優先的。在網路速度較慢的情況下,頻寬競爭會更加明顯,因此過多的預先載入提示會對使用者造成特別不利的影響。
相反地,請專注於幾項您知道可從適當預先載入作業中受益的高價值資源。預先載入字型時,請務必以 WOFF 2.0 格式提供字型,盡可能縮短資源載入時間。由於 WOFF 2.0 提供出色的瀏覽器支援,如果 LCP 候選項目是文字節點,使用 WOFF 1.0 或 TrueType (TTF) 等舊版格式會延遲 LCP。
在 LCP 和 JavaScript 方面,請務必確保從伺服器傳送完整的標記,以便瀏覽器的預先載入掃描器正常運作。如果您提供的體驗完全仰賴 JavaScript 轉譯標記,且無法傳送由伺服器轉譯的 HTML,那麼在瀏覽器預先載入掃描器無法處理的情況下,預先載入資源就會很有幫助,否則只有在 JavaScript 完成載入及執行時,才能發現這些資源。
累計版面配置位移 (CLS)
累積排版變動 (CLS) 是網站字型的重要指標,而 CLS 與使用 font-display
CSS 屬性來管理字型載入方式的網站字型有密切關聯。如要盡量減少與網路字型相關的版面配置位移,請考慮採用下列策略:
- 使用
font-display
的預設block
值時,預先載入字型。這需要取得平衡。在沒有備用字型的情況下,禁止顯示字型可能會造成使用者體驗問題。一方面,使用font-display: block;
載入字型可消除與網路字型相關的版面配置偏移。另一方面,如果這些網路字型對使用者體驗至關重要,您還是應該盡快載入這些字型。將預先載入與font-display: block;
結合,或許是可接受的折衷做法。 - 使用
fallback
的font-display
值時,預先載入字型。fallback
是swap
和block
之間的折衷,因為它具有極短的封鎖期間。 - 如果不使用預先載入,請為
font-display
使用optional
值。如果網頁字型對使用者體驗不太重要,但仍用於顯示大量網頁文字,建議您考慮使用optional
值。在惡劣條件下,optional
會在背景載入下次導覽所需的字型,同時以備用字型顯示頁面文字。在這些情況下,最終結果是 CLS 改善,因為系統字型會立即算繪,而後續網頁載入作業也會立即載入字型,不會造成版面配置位移。
在網頁字型方面,CLS 是難以最佳化的指標。如往常,請在實驗室中進行實驗,但請信賴實地資料,判斷字型載入策略是否有助於改善 CLS,還是會使其惡化。
Interaction to Next Paint (INP)
Interaction to Next Paint 是評估回應使用者輸入內容的指標。由於網路上互動功能的大部分是由 JavaScript 驅動,因此預先載入支援重要互動功能的 JavaScript,有助於降低網頁的 INP。不過,請注意,如果在啟動期間預先載入過多 JavaScript,資源爭奪頻寬的情況可能會導致非預期的負面後果。
您也應謹慎處理程式碼分割作業。程式碼分割是減少啟動期間載入 JavaScript 數量的絕佳最佳化方式,但如果互動需要在互動開始時載入 JavaScript,互動可能會延遲。為彌補這項缺點,您必須檢查使用者的意圖,並在互動發生前,為必要的 JavaScript 區塊注入預先載入內容。舉例來說,當表單中的任何欄位獲得焦點時,您可以預先載入驗證表單內容所需的 JavaScript。
結論
為改善網頁速度,請預先載入瀏覽器較晚才會發現的重要資源。預先載入所有內容會適得其反,因此請謹慎使用 preload
,並評估實際影響。