Web Performance

為什麼你的 Time to First Byte 很慢,以及該怎麼做

TTFB 不是單一錯誤。它是由 DNS、連線建立、CDN 路由、伺服器工作、快取未命中,有時還有一個緩慢的資料庫查詢所造成的可見延遲。

The Wux Webtools Team The Wux Webtools Team 10 分鐘閱讀 AI輔助,人類審核
A simplified network path from a browser to a CDN and origin server showing points where latency can occur.
目錄
  1. 先從 TTFB 實際測量的內容開始
  2. 什麼算是緩慢的 TTFB?
  3. 從不只一個地方測量
  4. 1. 瀏覽器開發者工具
  5. 2. 來自多個地區的合成測試
  6. 3. 真實使用者監控或伺服器日誌
  7. TTFB 緩慢的常見原因
  8. 你的 HTML 沒有被快取
  9. 你的 CDN 只快取資產
  10. 你的伺服器在回應前做太多事
  11. 資料庫查詢緩慢或不可預測
  12. 你的應用程式有 cold starts
  13. Redirects 浪費了第一個請求
  14. 實用的除錯順序
  15. Step 1: 測試主要文件,而不只是整個頁面
  16. Step 2: 比較地區
  17. Step 3: 檢查回應標頭
  18. Step 4: 檢查 origin timing
  19. Step 5: 修正已確認的最大延遲
  20. 通常有效的修正
  21. 在 edge 快取公開 HTML
  22. 將非關鍵工作移出請求路徑
  23. 減少後端相依鏈
  24. 把運算放得離使用者更近
  25. 讓 redirects 保持無聊
  26. 不該做的事
  27. 冷靜版計畫

先從 TTFB 實際測量的內容開始

Time to First Byte 通常簡稱為 TTFB,指的是瀏覽器請求某個資源,到收到回應第一個位元組之間的時間。

這聽起來像是伺服器指標,但它不只是伺服器指標。TTFB 包含幾個步驟:

  • DNS 查詢,如果主機名稱尚未被解析
  • TCP 連線建立
  • HTTPS 的 TLS 協商
  • 請求傳送到伺服器或 CDN edge 的時間
  • 伺服器上的排隊與處理
  • 回應傳回瀏覽器的時間

所以,高 TTFB 可能表示你的後端很慢。也可能表示使用者離你的 origin 很遠、CDN 設定錯誤、快取持續未命中,或伺服器花太多時間決定要送出什麼內容。

這很重要,因為 TTFB 位於載入鏈的開端附近。如果 HTML 文件很晚才抵達,瀏覽器也會很晚才發現 CSS、JavaScript、字型與圖片。即使你有很好的前端最佳化,只要第一個文件回應花了 1.5 秒,使用者仍然會覺得慢。

什麼算是緩慢的 TTFB?

沒有一個通用數字能適用於每個網站、地區與架構。不過,實務上的門檻仍然有幫助。

Google 的 web.dev 指引將低於 800 ms 的 TTFB 歸類為良好,800–1800 ms 需要改善,高於 1800 ms 則視為不佳。對於在使用者附近提供、且有良好快取的行銷頁面,你通常可以做得比這更好。對於需要執行動態工作的複雜已驗證 dashboard,可接受的數字可能較高,但它仍然應該能被解釋。

重要的習慣是將數字分段。全球平均 TTFB 900 ms,可能掩蓋了靠近 CDN edge 的使用者只需 150 ms,而另一個地區的使用者卻需要 2200 ms 的情況。同樣地,你的首頁可能沒問題,但搜尋、分類或登入後頁面可能正默默地讓人痛苦。

從不只一個地方測量

不要只憑一次 Lighthouse 執行結果來診斷 TTFB。Lighthouse 很有用,但它只是來自單一環境的一次測試。如果你剛開始解讀它,可以先冷靜閱讀如何不慌張地閱讀 Lighthouse 報告——主要重點是區分實驗室訊號與實際現場狀況。

