Core Web Vitals 效能優化專家
建立摘要
LCP 優化 LCP CLS INP

fetchpriority="high" 讓 LCP 圖片更快載入:原理、設定與常見錯誤診斷

fetchpriority="high" 是改善 LCP 最簡單有效的一行屬性,但加了也不一定有用。本文解釋瀏覽器 Tight Mode 機制、正確設定方式、與 preload 的核心差異,以及設了屬性但 LCP 仍慢的五個根因完整診斷流程。

陳

陳柏翰

網站效能工程師

fetchpriority="high" 讓 LCP 圖片更快載入:原理、設定與常見錯誤診斷

fetchpriority="high" 讓 LCP 圖片更快載入:原理、設定與常見錯誤診斷

上個月我在一個 Next.js 電商專案上加了一行 fetchpriority="high",Lighthouse 的 LCP 從 3.8s 掉到 2.1s,WebPageTest 的瀑布圖裡那個圖片請求從 Low 跳到 High,整個時序一目了然。這個屬性的原理是什麼?為什麼一行 HTML 屬性可以讓 LCP 優化跳一個量級?以及更重要的問題:為什麼有人加了這個屬性,LCP 還是沒動?這篇記錄我把這個問題拆開來看的過程。 (如果 LCP 元素是文字而非圖片,可參考 font-display 對文字 LCP 的影響)

fetchpriority high 讓 LCP 圖片從低優先提升至高優先的時序示意
加上 fetchpriority="high" 前後,LCP 圖片在瀑布圖中的優先順序變化

fetchpriority 屬性是什麼?

fetchpriority 是一個 HTML 屬性,用來告訴瀏覽器某個資源的載入優先順序比默認值更高或更低,目前已是 W3C 標準的一部分(2023 年 2 月標準化)。它屬於 Fetch Priority API 的 HTML 介面,可以套用在 img、link、script、iframe 元素以及 JavaScript 的 fetch() 呼叫上。

這個屬性有三個有效值:

值 意思 最常用情境
high 比默認優先順序更高 LCP hero 圖片
low 比默認優先順序更低 第三方 iframe、非關鍵腳本
auto 瀏覽器自行決定(預設值) 不需要調整的一般資源

注意:fetchpriority 是調整相對優先順序,不是設定絕對值。圖片的默認優先順序是 Low,加上 high 後會升到 High。但如果本來已經是 Highest 的資源(例如 render-blocking CSS),加上 high 也不會變得比 Highest 更高,只會降到 High,這一點很多人沒注意到。

為什麼 LCP 圖片的默認優先順序偏低?

瀏覽器在解析 HTML 的時候,圖片元素默認被標記為 Low 優先順序,原因是大多數圖片都在捲動範圍之外或在展開的選單裡,對首次渲染沒有直接影響。問題是 LCP 圖片是頁面最重要的視覺內容,它也被這個規則一視同仁地塞到 Low 隊列裡。

Chrome 有一個機制可以自動提升 in-viewport 圖片的優先順序,但這個提升只有在 layout 完成之後才發生。在 layout 完成之前,圖片已經在 Low 優先的隊列中排著等了。對於 LCP 圖片來說,這段等待時間直接加到 LCP 時間上。

DevTools 瀑布圖裡會看到圖片先顯示 Low,layout 之後才跳到 High,這個從 Low 到 High 之間的灰色橫條,就是 fetchpriority 能幫你省掉的時間。

Tight Mode 是什麼?fetchpriority 如何突破它

瀏覽器資源載入分兩個 phase。初始 phase 又稱 "Tight Mode":只要 in-flight 的請求少於兩個,Low 優先的資源才會被下載,否則一律等待。這個機制是為了讓 blocking 資源(CSS、關鍵 JS)優先下載完,不被大量圖片搶佔頻寬。

Tight Mode 瀑布圖時序:Low 優先圖片等待 blocking 資源下載完畢才開始
Tight Mode 下,Low priority 的 LCP 圖片(灰色等待段)被 CSS 和 JS 請求擋住,直到 blocking 資源清空後才開始下載

Tight Mode 結束的時間點是:所有 blocking scripts in the <head> 下載並執行完畢(帶 async 或 defer 的 script 不算 blocking)。這個時間點就是 DevTools 瀑布圖裡的 DOM Interactive 黃色垂直線。

當你加上 fetchpriority="high",圖片優先順序從 Low 升到 High,瀏覽器在 Tight Mode 時也會繼續下載它,不再等待。這就是為什麼加了這個屬性後,瀑布圖裡那個長長的灰色等待段消失了。

如果你的頁面有大量 render-blocking CSS 或 JS,Tight Mode 的等待時間可能很長。這也是為什麼在 Critical Rendering Path 分析中,減少 blocking 資源和加 fetchpriority 是互補的,前者縮短 Tight Mode 持續時間,後者讓 LCP 圖片不受 Tight Mode 影響。

正確加法:哪些元素支援、如何避免過度使用

