開啟網頁時,瀏覽器會向伺服器要求 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
,並評估實際影響。