對於 TTFB,你至少需要三種視角:

1. 瀏覽器開發者工具

開啟 Network 面板,停用快取後重新載入,並檢查主要文件請求。時間分解會顯示 DNS、連線、TLS、等待與下載階段。「waiting」階段通常是人們所說的後端時間,不過它也可能包含上游延遲。

2. 來自多個地區的合成測試

從靠近與遠離使用者的位置執行測試。如果某個地區的 TTFB 低、另一個地區高,在重寫應用程式碼之前,應先懷疑地理位置、CDN 路由、origin 位置或快取覆蓋率。

3. 真實使用者監控或伺服器日誌

現場資料會告訴你真實使用者在不同裝置、網路與 session 中的體驗。伺服器日誌可以告訴你 origin 是否快速產生了回應。用戶端觀察到的 TTFB 與 origin 處理時間之間的差異,通常就是 CDN 與網路問題出現的地方。

TTFB 緩慢的常見原因

你的 HTML 沒有被快取

這是內容網站與 ecommerce 網站最常見的問題。靜態資產被積極快取,但 HTML 文件——也就是瀏覽器最先需要的東西——每次請求都重新產生。

有時這是必要的。但通常不是。

如果一個公開頁面每天只變更幾次,它大概不應該要求每個匿名訪客都重新進行一次資料庫渲染。視情況使用完整頁面快取、edge 快取、靜態生成,或 stale-while-revalidate 模式。

檢查回應標頭中的訊號,例如 Cache-ControlCDN-Cache-StatusAgeVarySet-Cookie。如果頁面對每位訪客都送出唯一 cookie,可能會意外讓自己變得不可快取。如果你需要一個實用方式來思考這一層,我們關於 production 中 redirects 與 HTTP headers 除錯的指南中的相同除錯習慣,可以直接套用到 TTFB 工作上。

你的 CDN 只快取資產

許多團隊加上 CDN 後,就以為效能工作完成了。但如果 CDN 只提供圖片、CSS 與 JavaScript,第一個 HTML 請求可能仍然會一路傳到單一 origin 伺服器。

對於使用者都在本地的在地商家網站,這可能沒問題。但對國際受眾來說就不行。使用者離 origin 越遠,在後端工作甚至開始之前,你要付出的延遲就越多。

對 TTFB 友善的 CDN 設定通常表示:

  • 在安全的情況下快取公開 HTML
  • 尊重針對已驗證或個人化頁面的刻意 bypass 規則
  • 避免不必要的 Vary 標頭,導致快取被切得過細
  • 使用快取清除或重新驗證,而不是完全停用快取
  • 確認 edge locations 確實提供命中,而不是轉送每個請求

CDN 不是魔法。它是快取與路由層。請把它當成這樣來看待。

你的伺服器在回應前做太多事

緩慢的後端路徑可能來自許多小延遲:資料庫查詢、API 呼叫、模板渲染、feature flag 檢查、驗證、個人化、記錄,以及 cold starts。

最糟的模式是序列相依工作。例如:

  1. 擷取頁面資料
  2. 然後擷取相關商品
  3. 然後擷取價格
  4. 然後呼叫推薦服務
  5. 然後渲染 HTML

如果每個步驟都等待前一步完成,TTFB 會快速增加。將彼此獨立的工作平行化,從第一個回應中移除非關鍵呼叫,並快取成本高的結果。

一個有用的原則:如果使用者無法立即看到或使用該結果,它大概不應該阻塞第一個位元組。

資料庫查詢緩慢或不可預測

資料庫經常造成 TTFB 問題,因為它們在開發環境表現良好,卻在真實流量下表現不佳。缺少索引、大型 join、N+1 查詢、鎖競爭,以及過大的結果集,都會表現為「伺服器很慢」。

這裡不要猜。擷取慢請求的查詢時間。看 p95 與 p99,而不只是平均值。一個頁面通常在 120 ms 回應,但偶爾阻塞 4 秒,仍然會造成糟糕的使用者體驗。