把 fetchpriority="high" 加在已確認的 LCP 元素 img 標籤上,一個頁面只加一次;img、link、script、iframe 四種元素都支援這個屬性,但 LCP 圖片以外的使用情境相對少見。

<!-- 最常見:直接加在 img 元素 -->
<img src="hero.jpg" fetchpriority="high" alt="Hero image">

<!-- picture 元素需要加在內部的 img,不是 source -->
<picture>
  <source srcset="hero.avif" type="image/avif">
  <source srcset="hero.webp" type="image/webp">
  <img src="hero.jpg" fetchpriority="high" alt="Hero image">
</picture>

<!-- preload link 可以加 fetchpriority -->
<link rel="preload" as="image" href="hero.jpg" fetchpriority="high">

<!-- 降低非關鍵資源:第三方 iframe -->
<iframe src="https://youtube.com/..." fetchpriority="low"></iframe>

一個頁面只在一張圖片上設 high。理由很直接:優先順序是相對的。如果你把三張圖都設成 high,三張的優先順序相對於彼此沒有差異,等同於回到默認狀態。實際上只有明確的 LCP 元素需要這個屬性,其他 above-the-fold 圖片不需要,瀏覽器 layout 後會自動提升它們。

另一個常見誤解是 fetchpriority="high" 和 loading="eager" 是同一回事。對比如下:

屬性 作用 Tight Mode 期間
loading="eager" 不延遲載入(取消 lazy loading) 圖片仍是 Low priority,Tight Mode 中被擋住
fetchpriority="high" 提升優先順序 圖片升為 High priority,Tight Mode 中可以下載

簡單說:loading="eager" 決定要不要載入,fetchpriority="high" 決定多快載入。LCP 圖片需要兩個條件同時成立:不 lazy + 高優先。圖片默認就是 eager,所以多數情況只需要加 fetchpriority="high"。

fetchpriority 與 preload 有什麼不同?

兩者都是加速資源載入的工具,但作用在不同的維度。簡單定義:preload 改變瀏覽器發現資源的時機;fetchpriority 改變資源的優先順序。

對比維度 preload fetchpriority
主要作用 讓 "late-discovered" 資源提早被瀏覽器看到 調整資源在下載佇列中的優先順序
適用情境 CSS 背景圖、字體、動態載入的資源 HTML 中已明確宣告的 LCP 圖片
能否突破 Tight Mode 否(preload 的圖片仍是 Low priority) 是(High priority 在 Tight Mode 可以下載)
可組合使用 是 是(在 link[rel=preload] 上加 fetchpriority="high")

如果你的 LCP 元素是直接寫在 HTML 的 <img>,只需要 fetchpriority="high",不需要 preload。反過來,如果 LCP 圖片是 CSS 背景圖或透過 JS 動態插入,瀏覽器看不到 HTML 屬性,這時候用 <link rel="preload" as="image" fetchpriority="high"> 才有效。

關於 preload 和 prefetch 的完整用法差異,可以參考 Critical Rendering Path 的優化策略。

如何用 DevTools 確認 fetchpriority 是否生效

加了 fetchpriority="high" 之後,最直接的驗證方式是在 Chrome DevTools 的 Network 面板查看圖片請求的 Priority 欄位是否從 Low 變為 High,步驟如下:

  1. 打開 DevTools → Network 面板
  2. 右鍵點擊欄位標題,勾選顯示 Priority 欄
  3. 重新載入頁面
  4. 找到 LCP 圖片的請求,確認 Priority 欄顯示 High 而不是 Low

如果加了屬性但 Priority 欄仍然顯示 Low,最常見的原因是:這張圖片是透過 CSS 載入的(background-image),HTML 屬性加在 CSS 背景圖上沒有作用,瀏覽器看不到。

另一個確認方式是在 DevTools 的 Performance 面板跑一次錄製,找到圖片請求的 timing bar,確認 priority change 發生的時機點,或是完全沒有 priority change(代表從一開始就是 High)。

設了 fetchpriority 但 LCP 仍慢的常見根因

fetchpriority 只能解決「優先順序低導致等待」這個問題。如果根因不是這個,加了屬性也不會有效果。以下是最常見的五個根因: 關於行動裝置 LCP的特殊考量,可以參考行動裝置 LCP 優化指南。

  1. TTFB 太高:伺服器回應慢,圖片下載的起跑點就慢了。fetchpriority 無法加速 TTFB。需要從伺服器端或 CDN 解決,參考 TTFB 優化。
  2. 圖片太大:即使是 High priority,下載一張 1.5MB 的圖片還是需要時間。fetchpriority 是讓下載更早開始,不是讓下載更快完成。需要搭配圖片壓縮和正確格式。
  3. 多張圖片都設了 high:優先順序的相對性讓多個 high 互相抵消。回去確認頁面上只有一個 fetchpriority="high"。
  4. CSS background-image:HTML 屬性加在不存在的 HTML 元素上,瀏覽器無法感知。改用 <link rel="preload" as="image" fetchpriority="high">。
  5. 加在錯誤的元素:你認為是 LCP 的元素不一定是瀏覽器判定的 LCP 元素。先用 DevTools 或 Lighthouse 確認真正的 LCP 元素,再加屬性。如何識別可以參考 LCP 元素識別。
