Coolkid mascot CoolkidLab

SEO 菜鳥成長史 · #11 · 最後更新:2026-05-19

PageSpeed mobile 79 → 89:7 個 critical path 動作 + 3 個踩坑

#10 把全站結構對齊 AIO 5 原則做完 PageSpeed 還停在 80 多。這篇紀錄接下來 24 小時把 mobile 從 79 拉回 86-89 穩定區的 7 個動作 + 3 個踩坑。

誠實揭露:#10 結尾預告要做「critical CSS inline 子集 / nes.min.css 自製子集 / Google Fonts media trick」三件事。實際做完的是不一樣的 7 個動作 — 兩個被風險評估後跳過 一個解法被換掉。為什麼轉向也寫進來。

讀完你會知道:7 個動作的執行排序、3 個 perf 常見踩坑怎麼避、為什麼追到 PageSpeed 95+ 對個人站是走火入魔。

1. 為什麼 PageSpeed 跑分會跳?三跳教訓 (89 → 85 → 79)

動工前先講一個容易誤判的現象:PageSpeed 跑分有 ±5-10 分 variance。我那天連跑三次拿到 89 → 85 → 79 三個分數 — 同一份 code 同一個網路 三分鐘內三跳。

原因是 Lighthouse mobile 模式跑在模擬的「中階手機 + 慢速 4G」環境 模擬本身就會抖動。如果只看單次跑分容易做出兩種錯誤判斷:

  1. 看到 89 就以為「優化夠了」 — 其實隨便再跑一次可能掉到 79
  2. 看到 79 就以為「上次的改動失敗」 — 結果是 variance 不是 regression

正確做法:每次改動後跑 3-5 次取中位數。本文以下所有「改前 / 改後」分數都是中位數 不是單次。

2. 動作 1-2:拿掉 render-blocking CSS (為什麼放棄「critical CSS inline」)

Lab 用了 nes.min.css(288KB 怪物 — 但視覺風格依賴它)+ Google Fonts。兩者都是 render-blocking CSS — 瀏覽器要等它們下載完才開始畫。

原本 #10 結尾預告要做「critical CSS inline 子集」(把首屏要的 CSS 抽 1-2KB inline 到 HTML)+「nes.min.css 自製子集」(手寫 nes-minimal.css 砍到 15-30KB)。實際只做了下面兩個更便宜的動作:

為什麼放棄 critical CSS inline + 自製子集:

  1. critical CSS inline 有 FOUC 風險 — 抽錯一條樣式首屏會閃
  2. 自製 nes-minimal.css 要 2-3h 維護成本 + 升級 nes.css 時要重抽
  3. media=print trick 已收 80% 收益 — 剩下 20% 風險太高 ROI 不划算

perf 優化最大的迷思是「該做的全部做完」 — 實際上應該排序 ROI 做到邊際遞減就停。

3. 動作 3-4:字體 preload + woff2(只 preload 真在 LCP 路徑的資源)

字體跟 LCP 直接相關 — 因為 hero 標題用了自訂字體 字體沒下載完 LCP 不算發生(瀏覽器要嘛等字體 要嘛先用 fallback 字體畫再換 — 後者觸發 CLS)。

關鍵教訓:preload 不是越多越好。我中間試過把 mascot.webp 也 preload — 結果跑分反而掉 因為它跟字體搶頻寬 而 mascot 根本不在 LCP 元素路徑上。後來移除 mascot preload 跑分回升。

4. 動作 5-6:拿掉 LCP 拖累 (typewriter + body transition)

兩個自己加的「視覺優化」結果都是 LCP killer:

通則:任何在 LCP 元素上做 opacity 0→1 fade in / transform 進場 / typewriter 逐字打的動畫 都會直接把 LCP 拖 1.5-2 秒。視覺再漂亮也不該加。

5. 動作 7:visitor-overlay.js 3.5KB 取代 admin 27KB(訪客 JS payload -23KB)