常見修正包括:

  • 新增或修正索引
  • 移除 N+1 查詢模式
  • 快取讀取量大的資料
  • 對大型查詢分頁
  • 將報表或 analytics 查詢移出請求時間
  • 為下游呼叫設定合理逾時

你的應用程式有 cold starts

Serverless 與容器化平台可以很出色,但當流量突增或區域資源配置不足時,cold starts 可能會傷害 TTFB。

如果閒置後的第一個請求比後續請求慢很多,請調查 cold starts。你可能需要 provisioned concurrency、較小的 bundles、較少的啟動相依、warmer functions,或針對延遲敏感路由採用不同部署型態。

這不是反對 serverless 的論點。這是反對假裝 runtime 模型不存在的論點。

Redirects 浪費了第一個請求

Redirect 會在瀏覽器收到最終文件前,增加另一個請求-回應循環。舊連結可能無法避免從 http://https:// 的一次 redirect,但 chains 是浪費。

常見 chains 包括:

  • http://example.comhttps://example.comhttps://www.example.com
  • protocol 正規化後才進行 trailing slash 正規化
  • 快取查詢前先做 geo 或語言 redirects
  • legacy campaign links 會跳轉經過數個 URLs

盡可能修正來源連結,合併 redirect 規則,並讓 canonical URLs 直達。Redirect 時間不一定會被回報為最終請求的 TTFB,但使用者仍然要付出代價。

實用的除錯順序

當 TTFB 看起來很慢時,請使用這個順序。它能避免在確認快取與路由行為之前,就先最佳化應用程式碼的常見錯誤。

Step 1: 測試主要文件,而不只是整個頁面

找出 HTML 文件的請求。記錄總 TTFB 與時間分解。分別在有無瀏覽器快取的情況下重複測試。如果相關,測試公開頁面、動態頁面與登入後頁面。

Step 2: 比較地區

從多個地理位置執行相同 URL。如果較慢的地區與距離 origin 的遠近相關,優先處理 CDN 與 edge 快取。如果每個地區都慢,則查看後端處理與 origin 容量。

Step 3: 檢查回應標頭

尋找快取標頭、cookies、Age、CDN 狀態與 Vary。缺少 Age 標頭或反覆快取未命中都是線索。公開 HTML 上廣泛的 Vary: Cookie 標頭通常是快取殺手。

Step 4: 檢查 origin timing

加入伺服器時間 instrumentation。Server-Timing 標頭可以揭露後端階段,例如資料庫時間、渲染時間與上游 API 時間。即使是簡單標籤也很有用:

Server-Timing: db;dur=82, render;dur=41, api;dur=210

現在你的瀏覽器 timing 可以顯示伺服器是否花了 300 ms 做實際工作,或延遲是否發生在請求到達應用程式之前。

Step 5: 修正已確認的最大延遲

這聽起來很明顯,但團隊常常修熟悉的東西,而不是測量出來的東西。如果快取未命中占主因,就修快取。如果資料庫占主因,就修查詢。如果全球使用者的 TLS 與連線建立占主因,就修路由、CDN 覆蓋率或 origin 地理位置。

前端工作仍然重要。字型、圖片與 JavaScript 會影響 HTML 抵達後發生的事情。但它們不能替代快速的第一個回應。如果你也正在處理渲染效能,web fonts 仍然是許多網站上最容易取得的效能收益之一,因為它們會影響文件抵達後文字多快變得可用。

通常有效的修正

在 edge 快取公開 HTML

對於行銷頁面、文件、部落格、landing pages 與分類頁面,edge 快取通常是最大的 TTFB 改善。若內容經常變更,使用短 TTL。如果快取在背景更新時可接受內容稍微過時,使用 stale-while-revalidate。

請小心個人化。如果頁面依貨幣、語言、登入狀態或實驗群組而異,請明確定義這些變體。意外的逐使用者差異會破壞快取效率。

