使用 Fetch Priority API 最佳化資源載入功能

Fetch Priority API 可指出資源對瀏覽器的相對優先順序。這項功能可啟用最佳載入功能,並改善網站體驗核心指標。

阿迪奧斯馬尼
Addy Osmani
索荷尼 (Lena Sohoni)
Lena Sohoni
派翠克米南
Patrick Meenan

瀏覽器支援

  • 102
  • 102
  • x
  • 17.2

資料來源

當瀏覽器剖析網頁,並開始搜尋並下載資源 (例如圖片、指令碼或 CSS) 時,就會指派擷取 priority,嘗試以最佳順序下載資源。這些優先順序會因資源種類及在文件中的位置而有所不同。舉例來說,可視區域圖片的優先順序可能是 High,但如果是提早載入,則透過 <head> 中的 <link> 禁止轉譯的 CSS 可能是 Very High。瀏覽器相當擅長指派優先順序,但不一定在所有情況下都是最佳設定。

本文將介紹 Fetch Priority API 和 fetchpriority HTML 屬性,可讓您瞭解資源的相對優先順序 (highlow)。擷取優先順序可協助您最佳化 Core Web Vitals。

摘要

「擷取優先順序」功能可在以下幾個重要層面派上用場:

  • 指定圖片元素上的 fetchpriority="high",可提高 LCP 圖片的優先順序,讓 LCP 更快啟動。
  • 使用比目前常用的駭客入侵方式更明確的語意,提高 async 指令碼的優先順序 (為 async 指令碼插入 <link rel="preload">)。
  • 降低延遲內文指令碼的優先順序,以改善圖片序列。
比較 Google 航班/機票首頁的兩項測試的幻燈片視圖。使用底部的擷取優先順序提高主頁橫幅的優先順序,使 LCP 減少 0.7 秒。
測試 Google 航班/機票測試時,擷取「改善最大內容繪製」的優先等級 (2.6 到 1.9)

以往,開發人員在使用預先載入預先連線的情況下,在資源優先順序方面仍有部分影響,但影響程度有限。擷取優先順序可彌補這些資源提示的不足,但請務必瞭解這些項目所適用的位置。預先載入功能可讓您將重要資源告知瀏覽器,以便在自然搜尋之前先行載入。對於不容易發現的資源 (例如樣式表中的字型、背景圖片或指令碼載入的資源),這項功能特別有用。Preconnect 有助於暖機與跨來源伺服器的連線,有助於改善「Time-to-first-byte」等指標。當您知道來源,但不一定需要確切的資源網址時,這個選項相當實用。

「擷取優先順序」是一種標記式信號 (可透過 fetchpriority 屬性取得),開發人員可用來標明特定資源的相對優先順序。您也可以透過 JavaScript 和 Fetch API 搭配 priority 屬性使用這些提示,藉此影響資料擷取資源的優先順序。「擷取優先順序」也可以補強預先載入的。拍攝最大內容繪製圖片後,即使預先載入這種圖片,其優先順序仍會低。如果其他初期低優先順序資源被推送回正,使用「擷取優先順序」將有助於加快圖片載入的速度。

「擷取優先順序」功能適用於 Chrome 101 以上版本

資源優先順序

資源下載序列取決於瀏覽器針對網頁各項資源指定的優先順序。優先順序計算邏輯會受到不同的因素影響。比如

  • CSS、字型、指令碼、圖片和第三方資源會指派不同的優先順序。
  • 在文件中參照資源的位置或順序也會影響資源的優先順序。
  • preload 資源提示可協助瀏覽器更快發現資源,並在文件載入前載入資源並影響優先順序。
  • asyncdefer 指令碼的優先順序計算變更。

下表考量這類因素,說明 Chrome 目前對大多數資源的優先順序和順序。

  載入版面配置封鎖階段 在版面配置封鎖階段中一次載入一次性載入
