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

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

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

瀏覽器支援

  • 102
  • 102
  • x
  • 17.2

來源

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

本頁說明 Fetch Priority API 和 fetchpriority HTML 屬性,可讓您瞭解資源的相對優先順序 (highlow)。擷取優先順序有助於最佳化網站體驗核心指標。

摘要

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

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

以往,開發人員在使用預先載入預先連線的情況下,對資源優先順序的影響有限。預先載入功能可讓您將重要資源告知瀏覽器,這樣一來,瀏覽器才自然找到這些資源。這對難以搜尋的資源特別有用,例如樣式表中的字型、背景圖片或指令碼載入的資源。Preconnect 有助於暖機與跨來源伺服器的連線,並協助改善時間到第一個位元組等指標。如果您知道來源,但不一定是所需資源的確切網址,這項工具相當實用。

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

資源優先順序

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

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

下表顯示 Chrome 如何決定大多數資源的優先順序,並排列出順序:

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

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

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

當優先順序改變時,您可以在「Big request rows」設定或工具提示中查看初始優先順序和最終優先順序。

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

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

現在,您已瞭解瀏覽器的優先順序邏輯,接著可以調整網頁的下載順序,使其發揮最佳效能和網站體驗核心指標。以下提供幾個可以變更資源下載優先順序的項目範例:

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

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

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

  • 您有多張不需捲動位置的圖片,但有些圖片的優先順序不應相同。舉例來說,在圖片輪轉介面中,只有第一張顯示的圖片需要較高的優先順序,其他圖片在螢幕外一開始可設為較低的優先順序。
  • 可視區域中的圖片通常會從 Low 的優先順序開始。完成版面配置後,Chrome 會發現版面配置位於可視區域,並以提高優先順序。這通常會造成載入重要圖片 (例如主頁橫幅) 的明顯延遲。在標記中提供擷取優先順序,可讓圖片從 High 優先順序開始,並提早開始載入。為了嘗試自動處理這種情況,Chrome 會將前五大圖片的優先順序設為 Medium,這將有助於解決問題,但明確的 fetchpriority="high" 會更好。

    仍需要預先載入才能提前探索可做為 CSS 背景的 LCP 圖片。如要提高背景圖片的優先順序,請在預先載入項目中加入 fetchpriority='high'
  • 宣告指令碼為 asyncdefer 會指示瀏覽器以非同步方式載入指令碼。不過,如優先順序表格所示,這些指令碼的優先順序也會設為「低」。建議您提高委刊項的優先順序,同時確保非同步下載作業 (尤其是對使用者體驗至關重要的指令碼)。
  • 如果您使用 JavaScript fetch() API 以非同步方式擷取資源或資料,瀏覽器會指派 High 的優先順序。您可能會希望部分擷取作業以較低的優先順序執行,特別是將背景 API 呼叫與回應使用者輸入內容的 API 呼叫混合使用時。將背景 API 呼叫標示為 Low 優先順序,並將互動式 API 呼叫標示為 High 優先順序。
  • 瀏覽器指定 CSS 和字型的優先順序為 High,但有些資源的重要性可能高於其他資源。您可以使用「擷取優先順序」降低非重要資源的優先順序 (請注意,早期的 CSS 會封鎖轉譯功能,因此通常應設為 High 的優先順序)。

fetchpriority 屬性

透過 linkimgscript 標記進行下載時,請使用 fetchpriority HTML 屬性指定 CSS、字型、指令碼和圖片等資源類型的下載優先順序。可能接受的值如下:

  • high:資源的優先順序較高,且只要瀏覽器本身的經驗法則不會阻礙資源發生,您希望瀏覽器的優先順序高於平時順序。
  • low:資源的優先順序較低,而您希望瀏覽器在經驗法則允許的情況下再次降低資源的優先順序。
  • 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
優先順序
VeryHigh 中等 VeryLow
開發人員工具
優先順序
最高 中等 最低
主要資源
CSS (提早**) ⬆◉
CSS (延遲**)
CSS (媒體不相符***) ⬆*** ◉⬇
指令碼 (提前** 或不從預先載入掃描器取得) ⬆◉
指令碼 (後期**)
指令碼 (非同步/延遲) ◉⬇
Font
字型 (rel=preload) ⬆◉
匯入
圖片 (在可視區域中 - 在版面配置之後) ⬆◉
圖片 (前 5 張圖片 > 10,000px2)
圖片 ◉⬇
媒體 (影片/音訊)
XHR (同步) - 已淘汰
XHR/擷取* (非同步) ⬆◉
預先擷取
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 工作站,透過「擷取優先順序」重新編寫 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 或來源支援影響,還是值得一試,因為在瀏覽器要求資源時,優先順序經常會改變。舉例來說,在瀏覽器處理關鍵 <head> 項目時,低優先順序資源 (例如圖片) 往往不會遭到要求。

  • 在初次設計時,您可能無法導入「擷取優先順序」這項最佳做法。在開發週期的後續階段,您可以把優先順序指派給頁面上的各種資源。如果資源不符合您的期望,則可推出「擷取優先順序」功能,進一步進行最佳化。

開發人員應根據預期用途使用預先載入,預先載入剖析器未偵測到的資源 (字型、匯入作業、背景 LCP 圖片)。preload 提示的位置會影響預先載入資源的時間。

擷取優先順序取決於擷取資源的方式。

使用預先載入的提示

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

  • 如果在 HTTP 標頭中加入預先載入,其順序會優先於其他內容之前。
  • 一般而言,在剖析器接收到優先順序為 Medium 以上的項目時,系統會按照剖析器接收到的順序預先載入。如果您在 HTML 的開頭加入預先載入,請務必小心謹慎。
  • 字型預先載入效果可能最適合放在標題結尾或內文開頭。
  • 匯入預先載入 (動態 import()modulepreload) 應在需要匯入的指令碼標記之後執行,因此請務必先載入或剖析指令碼,以便在載入依附元件時進行評估。
  • 根據預設,圖片預先載入的優先順序為 LowMedium。請依據非同步指令碼和其他優先順序低或最低的標記,將這些標籤排序。

記錄

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

結論

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