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

Fetch Priority API 會指出資源相對於瀏覽器的相對優先順序。這有助於實現最佳載入效果,並改善 Core Web Vitals。

Addy Osmani
Addy Osmani
Leena Sohoni
Leena Sohoni
Patrick Meenan
Patrick Meenan

瀏覽器支援

  • Chrome:102。
  • Edge:102。
  • Firefox:132。
  • Safari:17.2。

資料來源

當瀏覽器剖析網頁,並開始探索及下載圖片、指令碼或 CSS 等資源時,會為這些資源指派擷取 priority,以便以最佳順序下載。資源的優先順序通常取決於資源的類型和文件中的所在位置。舉例來說,檢視區內的圖片可能具有 High 優先順序,而使用 <link><head> 中提早載入的轉譯阻斷 CSS 的優先順序可能為 Very High。瀏覽器在指派優先順序時,通常都能順利執行,但在某些情況下可能並非最佳做法。

本頁面將說明 Fetch Priority API 和 fetchpriority HTML 屬性,可讓您提示資源 (highlow) 的相對優先順序。Fetch Priority 可協助您改善 Core Web Vitals。

摘要

Fetch Priority 可協助處理以下幾個重點:

  • 在圖片元素上指定 fetchpriority="high",提升 LCP 圖片的優先順序,以便提早發生 LCP。
  • 提高 async 指令碼的優先順序,使用比目前最常見的駭客手法更佳的語意 (為 async 指令碼插入 <link rel="preload">)。
  • 降低晚期主體指令碼的優先順序,以便與圖片搭配時能有更好的排序。
比較 Google 航班/機票首頁的兩項測試結果。在底部,我們使用「擷取優先順序」提升主圖片的優先順序,因此 LCP 減少了 0.7 秒。
在 Google 航班/機票的測試中,Fetch Priority 可將 Largest Contentful Paint 從 2.6 秒縮短至 1.9 秒。

以往開發人員使用預先載入預先連線功能,對資源優先順序的影響有限。您可以透過預先載入功能,在瀏覽器自然偵測到重要資源之前,先告知瀏覽器要載入的資源。這項功能特別適合用來探索較難發現的資源,例如樣式表中包含的字型、背景圖片,或是從指令碼載入的資源。預先連線可協助暖機跨來源伺服器的連線,並有助於改善第一個位元組時間等指標。這項功能在您知道來源,但不一定知道所需資源的確切網址時很有用。

擷取優先順序可補足這些資源提示。這是透過 fetchpriority 屬性提供的標記信號,開發人員可用來指出特定資源的相對優先順序。您也可以透過 JavaScript 和 Fetch API 使用這些提示,並搭配 priority 屬性,影響為資料擷取資源的優先順序。擷取優先順序也可以補足預先載入功能。以最大內容繪製圖片為例,在預先載入時,仍會獲得較低的優先順序。如果圖片被其他早期低優先順序資源推遲,使用擷取優先順序可協助加快圖片載入速度。

資源優先順序

資源下載順序取決於瀏覽器為網頁上每項資源指定的優先順序。可能影響優先順序計算邏輯的因素包括:

  • 資源類型,例如 CSS、字型、指令碼、圖片和第三方資源。
  • 文件參照資源的位置或順序。
  • 指令碼是否使用 asyncdefer 屬性。

下表說明 Chrome 如何為大多數資源設定優先順序:

  在版面配置阻斷階段載入 在版面配置阻斷階段一次載入一個
Blink
Priority
VeryHigh VeryLow
開發人員工具
優先順序
最高 最低
主要資源
CSS (早期**) CSS (延遲**) CSS (媒體不相符***)
指令碼 (提前** 或未從預先載入掃描器) 腳本 (晚到**) 指令碼 (非同步)
字型 字型 (rel=preload)
匯入
圖片 (位於可視區域內) 圖片 (前 5 張圖片 > 10,000 像素 2) 圖片
媒體 (影片/音訊)
預先擷取
XSL
XHR (同步) XHR/fetch* (非同步)

瀏覽器會依據發現的順序,下載具有相同計算優先順序的資源。您可以在載入網頁時,透過 Chrome 開發人員工具的「Network」分頁,查看系統為不同資源指定的優先順序。(請務必在表格標題上按一下滑鼠右鍵,然後勾選「priority」欄)。

Chrome 開發人員工具的「網路」分頁列出多個字型資源。這些規則的優先順序均為最高。
BBC 新聞詳細資料頁面上資源 type = "font" 的優先順序
Chrome 開發人員工具的「網路」分頁列出多個字型資源。優先順序為低和高。
BBC 新聞詳細資料頁面上資源 type = "script" 的優先順序。

優先順序變更時,您可以在「大規模請求列」設定或工具提示中,同時查看初始和最終優先順序。

Chrome 開發人員工具的「網路」分頁。勾選「大要求資料列」設定,且「優先順序」欄顯示第一張優先順序為「高」的圖片,以及下方不同的初始優先順序「中」。工具提示也會顯示相同的內容。
開發人員工具中的優先順序變更。

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