Blink
優先順序
VeryHigh 媒介 VeryLow
開發人員工具
優先順序
最高 媒介 最低
主要資源
CSS (提早**) CSS (延遲**) CSS (媒體不相符***)
指令碼 (提前** 或不從預先載入掃描器取得) 指令碼 (後期**) 指令碼 (非同步)
Font 字型 (rel=preload)
匯入
圖片 (在可視區域中) 圖片 (前 5 張圖片 > 10,000px2) 映像檔
媒體
SVG 文件
預先擷取
XSL
XHR (同步) XHR/擷取* (非同步)

瀏覽器會按照搜尋到的順序下載優先順序相同的資源。在 Chrome 開發人員工具的「網路」分頁中載入網頁時,您可以查看指派給不同資源的優先順序。(務必在表格標題上按一下滑鼠右鍵,以加入「Priority」欄)。

Chrome 開發人員工具網路分頁列出的資產螢幕截圖。從左到右讀取的資料欄:名稱、狀態、類型、啟動者、大小、時間和優先順序。
BBC 新聞詳細資料頁面上資源 type = "font" 的優先順序
Chrome 開發人員工具網路分頁列出的資產螢幕截圖。從左到右讀取的資料欄:名稱、狀態、類型、啟動者、大小、時間和優先順序。
BBC 新聞詳細資料頁面上資源類型 =「script」的優先順序

在優先順序改變的情況下,您可以使用「Big request rows」設定,同時查看初始和最終優先順序。無論「大量要求資料列」設定為何,工具提示中也會顯示相同的文字。

Chrome 開發人員工具網路分頁列出的資產螢幕截圖。「大型要求列」設定已勾選,「優先順序」欄顯示第一張圖片為「高」,但下方初始優先順序不同的中。工具提示也會顯示相同的文字。
在開發人員工具中查看初始和最終優先順序

您何時需要使用擷取優先順序?

只要瞭解瀏覽器的優先順序邏輯,您就能使用一些現有的旋鈕來調整下載順序。你可以

  1. 根據要下載的順序,放置 <script><link> 等資源標記。優先順序相同的資源通常會依照發現的順序載入。
  2. 使用 preload 資源提示提前下載必要資源,特別是瀏覽器較不早發現的資源。
  3. 使用 asyncdefer 下載指令碼,而不會封鎖其他資源。
  4. 延遲載入需捲動位置的內容,讓瀏覽器能夠使用可用頻寬來處理更重要的前幾行資源。

這些技術有助於控管瀏覽器的優先順序運算作業,藉此提升效能並強化網站體驗核心指標。舉例來說,當系統已預先載入重要背景圖片時,可以更早發現這張圖片,進而改善最大內容繪製 (LCP)。

有時候,這些帳號代碼可能不足以為您的應用程式排定最佳資源優先順序。以下列舉幾個適合使用擷取優先順序的情境:

  1. 您有幾張不需捲動位置圖片,但這些圖片的優先順序不需要相同。例如,在圖片輪轉介面中,只有第一張圖片需要更高的優先順序。
  2. 可視區域中的主頁橫幅通常從「低」的優先順序開始 (請注意,Chrome 117 的變更會將前五張大型圖片設為「中」,但這不一定包含您的主頁橫幅)。版面配置完成後,Chrome 就會將版面配置移至可視區域,提高優先順序。這通常會增加圖片載入的時間。如果您在標記中提供擷取優先順序,就能讓圖片從「高」優先順序開始,並稍早開始載入。

    請注意,如要提早發現內含 CSS 背景的 LCP 圖片,還是需要預先載入圖片。此外,只要在預先載入項目中加入 fetchpriority='high',即可與擷取優先順序合併,否則圖片仍會以「低」或「中」的優先順序開始。
  3. 宣告指令碼為 asyncdefer 會指示瀏覽器以非同步方式載入指令碼。不過,如上表所示,這些指令碼的優先順序也會設為「低」。建議您提高審查優先順序,同時確保非同步下載作業,特別是任何對使用者體驗至關重要的指令碼。
  4. 您可以使用 JavaScript fetch() API 以非同步方式擷取資源或資料。瀏覽器指派擷取的優先順序為「高」。在某些情況下,您可能不想讓所有擷取作業以「高」優先順序執行,而偏好使用其他擷取優先順序。當您要執行背景 API 呼叫,並混合使用會回應使用者輸入內容的 API 呼叫 (例如自動完成) 時,這項功能就能派上用場。背景 API 呼叫可標記為「低」優先順序,並將互動式 API 呼叫標示為「高」優先順序。
  5. 瀏覽器將 CSS 和字型指定為「高」優先順序,但這類資源不一定相同,或對於 LCP 不需要必要設定。你可以使用「擷取優先順序」來降低部分資源的優先順序。

