開啟網頁時,瀏覽器會向伺服器要求 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
的好處是,瀏覽器不必剖析文件即可發現 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
,並評估實際影響。