瞭解瀏覽器的優先順序邏輯後,您就可以調整網頁的下載順序,以便最佳化網頁效能和Core Web Vitals。以下列舉一些您可以變更的項目,以影響資源下載的優先順序:

  • <script><link> 等資源標記依照瀏覽器下載的順序排列。一般來說,系統會依發現順序載入相同優先順序的資源。
  • 使用 preload 資源提示,提早下載必要資源,特別是瀏覽器不易在早期發現的資源。
  • 使用 asyncdefer 下載指令碼,且不會阻擋其他資源。
  • 延後載入下方內容,讓瀏覽器可將可用頻寬用於更重要的上方資源。

這些技術有助於控制瀏覽器的優先順序運算,進而改善效能和網站體驗核心指標。舉例來說,如果預先載入重要的背景圖片,就能提早發現該圖片,進而改善最大內容繪製時間 (LCP)。

有時這些句柄可能不足以為應用程式提供最佳資源優先順序。以下是使用擷取優先順序的幾種情境:

  • 您有幾張置頂圖片,但並非所有圖片都應具有相同的優先順序。舉例來說,在圖片輪轉介面中,只有第一個可見圖片需要較高的優先順序,其他通常在螢幕外顯示的圖片則可設定為較低的優先順序。
  • 可視區域內的圖片通常會以 Low 優先順序開始。版面配置完成後,Chrome 會發現這些元素位於可視區域內,並提高其優先順序。這通常會大幅延遲載入重要圖片 (例如主頁橫幅圖片)。在標記中提供擷取優先順序,可讓圖片以 High 優先順序啟動,並提早開始載入。為了盡可能自動化這項作業,Chrome 會將前五張較大的圖片設為 Medium 優先順序,這有助於改善問題,但明確的 fetchpriority="high" 會更有效。

    如果要及早偵測以 CSS 背景格式納入的 LCP 圖片,仍須使用預先載入功能。如要提高背景圖片的優先順序,請在預載時加入 fetchpriority='high'
  • 將指令碼宣告為 asyncdefer,可讓瀏覽器以非同步方式載入指令碼。不過,如優先順序表所示,這些指令碼也已指派為「低」優先順序。建議您提高優先順序,同時確保非同步下載,尤其是對使用者體驗至關重要的指令碼。
  • 如果您使用 JavaScript fetch() API 以非同步方式擷取資源或資料,瀏覽器會將 High 優先順序指派給該 API。您可能會希望某些擷取作業以較低的優先順序執行,尤其是當您同時使用背景 API 呼叫和回應使用者輸入內容的 API 呼叫時。將背景 API 呼叫標示為 Low 優先順序,將互動式 API 呼叫標示為 High 優先順序。
  • 瀏覽器會將 High 優先順序指派給 CSS 和字型,但其中部分資源可能比其他資源更重要。您可以使用 Fetch Priority 降低非必要資源的優先順序 (請注意,早期 CSS 會阻斷轉譯,因此通常應為 High 優先順序)。

fetchpriority 屬性

使用 fetchpriority HTML 屬性,為使用 linkimgscript 標記下載的資源類型 (例如 CSS、字型、指令碼和圖片) 指定下載優先順序。可接受下列值:

  • high:資源的優先順序較高,您希望瀏覽器將其優先順序設為高於平常,除非瀏覽器本身的推論法會阻止這項操作。
  • low:資源的優先順序較低,您希望瀏覽器將其降優先順序 (如果其 heuristics 允許的話)。
  • auto:預設值,可讓瀏覽器選擇適當的優先順序。

以下列舉幾個範例,說明如何在標記中使用 fetchpriority 屬性,以及等同於指令碼的 priority 屬性。

<!-- 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
Priority
VeryHigh VeryLow
開發人員工具
優先順序
最高 最低
主要資源
CSS (早期**) ⬆◉
CSS (延遲**)
CSS (媒體不相符***) ⬆*** ◉⬇
指令碼 (提前** 或未從預先載入掃描器) ⬆◉
腳本 (晚到**)
指令碼 (async/defer) ◉⬇
字型
字型 (rel=preload) ⬆◉
匯入
圖片 (位於可視區域中 - 版面配置後) ⬆◉
圖片 (前 5 張圖片 > 10,000 像素 2)
圖片 ◉⬇
媒體 (影片/音訊)
XHR (同步) - 已淘汰
XHR/fetch* (非同步) ⬆◉
預先擷取
XSL

fetchpriority 會設定相對優先順序,也就是將預設優先順序提高或降低適當幅度,而非明確將優先順序設為 HighLow。這通常會導致 HighLow 優先順序,但不一定。舉例來說,使用 fetchpriority="high" 的關鍵 CSS 會保留「非常高」/「最高」優先順序,而對這些元素使用 fetchpriority="low" 則會保留「高」優先順序。這兩種情況都沒有明確將優先順序設為 HighLow

用途

如要提供瀏覽器有關擷取資源優先順序的額外提示,請使用 fetchpriority 屬性。

提高 LCP 圖片的優先順序

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

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

下圖比較了 Google 航班/機票頁面,其中一個有載入 LCP 背景圖片,另一個則沒有,以顯示兩者的差異。將優先順序設為高後,LCP 從 2.6 秒改善為 1.9 秒