Lab 有 inline-edit 功能 — admin 點 ✏️ 圖示可以在公開頁面上直接編輯內容。原本所有訪客都載 edit-overlay.js (27KB)雖然訪客根本看不到編輯按鈕。

拆分:

  1. visitor-overlay.js (3.5KB) — 所有訪客載 只處理顯示邏輯
  2. edit-overlay.js (27KB) — 只 admin (有 token 或 ?edit=1) 才 dynamic import 載入

對訪客 -23 KB JS payload。對 TBT / FCP 都有直接幫助 因為 JS parse + execute 是 main thread blocking。

這也是「為使用者而不是為自己優化」的具體實作 — admin (我) 載得多沒差 訪客省得越多越好。

6. 3 個反面教訓(踩過的坑都公開)

想做 結果 教訓
preload mascot.webp跑分掉 3-5 分preload 只給真在 LCP 路徑上的資源
加 typewriter 進場93 → 83 (-10 分)JS 動畫不該碰 LCP 元素
看單次跑分判斷89→85→79 誤判每次改動跑 3-5 次取中位數

踩坑跟動作一樣重要 — 動作告訴你「怎麼做對」 踩坑告訴你「別做什麼」。後者通常比前者省更多時間。

7. 對照分數 + 為什麼停在 86-89 是合理停損點

指標 改前(中位數) 改後 狀態
Mobile 總分79-8386-89+6-10 分
LCP~4s2.5-3.5s🟠 還橘
FCP~2.5s1.3-2.0s🟠 還橘
TBT~150ms~40ms🟢 綠
CLS~0.050-0.04🟢 綠

TBT 跟 CLS 都過綠線 LCP 跟 FCP 還在橘。但我選擇停在這 不繼續追 95+。理由:

  1. 邊際收益遞減 — 79 → 89 花 24 小時 89 → 95 至少要再花 2-3 天
  2. 剩下優化(zoom→rem 全站重算 / critical CSS inline 子集)視覺風險高 改壞跑版的 cost 比 5 分跑分高
  3. PageSpeed ≠ 真實體驗 — 真實用戶用的是 4G+ / Wifi 不是 Lighthouse 模擬的慢速 4G
  4. 比追 95 分重要 100 倍的是「下一篇文章寫了沒」 — 內容才是 SEO / GEO 的本體

個人站合理停損點:Mobile 87+ TBT 綠 CLS 綠 LCP 在 3.5s 以下。剩下時間拿去寫文章 / 做 GEO 結構 / 跟讀者互動。perf 是基礎建設 不是品牌。

AIO 結構(#10)+ critical path perf(#11)兩戰打完 Lab 結構面 + 速度面都對齊 GEO 時代。下一站:GSC 觀察 1-2 個月 看 AI 引用 referrer 數據 / 哪些頁面開始被 AI 摘要引用。資料夠了再寫 #12。

看完這篇之前先確認:

適合你
  • 想優化 PageSpeed 不知從哪開始
  • 用了 nes.css / Bootstrap 重 CSS 站
  • 想理解跑分為何會 ±5-10 跳
不適合
  • 純動態站(Next.js 已內建 critical CSS)
  • 已經穩定 95+ 的人
  • 把 PageSpeed = 真實體驗的人
最常踩
  • 看單次跑分就下大決定
  • preload 越多越好的迷思
  • JS 動畫加在 LCP hero 元素上

相關閱讀

這篇背後的真實開發過程記錄在 Build Log搜尋標籤:perfpagespeedcritical-pathlcpbuild-in-public

本篇為個人學習與實驗紀錄。PageSpeed 跑分受網路條件 / Lighthouse 版本 / 模擬硬體影響有 variance 本文數據為 Lab 實測中位數。不同站體質不同(框架 / CSS 大小 / 字體策略)請依自身狀況實驗驗證。本站不接 YMYL 高風險站、不做 PBN、不做品牌矩陣 SEO。

← 回 SEO 菜鳥成長史

⚠ 本站所有內容僅供教育與研究用途,不構成投資建議,不保證任何獲利。投資有風險,使用者須自行判斷並承擔結果。