延遲載入實際上會對你的最大內容繪製造成什麼影響
延遲載入很有用,但它不是通用的效能修補方式。對 LCP 來說,它可能有幫助、造成傷害,或完全沒有影響,取決於哪一項資源被延後。
目錄
延遲載入是一種排程決策,不是加速咒語
延遲載入常被描述為一種效能改善,這沒有錯,就像不把行李箱裝滿確實能減輕重量一樣。它之所以有幫助,是因為瀏覽器一開始要做的工作變少了。
這個差異對 Largest Contentful Paint 很重要,通常簡稱為 LCP。LCP 衡量的是視窗中最大的有意義元素何時被渲染。在許多頁面上,這個元素是一張 hero image。在其他頁面上,它可能是大型標題、poster image、產品照片,或一個內容區塊。
延遲載入會改變資源被請求的時間。它不會讓圖片解碼更快、伺服器回應更快,或字型更早渲染。如果你延遲載入錯誤的東西,尤其是最後成為 LCP 的元素,你等於是在告訴瀏覽器:先等一下,再去抓取它必須顯示、才能通過 Core Web Vitals 的那個東西。
這就是為什麼延遲載入既被過度使用,也經常沒有被充分理解。
當你延遲載入圖片時,瀏覽器會做什麼
原生圖片延遲載入通常會這樣加入:
<img src='hero.jpg' loading='lazy' alt='...'>
使用 loading='lazy' 時,瀏覽器可以延後抓取圖片,直到它認為這張圖片可能即將需要被使用。實務上,瀏覽器會使用與視窗的距離、網路條件、圖片尺寸,以及其他啟發式規則。確切規則屬於實作細節,而且可能改變。
使用 loading='eager',或在多數情況下沒有 lazy 屬性時,瀏覽器會把圖片視為一般載入流程的一部分。它仍然必須在 CSS、JavaScript、字型、圖片和其他請求之間做優先順序安排,但這張圖片會立刻被發現。
這表示延遲載入主要影響三個階段:
- 發現: 瀏覽器注意到資源的時間。
- 請求開始: 網路抓取開始的時間。
- 渲染時機: 資源終於可以被解碼並繪製的時間。
對 LCP 來說,危險的是請求開始。如果 LCP 圖片請求開始得很晚,後面所有事情也都會跟著延後。
簡單規則:永遠不要延遲載入 LCP 候選元素
如果一張圖片在初始視窗中可見,而且很可能是最大的內容元素,就不要延遲載入它。
這包括:
- hero images
- 首屏以上的主要產品照片
- 大型文章主圖
- 以
<img>實作、類似背景的大型圖片 - 當 poster 是主要視覺元素時的 video poster images
瀏覽器必須等到 LCP 圖片被請求、傳輸、解碼並繪製後,才能渲染它。延遲載入會在第一步之前加入不確定性。即使只是很小的延遲,也可能足以讓較慢連線上的 LCP 從可接受變成不佳。
常見的失敗模式如下:
- 伺服器送出 HTML。
- 瀏覽器解析到一張首屏以上的圖片。
- 圖片有
loading='lazy'。 - 瀏覽器等待,因為延遲載入的啟發式規則認為它可以等。
- CSS 和 JavaScript 繼續載入。
- 圖片請求比應該開始的時間更晚才開始。
- 即使圖片檔案本身已經合理最佳化,LCP 仍然延遲。
這很令人沮喪,因為在程式碼審查中,頁面可能看起來很整潔。問題不只是檔案大小,而是優先順序。
如果你正在讀取實驗室工具輸出,並試著判斷 LCP 是否真的是問題,我們的指南 如何閱讀 Lighthouse 報告而不驚慌 刻意保持實用:在開始改程式碼之前,先區分現場資料、實驗室提示和修正方向。(注意:如果你的路由區分大小寫,請使用 CMS 中的確切 URL。)
更正:使用實際的內部 URL
正確的 Wux 文章 URL 是 如何閱讀 Lighthouse 報告而不驚慌。重點不變:在改變載入行為之前,先識別 LCP 元素。
延遲載入何時可以改善 LCP
當延遲載入讓非關鍵資源不擋在瀏覽器前面時,它可以間接改善 LCP。
想像一個產品頁,上方有一張 hero product image,首屏以下有一個包含十二張推薦圖片的 carousel。如果十三張圖片全部急切載入,瀏覽器可能會把頻寬和連線槽用在使用者還看不到的圖片上。在受限網路中,這可能會與 hero image、CSS 或字型檔案競爭。
延遲載入首屏以下的 carousel 圖片,可以幫助 LCP 圖片更早載入,因為初始頁面載入期間競爭的非關鍵請求變少了。
這才是延遲載入合理的效能使用情境:
- 急切載入首屏以上的 LCP 候選元素
- 延遲載入初始視窗以下的圖片
- 避免用沉重的 scripts 很晚才注入重要圖片
- 在 HTML 中保留圖片尺寸,以避免版面位移
延遲載入本身不是 LCP 最佳化。它是一種資源優先順序工具。當它保護關鍵路徑時,它才有幫助。
LCP 圖片的更好模式
對首屏以上的 LCP 圖片來說,目標是讓瀏覽器早點發現它、早點請求它,並在沒有版面不穩定的情況下渲染它。
穩健的基準做法如下:
<img
src='/images/product-hero.avif'
srcset='/images/product-hero-800.avif 800w, /images/product-hero-1400.avif 1400w'
sizes='(max-width: 768px) 100vw, 720px'
width='1400'
height='900'
loading='eager'
fetchpriority='high'
decoding='async'
alt='Black hiking backpack with roll-top closure'
>
重要的部分不是裝飾:
loading='eager'可避免延遲載入造成的等待。fetchpriority='high'告訴瀏覽器這張圖片很重要。width和height預留空間並減少版面位移。srcset和sizes避免下載過大的圖片。- 現代格式在謹慎使用時可以減少傳輸時間。
如果你仍然對每個螢幕提供同一張大型 JPEG,圖片格式和響應式尺寸可能比 lazy-loading 屬性更重要。實用的決策樹可參考 AVIF 何時勝過 WebP,以及何時不會。
背景圖片需要額外小心
CSS 背景圖片不會像一般 HTML 圖片那樣早被發現。瀏覽器必須先抓取並解析 CSS,才會知道它們存在。如果你的 LCP 元素是 CSS 背景圖片,你已經讓發現流程變得更困難。
這不表示背景圖片被禁止。它表示你應該有意識地使用它們。
對裝飾性圖片來說,CSS 背景沒問題。對有意義的 hero imagery 來說,<img> 或 <picture> 元素通常更好,因為它對 HTML parser 可見、支援 alt text,並且能與響應式圖片屬性良好搭配。
如果你必須為 LCP 圖片使用 CSS 背景,請考慮預先載入它:
<link rel='preload' as='image' href='/images/hero.avif'>
Preload 也不是魔法棒。預先載入太多圖片,會用另一種形式製造同樣的優先順序問題。把它用在真正重要的那一張圖片,而不是設計系統裡的每一張圖片。
JavaScript 延遲載入經常讓事情變得更糟
在原生延遲載入被廣泛支援之前,許多網站使用 JavaScript libraries,在頁面載入後或 intersection observer 觸發後,把 data-src 換進 src。有些網站現在仍然這麼做。
對長篇文章頁或大量圖片的 galleries 來說,這可能合理。對首屏以上內容來說,這是很差的選擇。
瀏覽器 preload scanner 很快,但如果圖片 URL 藏在自訂屬性裡,它就無法在 JavaScript 執行前請求那張圖片。如果你的 hero image 一開始是 data-src='hero.jpg',你就把發現流程延後到 script 下載、解析、執行和 framework hydration 之後。
這對 LCP 來說是很糟的取捨。把關鍵圖片 URL 放在真正的 HTML 裡。讓瀏覽器做它的工作。
LCP 不一定是圖片問題
在某些頁面上,LCP 元素是文字。在這種情況下,延遲載入圖片可能幾乎沒有直接影響。你的瓶頸可能是阻塞渲染的 CSS、緩慢的伺服器回應、client-side rendering,或 web fonts。
字型值得特別提起,因為它們經常是文字渲染延遲的隱藏原因。大型標題可能成為 LCP,而字型載入行為可能延遲或改變該標題繪製的時間。如果你的圖片調整沒有推動指標改善,請直接檢查 LCP 元素,而不是假設問題所在。我們關於 web fonts as a performance win 的文章涵蓋那些常常有效、但不刺激的修正:更少的 weights、現代格式、合理的 fallbacks。
如何測試延遲載入變更而不欺騙自己
不要只是坐在辦公室 Wi-Fi 上盯著頁面測試。你需要看到請求時機。
使用這個流程:
- 開啟 Chrome DevTools 並記錄 Performance trace。
- 啟用 network throttling,例如 Fast 4G 或 Slow 4G。
- 在停用快取的情況下重新載入頁面。
- 找到 LCP marker。
- 識別 LCP element。
- 在 Network panel 中,檢查該資源何時開始載入。
如果 LCP 資源開始得很晚,請問為什麼:
- 它是否被延遲載入?
- 它是否由 JavaScript 注入?
- 它是否藏在 CSS 裡?
- 它是否被其他圖片排擠而降低優先順序?
- 伺服器回應是否很慢?
接著只做一項變更並重新測試。當團隊在同一次部署中同時改圖片格式、延遲載入、預先載入、JavaScript bundles 和 CDN 設定時,效能工作會變得混亂。你可能改善了頁面,但不會知道是哪一項變更真正有影響。
現場資料也很重要。實驗室工具有助於診斷,但 LCP 會因裝置、網路、視窗大小、快取狀態和地理位置而變動。可以的話,使用 real-user monitoring 或 Chrome User Experience Report 資料。
<!-- tool-cta:start -->
💡 試試這個: 透過 Image Compressor 處理你的 LCP 圖片,使其保持較小並優先載入,這樣就能不需要 lazy loading 也能快速渲染。
<!-- tool-cta:end -->
多數網站適用的實務政策
對多數 marketing sites、ecommerce pages、documentation sites 和 publisher pages 來說,這套政策已經足夠:
- 首屏以上主要圖片:急切載入,並考慮高 fetch priority。
- 首屏以下內容圖片:延遲載入。
- Icons 和 tiny UI assets:通常不值得逐一思考。
- CSS background hero:重新考慮改成 HTML image,或謹慎 preload。
- JavaScript-injected hero image:如果可能,修正渲染架構。
- Carousels:只急切載入第一個可見 slide;其餘延遲載入。
有些邊界案例。瀏覽器啟發式規則會改進。Frameworks 會加入自動圖片元件。有些 platforms 現在會避免延遲載入偵測到靠近視窗的圖片。即使如此,原則不變:關鍵資源應該早且明顯;非關鍵資源應該等待。
當延遲載入表達出這個差異時,它很有價值。當它把最重要的內容藏起來,直到頁面已經開始輸掉 LCP 競賽之後才讓瀏覽器看到時,它就有害。