實驗使用 Cloudflare worker 來重寫 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>

雖然圖片 2 至 4 會位於檢視區之外,但系統可能會將這些圖片視為「足夠接近」的圖片,因此會將圖片提升至 high,即使新增 load=lazy 屬性也一樣。因此,fetchpriority="low" 是這個問題的正確解決方案。

在先前針對 Oodle 應用程式進行的實驗中,我們使用這項功能降低載入時不會顯示的圖片優先順序。這項調整可將網頁載入時間縮短 2 秒。

在 Oodle 應用程式的圖片輪轉介面中使用擷取優先順序時,擷取優先順序的並排比較。在左側,瀏覽器為輪轉介面圖片設定預設優先順序,但下載和繪製這些圖片的速度比右側範例慢約兩秒,因為右側範例只為第一個輪轉介面圖片設定較高的優先順序。
只為第一張輪轉介面圖片使用高優先順序,可加快網頁載入速度。

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

如要停止預先載入的資源與其他重要資源競爭,您可以降低其優先順序。請在圖片、指令碼和 CSS 中使用這項技巧。

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

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

重新設定指令碼優先順序

網頁需要的互動指令碼應快速載入,但不應阻擋其他更重要的轉譯阻斷資源。您可以將這些項目標示為優先順序為 async

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

如果指令碼依賴特定 DOM 狀態,就無法標示為 async。不過,如果這些資源是在網頁上執行,您可以以較低的優先順序載入:

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

這麼做仍會在剖析器遇到這個指令碼時將其封鎖,但會允許優先處理前面的內容。

如果需要完整的 DOM,您可以改用 defer 屬性 (會依序在 DOMContentLoaded 後執行),甚至是頁面底部的 async

降低非必要資料擷取作業的優先順序

瀏覽器會以高優先順序執行 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 擷取優先順序可能不會大幅改善 LCP。不過,如果預先載入作業發生在其他資源載入後,high 擷取優先順序可以進一步改善 LCP。如果重要圖片是 CSS 背景圖片,請使用 fetchpriority = "high" 預先載入。

  • 在資源競爭可用網路頻寬的環境中,優先順序可改善載入時間。在無法並行下載的 HTTP/1.x 連線,或低頻寬的 HTTP/2 或 HTTP/3 連線上,這類情況很常見。在這種情況下,優先順序有助於解決瓶頸問題。

  • CDN 並未統一實作 HTTP/2 優先順序,HTTP/3 也是如此。即使瀏覽器透過擷取優先順序傳達優先順序,CDN 可能也不會依指定順序重新設定資源的優先順序。這會導致測試擷取優先順序的難度提高。優先順序會在瀏覽器內部和支援優先順序的通訊協定 (HTTP/2 和 HTTP/3) 中套用。不過,如果您只想為內部瀏覽器優先順序 (不論是否支援 CDN 或來源) 使用 Fetch Priority,還是值得這麼做,因為瀏覽器要求資源時,優先順序經常會變更。舉例來說,當瀏覽器處理重要的 <head> 項目時,圖片等低優先順序資源通常會暫緩要求。

  • 您可能無法在初始設計中,將「擷取優先順序」列為最佳做法。在開發週期後期,您可以將優先順序指派給網頁上的不同資源,如果這些資源不符合您的預期,您可以導入擷取優先順序來進一步進行最佳化。

開發人員應將預先載入功能用於預期用途,也就是預先載入剖析器未偵測到的資源 (字型、匯入項目、背景 LCP 圖片)。preload 提示的位置會影響資源的預先載入時間。

擷取優先順序是指擷取資源時的擷取方式。

使用預先載入功能的提示

使用預先載入功能時,請注意下列事項:

  • 在 HTTP 標頭中加入預先載入內容,會將其置於載入順序中的所有其他項目之前。
  • 一般來說,預先載入的順序會依照剖析器取得的順序,適用於 Medium 以上優先順序的任何項目。如果您在 HTML 開頭加入預先載入內容,請務必小心操作。
  • 字型預先載入功能最適合放在標頭結尾或內文開頭。
  • 匯入預先載入 (動態 import()modulepreload) 應在需要匯入的指令碼標記後執行,因此請務必先載入或剖析指令碼,以便在其依附元件載入時進行評估。
  • 圖片預先載入作業預設為 LowMedium 優先順序。並將其排序在非同步指令碼和其他低或最低優先順序的代碼之前。

記錄

在 2018 年,Chrome 首次以來源試用計畫的形式實驗擷取優先順序,並在 2021 年再次使用 importance 屬性進行實驗。當時稱為「優先順序提示」。此後,介面已變更為 HTML 的 fetchpriority 和 JavaScript 的 Fetch API 的 priority,這是網頁標準程序的一部分。為避免混淆,我們現在將這個 API 稱為 Fetch Priority。

結論

開發人員可能會對 Fetch Priority 感興趣,因為這項功能修正了預先載入行為,且最近也著重於網站體驗核心指標和 LCP。他們現在可以使用其他旋鈕,實現偏好的載入順序。