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

CDN 改善 LCP 的機制與實測:Cache Rules、圖片傳輸與快取命中率診斷

CDN 怎麼影響 LCP 的四個子階段?本文拆解 TTFB、資源載入時間與快取命中率的關聯,說明 Cloudflare Cache Rules 設定步驟、圖片 CDN 格式壓縮,以及工程師實測 LCP 從 3.8s 壓到 1.4s 的完整設定紀錄。

陳

陳柏翰

網站效能工程師

CDN 改善 LCP 的機制與實測:Cache Rules、圖片傳輸與快取命中率診斷

CDN 怎麼改善 LCP?從 TTFB、快取命中率到圖片傳輸的完整分析

本文討論的是 CDN 對 LCP(Largest Contentful Paint)四個子階段的影響機制,不是 CDN 廠商選型。很多工程師加了 CDN 之後,Lighthouse 的 TTFB 確實降下來了,但 LCP 還是卡在 3 秒以上。問題不在 CDN 沒用,而是 CDN 只能直接影響 LCP 四個子階段中的一到兩個,其他瓶頸要另外處理。這篇整理了實測 waterfall 分析、Cloudflare Cache Rules 設定步驟、cache hit rate 診斷方式,以及一個把 LCP 從 3.8s 壓到 1.4s 的真實設定紀錄。要理解 CDN 如何配合 LCP 優化完整架構,先把四個子階段搞清楚才有效率。

CDN 透過哪些機制影響 LCP 的四個子階段?

LCP 由四個子階段組成,每個階段 CDN 的影響力不同。TTFB 和 resource load time 是 CDN 直接能壓縮的兩個階段;resource load delay 和 render delay 主要受 HTML 解析順序、preload 設定、render-blocking 資源影響,CDN 間接有幫助但不是主力。

LCP 四個子階段與 CDN 影響範圍對應圖
LCP 四個子階段(TTFB / 資源載入延遲 / 資源載入時間 / 渲染延遲)與 CDN 可介入的範圍標記
LCP 四子階段 × CDN 影響能力
子階段 定義 CDN 影響程度 CDN 的具體作用
TTFB(伺服器回應) 從請求發出到第一個 byte 回應的時間 直接影響 邊緣節點就近回應,省去跨洲 RTT;HTML 快取後直接從邊緣回傳
Resource Load Delay(資源載入延遲) 瀏覽器發現 LCP 元素到開始下載的時間 間接(小) CDN 無法影響 preload 設定或 HTML 解析順序;需搭配 fetchpriority 或 preload
Resource Load Time(資源載入時間) 下載 LCP 資源(通常是圖片)的實際時間 直接影響 邊緣節點就近提供圖片;啟用 WebP/AVIF 轉換縮小檔案體積
Render Delay(渲染延遲) 資源下載完到實際繪製完成的時間 間接(小) 透過壓縮 HTML 和 CSS 加快解析;但主要取決於 DOM 複雜度和 JS 執行

根據 web.dev 的 LCP 優化指南,TTFB 的目標是壓到 800ms 以下,resource load time 的目標根據 LCP 圖片大小而定,但通常要壓到 200ms 以內才算好。這兩個數字直接決定 CDN 要設定到什麼程度。

TTFB 降低了,LCP 為什麼還是很慢?

TTFB 從 1,200ms 降到 280ms,但 LCP 只從 3.8s 降到 3.1s。這是最常見的工程師誤判。原因是 LCP 的四個子階段裡,TTFB 只是其中一個,而且不一定是最胖的那個。

打開 Chrome DevTools 的 Performance 面板,跑一次錄製,找到 LCP 元素被標記的那個 frame。在 Timing 欄看 LCP breakdown:如果 resource load time 佔了 2s 以上,那 CDN 降 TTFB 只贏了一小局。圖片本身 1.2MB 還沒壓縮,才是主要瓶頸。