fetchpriority 屬性

您可以使用 fetchpriority HTML 屬性提供擷取優先順序。這項屬性可以與 linkimgscript 標記搭配使用。這個屬性可讓您指定在下載時使用支援的標記,例如 CSS、字型、指令碼和圖片等資源類型的優先順序。fetchpriority 屬性接受以下三個值的其中之一:

  • high:您將資源視為高優先順序,且只要瀏覽器的經驗法則不會阻礙該資源,就應該優先採用該資源。
  • low:你認為資源的優先順序較低,並希望瀏覽器在經驗法則許可的情況下降低資源的優先順序。
  • auto:這是您沒有偏好設定的預設值,讓瀏覽器決定適當的優先順序。

以下舉例說明如何在標記和指令碼類似的 priority 屬性中使用 fetchpriority 屬性。

<!-- We don't want a high priority for this above-the-fold image -->
<img src="/images/in_viewport_but_not_important.svg" fetchpriority="low" alt="I'm an unimportant image!">

<!-- We want to initiate an early fetch for a resource, but also deprioritize it -->
<link rel="preload" href="/js/script.js" as="script" fetchpriority="low">

<script>
  fetch('https://example.com/', {priority: 'low'})
  .then(data => {
    // Trigger a low priority fetch
  });
</script>

瀏覽器優先順序和fetchpriority

您可以將 fetchpriority 屬性套用至不同的資源,如下圖所示,藉此增加或降低運算後的優先順序。每列的 fetchpriority="auto" (📅?) 代表該資源類型的預設優先順序 (Google 文件也會提供)。

  載入版面配置封鎖階段 在版面配置封鎖階段中一次載入一次性載入
Blink
優先順序
VeryHigh 媒介 VeryLow
開發人員工具
優先順序
最高 媒介 最低
主要資源
CSS (提早**) ⬆◉
CSS (延遲**)
CSS (媒體不相符***) ⬆*** ◉⬇
指令碼 (提前** 或不從預先載入掃描器取得) ⬆◉
指令碼 (後期**)
指令碼 (非同步/延遲) ◉⬇
Font
字型 (rel=preload) ⬆◉
匯入
圖片 (在可視區域中 - 在版面配置之後) ⬆◉
圖片 (前 5 張圖片 > 10,000px2)
映像檔 ◉⬇
媒體 (影片/音訊) ◉⬇
SVG 文件 ◉⬇
XHR (同步) - 已淘汰
XHR/擷取* (非同步) ⬆◉
預先擷取
XSL

請注意,fetchpriority 會設定「相對優先順序」,也就是以適當的金額調整預設優先順序,而不是明確將優先順序設為「高」或「低」,由瀏覽器決定相對優先順序。通常會是「高」或「低」,但有時不一定。舉例來說,fetchpriority="high" 的重要 CSS 仍會保留「非常高」/「最高」優先順序,而在這些這類上使用 fetchpriority="low" 仍會保留「高」優先順序,但在未明確設為「高」或「低」的情況下,前者仍會保留「高」優先順序。