LCP 仍慢的診斷決策樹:從 fetchpriority 是否生效到根因分類
加了 fetchpriority="high" 但 LCP 沒有改善時的根因診斷流程

各框架的實作方式:WordPress、Angular、Next.js

主流框架和 CMS 大多已在圖片組件層面自動加上 fetchpriority="high",只需要啟用對應的 priority 選項即可;直接使用原生 <img> 標籤的情況才需要手動設定。

WordPress 6.3+

WordPress 6.3 開始,Core 的圖片輸出邏輯會自動在偵測到的 LCP 圖片上加 fetchpriority="high"。如果你需要手動控制,可以用 wp_get_attachment_image() 傳入 fetchpriority 參數,或使用 wp_img_tag_add_fetchpriority_attr 過濾器。

<?php
// 手動在 LCP 圖片上加 fetchpriority
echo wp_get_attachment_image(
    $attachment_id,
    'full',
    false,
    array( 'fetchpriority' => 'high' )
);
?>

Angular NgOptimizedImage

Angular 的 NgOptimizedImage 指令會自動在帶有 priority 屬性的圖片上加 fetchpriority="high":

<!-- Angular template: 加 priority 即自動設 fetchpriority="high" -->
<img ngSrc="hero.jpg" priority width="1200" height="630" alt="Hero">

Next.js

Next.js 的 next/image 組件有 priority prop,設為 true 時自動加 fetchpriority="high" 並移除 lazy loading:

// Next.js: priority prop 自動設 fetchpriority="high"
import Image from 'next/image'

export default function Hero() {
  return (
    <Image
      src="/hero.jpg"
      width={1200}
      height={630}
      alt="Hero"
      priority  // 加這個就夠了
    />
  )
}

如果你在 Next.js 裡用原生 <img> 而不是 next/image,就需要手動加 fetchpriority="high"。這個情況在 App Router 的 Server Components 裡比較常見。

實驗記錄:加 fetchpriority 前後,LCP 從 3.8s 到 2.1s

測試環境:Next.js 14 (App Router) + Vercel 部署,頁面包含一個 1024×576 的 WebP hero 圖片(約 180KB),沒有 render-blocking JS,有兩個外部 CSS 字體。

指標 加 fetchpriority 前 加 fetchpriority 後 變化
LCP (Lighthouse) 3.8s 2.1s -45%
LCP (WebPageTest) 4.2s 2.3s -45%
圖片 Priority in waterfall Low → High (layout 後才升) High (從一開始) 消除 priority bump
圖片等待灰色段 (stall) 約 1.4s 約 0.1s -93%
FCP 1.2s 1.2s 無變化

FCP 沒有變化這點值得注意:fetchpriority 只影響這張圖片的下載時間,不影響 HTML parsing 和初始渲染。如果你想同時加速 FCP,需要解決的是 render-blocking 資源,不是圖片優先順序。

另一個值得記錄的細節:這個測試的字體載入用的是 font-display: swap,Tight Mode 結束時間(DOM Interactive)大約在 1.8s。沒有 fetchpriority 時,圖片在 Tight Mode 中等了足足 1.4 秒;加了 fetchpriority 後,圖片在頁面載入 0.4s 就開始下載了。

瀏覽器支援現況(2024 年後的完整支援)

2026 年的今天,fetchpriority 已在 Chrome、Edge、Safari、Firefox 所有主流桌面和行動瀏覽器上完整支援,可以無條件在生產環境使用,不需要 polyfill 或 feature detection。

  • Chrome/Edge:從 2022 年 Chrome 102 開始支援
  • Safari:iOS/macOS Safari 17.2(2023 年底)開始支援
  • Firefox:Firefox 132(2024 年 10 月)正式加入

這個屬性在不支援的舊瀏覽器中會被忽略,不會有任何副作用。換句話說,加了 fetchpriority="high" 在任何情況下都是安全的,支援的瀏覽器會用,不支援的瀏覽器跳過。

全球大約 95% 以上的瀏覽器流量現在都可以受益於這個屬性。台灣市場以 Chrome 和 Safari 為主,實際覆蓋率更高。

如果你還沒在 LCP 圖片上加這個屬性,這是今天可以做的最簡單的效能改善。一行 HTML 屬性,不需要後端改動,不需要 JS,不需要 build step,瀑布圖裡的那個灰色等待段就消失了。


參考資料

陳

陳柏翰

網站效能工程師

專注前端效能優化超過 8 年,曾協助電商、媒體和 SaaS 平台改善 Core Web Vitals 指標。相信效能優化應該基於數據而非直覺。

50+ 效能實驗
8 年 前端經驗
200+ 優化案例

想看更多?

探索所有效能實驗

查看完整的實驗報告列表,找到你需要的效能優化方案。

所有實驗報告 免費效能診斷