將非關鍵工作移出請求路徑

寄送 email、analytics enrichment、推薦生成、webhook 呼叫與繁重 logging,很少應該阻塞第一個位元組。將它們放進 queues,或在 response 開始後執行。

減少後端相依鏈

將獨立呼叫平行化。快取慢速 API 的回應。設定逾時。為有幫助但非必要的服務設計 fallback content。

一個緩慢的推薦 widget 不應該延遲整個商品頁面。

把運算放得離使用者更近

如果你的使用者遍布全球,而 origin 只在一個地區,延遲就是結構性的。CDN 快取可以為公開內容隱藏大部分延遲。對於動態內容,考慮區域部署、適合路由的 edge rendering,或將 APIs 移近受眾。

讓 redirects 保持無聊

用一次跳轉正規化 URLs。更新內部連結,讓使用者與 crawlers 直接前往最終目的地。稽核舊 campaign URLs 與平台遷移。Redirects 很容易被忽略,因為它們在正常運作時看不見,但它們仍然花時間。

不該做的事

不要為每個 route 追求完美 TTFB 數字。會執行實際運算的已驗證報表,不會像已快取的部落格文章一樣表現。

不要把平均 TTFB 當成唯一指標。百分位數很重要。地理位置很重要。頁面類型很重要。

不要假設有 CDN 就代表你的 HTML 已經被快取。請驗證它。

也不要把 TTFB 視為與產品決策無關。個人化、實驗、即時庫存與第三方服務都有延遲成本。有些值得。有些只是習慣。

<!-- tool-cta:start -->

💡 試試這個: 診斷 TTFB 時,Get Headers 會顯示快取狀態、伺服器耗時和重新導向,這些資訊通常能說明延遲來自哪裡。

<!-- tool-cta:end -->

冷靜版計畫

一旦你停止把緩慢的 TTFB 當成模糊的「伺服器問題」,它通常都可以修正。測量文件請求。依地區與頁面類型分段。檢查標頭。比較用戶端 timing 與 origin timing。然後修正已確認的最大瓶頸。

多數網站不需要奇特的架構。它們需要更少可避免的快取未命中、更少阻塞後端工作、更乾淨的 redirects,以及更清楚知道在送出第一個位元組之前,哪些事情必須發生。

常見問題

TTFB 是 Core Web Vitals 指標嗎?
不是。TTFB 不是 Core Web Vitals 之一,但它會強烈影響 Largest Contentful Paint 等指標,因為瀏覽器必須先發現文件與其相依資源,才能渲染重要內容。
好的 TTFB 目標是多少?
作為一般基準,web.dev 認為低於 800 ms 是良好。對於已快取的公開頁面,許多團隊可以設定更低目標。對於複雜的已驗證 routes,請聚焦於一致性、百分位數,以及延遲是否合理。
加入 CDN 會自動修正 TTFB 嗎?
不一定。CDN 只有在降低路由延遲或提供已快取回應時,才會改善 TTFB。如果每個 HTML 請求都被轉送到 origin,你的 CSS 與圖片可能很快,但文件仍然很慢。
JavaScript 最佳化可以改善 TTFB 嗎?
對傳統 server-rendered pages 來說,通常不會直接改善。JavaScript 影響的是回應開始後的解析、渲染與互動性。TTFB 主要關乎把第一個回應位元組送到瀏覽器。
為什麼我的 TTFB 只對登入使用者很慢?
登入後頁面較難快取,因為它們是個人化的。那裡的緩慢 TTFB 通常來自資料庫查詢、權限檢查、API 呼叫、session 處理,或無法在使用者之間共享的 server-side rendering 工作。

來源與進一步閱讀

  1. web.dev: Optimize Time to First Byte
  2. MDN Web Docs: PerformanceResourceTiming.responseStart
  3. W3C: Server Timing
  4. RFC 9111: HTTP Caching
關於作者
The Wux Webtools Team

最後更新:

繼續閱讀