應用情境

您可以使用 fetchpriority 屬性來處理您希望瀏覽器在擷取資源時,額外提示哪個優先順序。

提高 LCP 圖片的優先順序

您可以指定 fetchpriority="high" 以提高 LCP 或其他重要圖片的優先順序。

<img src="lcp-image.jpg" fetchpriority="high">

以下比較圖顯示了 Google 航班/機票頁面的 LCP 背景圖片,已載入和未擷取「優先檔案」類別。將優先順序設為高時,LCP 從 2.6 改善為 1.9 秒

這項實驗是透過 Cloudflare 工作站,將 Google 航班/機票頁面改寫為使用「擷取優先順序」功能。

降低不需捲動位置圖片的優先順序

您可以使用 fetchpriority="low",降低一開始可能不重要 (例如圖片輪轉介面) 不需捲動位置的圖片優先順序。

<ul class="carousel">
  <img src="img/carousel-1.jpg" fetchpriority="high">
  <img src="img/carousel-2.jpg" fetchpriority="low">
  <img src="img/carousel-3.jpg" fetchpriority="low">
  <img src="img/carousel-4.jpg" fetchpriority="low">
</ul>

我們在先前的 Oodle 應用程式實驗中,運用此方法降低載入時未顯示的圖片優先順序。結果證明瞭縮短 2 秒的載入時間。

在 Oodle 應用程式的圖片輪轉介面上使用擷取優先順序的並排比較。瀏覽器左側會設定輪轉介面圖片的預設優先順序,但下載和繪製這些圖片的時間比右手邊範例慢兩秒,因此只為第一張輪轉介面圖片設定較高的優先順序。

降低預先載入資源的優先順序

如要防止預先載入的資源與其他關鍵資源競爭,您可以提供降低這些項目的優先順序提示。這項技巧適用於圖片、指令碼和 CSS。

<!-- Lower priority only for non-critical preloaded scripts -->
<link rel="preload" as="script" href="critical-script.js">
<link rel="preload" href="/js/script.js" as="script" fetchpriority="low">

<!-- Preload CSS without blocking other resources -->
<link rel="preload" as="style" href="theme.css" fetchpriority="low" onload="this.rel='stylesheet'">

變更指令碼優先順序

需要利用指令碼來為網頁的某些部分添加互動功能非常重要,但不應封鎖其他資源。您可以將其標示為高優先順序的非同步。

<script src="async_but_important.js" async fetchpriority="high"></script>

如果指令碼依賴特定 DOM 狀態,就無法標示為非同步。不過,如果網頁排名較低,下載作業的優先順序可能會較低 (如圖所示)。

<script src="blocking_but_unimportant.js" fetchpriority="low"></script>

降低非關鍵資料擷取的優先順序

瀏覽器執行以高優先順序執行的 fetch。如果有多個擷取作業可能會同時觸發,您可針對較重要的資料擷取使用高預設優先順序,針對較不重要的資料則降低優先順序。

// Important validation data (high by default)
let authenticate = await fetch('/user');

// Less important content data (suggested low)
let suggestedContent = await fetch('/content/suggested', {priority: 'low'});

擷取優先順序實作注意事項

