網站速度診斷實戰 | 用 Lighthouse CLI 從 55 分修到 84 分

編譯摘要

編譯摘要:網站速度診斷實戰(Lighthouse CLI)

第一步:濃縮

核心結論 1:TBT 與 CLS 是「陰性判讀」訊號,兩個 0 就能把慢的原因從整站縮到「載入」這一層。

  • 案例數據:FCP 13.8s、LCP 17.4s(都極慢),但 TBT 0ms、CLS 0。
  • TBT 0 代表 JavaScript 沒卡住主執行緒,CLS 0 代表排版沒亂跳,執行層與繪製層同時被排除。
  • 第二刀看 Root document 回應時間:80ms,伺服器端也被排除,剩下的只剩「在等某個檔案下載」。

核心結論 2:中文站的首屏瓶頸經常是渲染阻塞的字型,不是主機。

  • opportunities 顯示 Eliminate render-blocking resources 可省 12.2s,遠大於其他項目。
  • 元凶是一支 232KB 的 Google Fonts CSS,牽出一串 80–120KB 的中文 woff2;前 15 大請求裡 12 個是字型。
  • 根因落在佈景主題 functions.php:一次載三套字型、七種字重(Playfair Display 4 + Noto Serif TC 3 + Noto Sans TC 4)。

核心結論 3:CLI 相對 GUI 的價值不是「分數更準」,而是 JSON 能把體感翻譯成一行程式碼。

  • 同一顆引擎,GUI 只吐網頁報告,CLI 同時吐 HTML + 可解析 JSON,可用 jq 撈出「哪個資源、能省幾秒」。
  • 修改全部收斂在 functions.php,不動任何外掛:字型非阻塞載入(media="print" + onload)、補 fonts.googleapis.com preconnect(單這一項省 0.34s)、砍 CSS 未引用字重、圖片轉 WebP。
  • 結果:Performance 55 → 84、FCP 13.8s → 1.3s(快 91%)、LCP 17.4s → 4.3s、Speed Index 13.8s → 2.2s;代價是 CLS 由 0 微升到 0.054。

第二步:質疑

前提假設:

  1. 這是一個「字型型」慢站。 同一支工具在不同站會得到完全不同的結論:同團隊的 WP-CLI 健檢案例中,瓶頸是外掛執行佔 67% 載入時間、TTFB 4 秒,字型完全不是問題。判讀路徑(TBT / CLS / TTFB 三個數字)可移植,修復清單不可移植。
  2. Lighthouse 是 lab data 不是 field data。 它模擬中階手機 CPU 與節流網路,單次掃描本身有數分的變異,與真實使用者的 CrUX 欄位資料可能不一致。分數是診斷工具,不是驗收標準。
  3. 「從自己電腦掃公開網址」量到的是這條網路的體驗。 它比掃 localhost 真實,但仍受掃描端的頻寬與 CDN 節點影響,不等於全體訪客的平均。
  4. 砍字重靠 CSS 靜態比對。 若字重由 JavaScript 動態注入、或由編輯器內容(inline style)指定,靜態比對會漏掉,砍下去畫面就變。
  5. 中文字型是這個案例的放大器。 換成純英文站,同樣載七種字重的檔案量小一個數量級,同一個錯誤可能只造成 1 秒延遲,結論強度大幅下降。

換情境還成立嗎:

  • 換技術棧(Astro、Next.js、Hugo):字型阻塞與修法(preload、media="print"font-display、subset)完全一樣,這條與 CMS 無關。
  • 換資源類型(客服 widget、追蹤碼、第三方 CSS):render-blocking 的判讀與搬離關鍵路徑的手法照用。
  • 換瓶頸層(資料庫、外掛 hook、TTFB):整條路徑要換成 WP-CLI 那一套,Lighthouse 只能告訴你「不在前端」。

反例與邊界條件:

  • TBT = 0 的慢站不一定是字型,也可能是 TTFB 慢;本案是靠 Root document 80ms 這個數字才排除伺服器,少了這一刀會誤判。
  • media="print" + onload 依賴 JavaScript,關掉 JS 的訪客要靠 <noscript> fallback 才看得到字型。
  • 非阻塞載入有代價:字型切換造成 CLS 從 0 升到 0.054。這是拿一點版面位移換 12 秒首屏,不是無損改善。
  • 分數 84 ≠ Core Web Vitals 通過:LCP 4.3s 仍高於 2.5s 的 good 門檻。分數提升與指標達標是兩件事。

第三步:對標

跨域類比:

  • 鑑別診斷(醫學):本案最有價值的兩個數字是兩個「陰性結果」(TBT 0、CLS 0),因為它們一次排除掉兩整類病因。醫生縮小範圍靠排除法,不是靠找到症狀,這與 [[除錯排查方法論]] 的「每次只驗證一個假設」同構。
  • 限制理論/生產線瓶頸(TOC):非瓶頸環節再快也不提升產出。伺服器 80ms 已經很好,但改善它對首屏毫無幫助;瓶頸修掉後它會移動到下一處(本案移到未轉 WebP 的圖片、LCP 4.3s)。這解釋了為什麼「修完還有下一輪」是常態而不是失敗。
  • 關鍵路徑法(專案管理 CPM):渲染阻塞資源等於關鍵路徑上的工項,非阻塞資源等於有浮時的工項。本案並沒有刪掉那 232KB,只是把它從關鍵路徑移到浮時,總工期就縮短 12 秒。工作量沒有變少,順序變了而已。
  • 儀表燈 vs OBD-II 診斷碼:GUI 給的是「引擎故障燈亮了」(分數 55),CLI 的 JSON 給的是「P0301 第一缸失火」(functions.php 第 45 行的字型載入)。從體感到零件編號的躍遷,才是命令列工具真正換來的東西。

知識庫定位: 既有 [[WordPress 效能最佳化]] 概念的關鍵數據點全部來自後端(TTFB、Redis 命中率、外掛 hook 數量),本文補上第一組前端數據,並提供前後端的分流判準:TBT、CLS、TTFB 這三個數字決定要走 WP-CLI 那條路還是 Lighthouse 這條路。兩者不衝突,是同一個「先診斷再治療」原則的兩個分支。與 [[SEO 結構基礎]] 的「Core Web Vitals 是 tiebreaker 不是入場券」一致,本文明確避免暗示修速度就能提升排名。