診斷步驟:

  1. DevTools Network tab,過濾 Img,找到 LCP 圖片
  2. 點擊圖片資源,看 Timing 細節:Waiting (TTFB) 和 Content Download 各佔多少
  3. 如果 Content Download 時間 > Waiting 時間,瓶頸是圖片大小,不是 TTFB
  4. 此時需要的是壓縮圖片或啟用圖片 CDN,而不是繼續調整快取策略

TTFB 優化的細節,包括六個階段的診斷方式,可以參考 TTFB 優化完整指南。

Cloudflare 預設不快取 HTML:Cache Rules 怎麼設定?

Cloudflare 預設只快取靜態資源(CSS、JS、圖片、字體),HTML 不在預設快取範圍內。這表示每次用戶請求頁面,Cloudflare 都會回頭問 origin server,TTFB 不會因為 Cloudflare 而大幅改善。要讓 HTML 也被快取,需要手動建立 Cache Rules。

Cloudflare Cache Rules 設定流程圖
Cloudflare Cache Rules 四步驟設定流程:從 Zone 設定到 TTL 配置

設定步驟:

  1. 登入 Cloudflare Dashboard,選擇你的 Zone(網域)
  2. 左側導航 Caching > Cache Rules,點「建立規則」
  3. 設定觸發條件:所有請求(All incoming requests),或限縮到特定路徑如 /blog/*
  4. 快取行為選「Cache everything」,設定 Edge TTL(建議靜態內容 86400s,動態內容 3600s)
  5. 儲存並啟用

注意事項:如果網站有登入功能或個人化內容,不能對所有路徑套用 Cache everything,要先排除 /account/、/cart/ 等動態路徑。快取規則的概念可以先看 快取是什麼 這篇建立基礎認識。

Cache Hit Rate 低於 70% 的四個常見原因

Cache Hit Rate(快取命中率)是衡量 CDN 效果的核心指標。理想的命中率應在 80% 以上,低於 70% 代表大量請求仍穿透到 origin server,TTFB 改善幅度有限。

Cache Hit Rate 偏低的四種常見原因與修法
原因 說明 識別方式 修法
URL 含動態 query string 分析工具在 URL 加上 ?session=xxx 或 ?fbclid=xxx,讓每個 URL 被視為不同資源 Cloudflare Analytics 看 cache status 分布 在 Cache Rules 設定忽略特定 query string(Cache Key 設定)
Cookie 造成 bypass 請求含有特定 Cookie(如購物車 cookie),Cloudflare 判斷為動態內容不快取 Response Header 看 cf-cache-status: BYPASS 設定 Cache Rules 排除 Cookie bypass,或清理不必要的 Cookie
Origin 回傳 no-cache header 伺服器送出 Cache-Control: no-cache 或 no-store,Cloudflare 尊重此設定不快取 Network tab 看 Response Headers 的 Cache-Control 修改伺服器 Cache-Control 設定,或在 Cloudflare 建立 Override Cache-Control 規則
動態回應(每次不同) PHP/Node.js SSR 每次回傳不同 HTML,即使設定 Cache everything 也會 bypass 看 cf-cache-status: DYNAMIC 或 MISS 考慮靜態化(SSG)或在 CDN 層啟用 HTML streaming cache

根據 web.dev CDN 指南,Cache Hit Rate 低的最常見罪犯是 URL 參數問題,特別是第三方分析腳本自動附加的 tracking parameter。

如何用 Response Header 驗證 CDN 快取是否命中?

設定完 Cache Rules 之後,第一個要做的事是驗證快取確實生效,不能只靠感覺說「應該有快取了」。最直接的方式是看 HTTP Response Header 的 cf-cache-status 值。

驗證步驟:

  1. 打開 Chrome DevTools,切到 Network tab
  2. 重新整理頁面(不要 Hard Refresh,用一般 F5 或重新輸入 URL)
  3. 點擊最上方的 HTML 文件請求
  4. 切到 Headers 頁籤,往下找 Response Headers
  5. 找 cf-cache-status 欄位,確認值為 HIT
cf-cache-status 各值的意義
值 意義 對 TTFB 的影響
HIT 從邊緣節點快取直接回應 最快,TTFB 通常 < 100ms
MISS 快取沒有,向 origin 請求後快取 第一次較慢,後續 HIT
EXPIRED 快取過期,重新向 origin 驗證 略慢,需重新驗證
BYPASS 快取被跳過(Cookie / no-cache header / 動態路徑) 等同無 CDN,每次打 origin
DYNAMIC 動態內容,Cloudflare 判斷不適合快取 等同無 CDN

如果看到 MISS 而且一直不轉 HIT,通常是快取 TTL 設太短(如 0s)或 Cache Rules 設定有誤。如果是 BYPASS,回到上一節找對應的 bypass 原因排除。

圖片 CDN 如何縮短 LCP 的 Resource Load Time?

LCP 元素 73% 是圖片(2024 Web Almanac 數據),所以圖片傳輸速度直接決定 resource load time。圖片 CDN 做的事是:就近提供圖片 + 自動轉換為更小的格式(WebP 或 AVIF)+ 根據裝置尺寸動態裁切。

Cloudflare 提供兩個相關功能:

  • Cloudflare Polish:自動將圖片轉換為 WebP(需 Pro 方案),開啟後不需改 HTML,Cloudflare 在邊緣自動轉換
  • Cloudflare Images:完整的圖片 CDN 服務,支援 AVIF 轉換、響應式圖片、動態裁切,需額外費用

關於 LCP 圖片的 HTML 設定,搭配 fetchpriority 設定 一起使用效果更明顯;CDN 讓圖片下載快,fetchpriority 讓瀏覽器更早開始下載。圖片格式的完整比較可以參考 網站圖片優化指南。

Cloudflare Polish 和 AVIF 轉換:效果好不好?

Cloudflare Polish 對 WebP 轉換效果明顯,平均可以把 LCP 圖片體積縮小 40-60%;AVIF 更進一步省下約 40% 體積,但需要確認瀏覽器支援度再決定是否啟用。以下是實測三個格式的對比數據(圖片解析度 1,440x900,相同內容):

LCP 圖片格式對比:檔案大小與 LCP Resource Load Time
格式 檔案大小(典型值) Resource Load Time(3G 模擬) 瀏覽器支援度 備注
JPEG(原始) 380KB 1,420ms 全平台 未壓縮基準值
JPEG(壓縮 q=80) 210KB 820ms 全平台 最保守做法
WebP 145KB 560ms Chrome / Firefox / Safari 14+ Cloudflare Polish 自動轉換
AVIF 88KB 340ms Chrome / Firefox(Safari 16+) Cloudflare Images 支援

AVIF 比 WebP 再省 40% 體積,但 Safari 16 以下不支援。建議做法是搭配 <picture> 元素,瀏覽器依序嘗試 AVIF → WebP → JPEG:

<picture>
  <source srcset="hero.avif" type="image/avif">
  <source srcset="hero.webp" type="image/webp">
  <img src="hero.jpg" alt="主視覺圖" fetchpriority="high" width="1440" height="900">
</picture>

這段 code 讓支援 AVIF 的瀏覽器(Chrome、Firefox)自動用最小的版本,Safari 退回 WebP,舊瀏覽器退回 JPEG。每個 <source> 都讓 CDN 提供對應格式的快取版本。

從 3.8s 到 1.4s:一個實測案例的設定組合

這是一個媒體站首頁的 LCP 優化紀錄,初始環境:Nginx origin,台灣主機,Cloudflare 免費方案但完全沒有設定快取規則,LCP 元素是一張 440KB 的 JPEG banner。

CDN 改善 LCP 實測:從 3.8s 到 1.4s 的設定紀錄
CDN 改善 LCP 實測:三個設定步驟的效果累積圖
LCP 改善實測:各步驟的效果拆解
步驟 設定內容 TTFB 變化 Resource Load Time 變化 LCP 結果
初始狀態 Cloudflare 未設定快取規則 1,240ms 1,580ms(440KB JPEG) 3.8s
步驟 1 建立 Cache Rules:Cache everything,TTL 86400s 1,240ms → 280ms(命中邊緣快取) 1,580ms(圖片未改) 2.9s(-0.9s)
步驟 2 啟用 Cloudflare Polish(WebP 轉換) 280ms 1,580ms → 620ms(158KB WebP) 1.7s(-1.2s)
步驟 3 加 fetchpriority="high" 到 LCP img 280ms 620ms → 560ms(提早發現資源) 1.4s(-0.3s)

最大的改善來自步驟 1(HTML 快取讓 TTFB 降了 960ms)和步驟 2(圖片 WebP 轉換省了近 1s)。步驟 3 的 fetchpriority 相對小,但加上去很容易,不加白不加。

要注意的是,步驟 1 設定 Cache Rules 後,第一次請求還是 MISS(去 origin 取),第二次以後才 HIT。用 WebPageTest 的 repeat view 才能測到 CDN 命中後的真實數字;Lighthouse 的 lab data 可能每次都 MISS。

CDN 改善 LCP 沒效果的三種常見情境

CDN 不是萬能的。LCP 瓶頸如果不在 TTFB 或 resource load time,只加 CDN 幾乎看不到效果。以下三種情境是工程師最常誤判 CDN 有用的場景,每個情境都需要不同的修法,先診斷清楚才能對症下藥:

  1. LCP 瓶頸在 render delay,不在傳輸
    如果 LCP breakdown 顯示 TTFB 200ms、resource load time 400ms,但 render delay 卻有 2s,代表問題是 LCP 圖片被 JavaScript 阻塞渲染,或 DOM 太複雜。CDN 降不了 render delay。這時要往 JS 執行優化和 render-blocking 消除方向走。
  2. 網站是 SSR 但沒有 HTML 快取
    如果使用 Next.js SSR 或 PHP 動態渲染,每次請求都產生不同 HTML,Cloudflare 看到 Cookie 或動態 header 就 bypass,快取命中率近 0。這種情況要先解決 HTML 快取問題(或改用 SSG / ISR),CDN 才有用武之地。
  3. LCP 元素不是靜態圖片,是 CSS background-image
    CSS background-image 的 LCP 元素無法用 fetchpriority 加速,也不在瀏覽器的 preload scanner 掃描範圍,resource load delay 天生就長。CDN 可以讓圖片本身快,但延遲發現的問題沒解決,LCP 還是慢。建議改成 <img> 元素。

CDN 改善 LCP 的診斷清單

CDN 改善 LCP 的正確做法是先診斷再設定,不同的 LCP 瓶頸對應不同的 CDN 設定組合。按順序跑以下清單,確認瓶頸在哪個子階段,再決定優先處理哪一步:

  1. 確認 CDN 有沒有命中:Response Header 看 cf-cache-status: HIT。如果是 MISS/BYPASS,先解決快取問題。
  2. 看 LCP Breakdown 數字:DevTools Performance 面板錄製,找 LCP 元素,看 TTFB / resource load delay / resource load time / render delay 各多少。
  3. 確認 LCP 瓶頸在哪個階段:
    • TTFB > 800ms → 設定 HTML 快取(Cache Rules)
    • Resource load time > 500ms → 壓縮圖片或啟用圖片 CDN
    • Resource load delay > 200ms → 加 fetchpriority="high" 或 preload
    • Render delay > 200ms → 查 render-blocking JS/CSS
  4. 驗證 cache hit rate:Cloudflare Analytics 看 Cache Hit Rate;低於 70% 找 bypass 原因。
  5. 圖片格式確認:LCP 圖片是 JPEG 超過 150KB 就考慮轉 WebP 或 AVIF。
  6. 用 repeat view 測試:WebPageTest 勾選 repeat view,才能測到 CDN 命中後的真實 LCP 數字;Chrome DevTools LCP Breakdown 工具也可以直接看各子階段佔比。
陳

陳柏翰

網站效能工程師

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

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

想看更多?

探索所有效能實驗

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

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