如上所述,擷取優先順序可改善特定用途的效能。請留意以下事項:

  • fetchpriority 屬性為提示,而非指令。瀏覽器會試著遵循開發人員的偏好設定。此外,瀏覽器也可能會在發生衝突時,視需要套用資源的偏好設定。
  • 「擷取優先順序」不應與預先載入混淆。兩者都不同,原因如下:

    • 預先載入是必要的擷取,而不是提示。
    • 預先載入可讓瀏覽器提早找到資源,但仍會以預設的優先順序擷取資源。反之,「擷取優先順序」並無法幫助使用者發現,但可讓您提高或降低擷取優先順序。
    • 較容易觀察及測量預先載入的效果。

    「擷取優先順序」可提升優先排序的精細程度,補強預先載入的問題。如果您已將 LCP 圖片指定為 <head> 中第一個項目之一的預先載入項目,則 high 擷取優先順序可能無法大幅提高。但是,如果預先載入在其他資源之後,則 high 擷取優先順序可以改善 LCP。如果重要圖片是 CSS 背景圖片,請使用 fetchpriority = "high" 預先載入該圖片。

  • 在更多資源爭用可用網路頻寬的環境下,優先排序所引起的可觀優勢將更相關。當 HTTP/1.x 連線無法使用平行下載,或低頻寬 HTTP/2 連線時,這是很常見的情況。在這種情況下,優先順序可以解決這類瓶頸。

  • CDN 無法統一導入 HTTP/2 優先順序。即使瀏覽器以「擷取優先順序」進行通訊,也未必會按要求的順序為資源排定優先順序。這使得測試擷取優先順序變得困難。優先順序會同時套用到瀏覽器內部,以及支援優先順序的通訊協定 (HTTP/2 和 HTTP/3)。即使只是獨立於 CDN 或來源支援之外的內部瀏覽器優先順序,仍然值得使用,因為在瀏覽器要求資源時通常會變更。例如,在瀏覽器處理重要 <head> 項目時,低優先順序資源 (例如圖片) 通常不會遭到要求。

  • 在您初次設計時,可能無法採用「擷取優先順序」做為最佳做法。這類最佳化作業可在開發週期的後期套用。您可以查看網頁中指派給不同資源的優先程度。如果優先順序與預期不符,不妨導入「擷取優先順序」,進一步提升最佳化成效。

在 Chrome 95 以上版本中使用預先載入功能

在 Chrome 第 73 至第 76 版中,「擷取優先順序」功能可供試用,但由於 Chrome 95 中已修正優先順序的問題,因此這項功能尚未發布。在 Chrome 95 以下版本中,透過 <link rel=preload> 發出的要求一律會先在預先載入掃描器偵測到的其他要求之前開始,即使其他要求的優先順序較高亦然。

隨著 Chrome 95 版修正程式和「擷取優先順序」的強化功能,我們希望開發人員能開始根據特定用途使用預先載入功能,預先載入剖析器未偵測到的資源 (字型、匯入項目、背景 LCP 圖片)。preload 提示的位置會影響預先載入資源的時間。使用預先載入的要點如下:

  • 在 HTTP 標頭中加入預先載入,會優先於其他網頁。
  • 一般來說,預先載入的內容會按照「中」優先順序超過「中」的優先順序,因此在 HTML 開頭時,請特別留意。
  • 字型預先載入效果可能適合在標題結尾或開頭。
  • 匯入預先載入 (動態 import()modulepreload) 必須在需要匯入的指令碼標記之後完成 (因此系統會先載入/剖析實際指令碼)。基本上,如果指令碼標記載入的指令碼會觸發依附元件載入作業,請確保依附元件的 <link rel=preload> 位於父項指令碼標記之後,否則依附元件可能會在主要指令碼之前載入。在正確順序,可以在系統載入依附元件時剖析/評估主要指令碼。
  • 圖片預先載入的優先順序設定為「低」或「中」(沒有擷取優先順序),且順序應該與非同步指令碼和其他低或最低優先順序標記相比。

記錄

「擷取優先順序」計畫於 2018 年首次在 Chrome 中進行實驗,並以 importance 屬性再次測試。當時我們稱之為優先提示。根據網路標準流程,Google 的介面已改為 fetchpriority (適用於 HTML) 和 priority (適用於 JavaScript 的 Fetch API)。為了減少混淆,我們現在將這個 API 稱為「擷取優先順序」。

結語

我們能夠修正預先載入行為,並近期將重點放在網站體驗核心指標和 LCP,因此開發人員可能會有興趣使用「擷取優先順序」。現在他們可使用額外的旋鈕來達成想要的載入序列。