PageSpeed 效能 67 → 93:三輪優化全紀錄
文 / Coolkid發布:2026-05-09 · 最後更新:2026-06-11閱讀約 8 分鐘

摘要
PageSpeed 分數太低怎麼優化?非工程師的靜態站從 67 分修到 93 分,只動了三件事,壓圖片(WebP 省 97%)、字型改成 font-display: optional、修版面位移(CLS 0.336 降到 0.05)。每輪只改一個變因,總共約 1.5 小時。
GSC 等不到資料的這幾天,我先跑去玩 PageSpeed Insights。
第一次跑完就直接被打臉。
效能 67 分(橘燈),最大內容繪製(LCP)19.8 秒。Google 自己定的標準是 2.5 秒。我超標將近 8 倍。
這篇紀錄我怎麼把效能從 67 衝到 93,LCP 從 19.8 秒降到 2.3 秒,CLS 從 0.336 修到 0.05 以下。
總共三輪,每一輪只修一個東西。
1. 為什麼這篇值得寫
PageSpeed 的教學文章一抓一大把,但大部分都是「給工程師看的清單」:
- Tree-shaking、code splitting、SSR vs SSG
- HTTP/2 push、Brotli、CDN edge cache
- Critical CSS、preconnect、prefetch、prerender
我這種非工程師背景的,看了只會更慌。
實際上一個普通的靜態網站,九成的問題就集中在三件事,圖片太大、字型載得慢、版面在跳。
把這三件處理完,分數會從 60 多直接跳到 90 以上。
先講官方的標準訂在哪裡。Google Core Web Vitals 官方標準把「良好」定義成 LCP 不超過 2.5 秒,CLS 不超過 0.1,互動回應(INP)不超過 200 毫秒,取的是所有造訪的第 75 個百分位。
下面三輪優化追的就是這條線。
2. 為什麼圖片是 PageSpeed 最大兇手?(67 → 78)
看到 67 分,第一反應是「我程式碼是不是哪裡寫爛了」。冷靜下來打開 assets 資料夾:
portrait-pixel.png 1907 KB
mascot.png 1627 KB
logo.png 1668 KB
問題一眼就看得出來。三張 1024×1024 以上的 PNG,但網站實際只顯示 240×240 或更小。
這就像下單買 1000 股,結果只成交 100 股,另外 900 股的錢全部白付。
修法用 Pillow 寫 10 行 Python:
from PIL import Image
img = Image.open('assets/portrait-pixel.png')
img.resize((480, 480), Image.LANCZOS).save(
'assets/portrait-pixel.webp',
format='WEBP', quality=85, method=6
)
結果:
- portrait-pixel: 1907 KB → 56 KB(-97%)
- mascot: 1627 KB → 8 KB(-99.5%)
- 首頁總圖片載入: 約 3.5 MB → 約 64 KB
順手做了三件事讓 hero 圖更早顯示:
- <picture> 包 WebP source + PNG fallback(舊瀏覽器仍可用)
- Hero img 加 fetchpriority='high' + decoding='async'
- 首頁 <head> 加 <link rel='preload'> 提前下載
再跑一次。效能 67 變成 78,LCP 從 19.8 秒降到 2.3 秒,亮綠燈了。
但總分還是沒有過 90。
3. CLS 0.336 修不到 0.1 怎麼辦?(78 → 93)
圖片修完,下一個紅燈是 CLS(Cumulative Layout Shift)0.336。標準是 < 0.1。
CLS 就是「畫面亂跳指數」。頁面載入的時候東西還在動,使用者體驗會被扣分。
我這站有兩個地方在跳。
(1)Mascot 圖片屬性跟 CSS 對不起來
img 標籤寫的是 width=32 height=32,但 CSS 後面又寫 width:84px height:84px。
瀏覽器會先照 img 屬性畫一個 32×32 的位置,等 CSS 載入後再撐成 84×84,整列導覽跟著跳一下。
修法:把 img 屬性改成跟 CSS 一致的 84×84。順便重新產 168×168 的 mascot 給 retina 顯示用。
(2)Press Start 2P 字型用 swap 模式
我整站用 Press Start 2P 這個像素字體,從 Google Fonts 抓的。
預設模式是 font-display: swap,先用系統字體畫出來,等 web font 載完再換過去。
換的那一瞬間整個版面重排,因為像素字的寬度跟一般字差很多。CLS 就是這樣衝上去的。
修法很簡單,URL 一個字改掉:
// 改前
fonts.googleapis.com/css?family=Press+Start+2P&display=swap
// 改後
fonts.googleapis.com/css?family=Press+Start+2P&display=optional
optional 模式的意思是,給瀏覽器 100 毫秒去載字型,超過就一律改用備用字體,而且整次造訪都不再換回來。
所以第一次進來的人可能看到中文備用字體,第二次以後字型已經在快取裡,就會正常顯示。
代價是第一次的視覺體驗略差。但 CLS 直接歸零。
再跑一次。效能 78 變 93,CLS 從 0.336 掉到 0.05 以下。
三個主要指標全部亮綠燈。
4. 無障礙卡在 89 怎麼補到 100?(色彩對比)
效能 93 之後,唯一還沒過 90 的是無障礙,89 分。
Lighthouse 的無障礙檢測主要看三件事,色彩對比、語意化標籤、ARIA 屬性。
我的問題集中在色彩對比。網頁無障礙標準(WCAG AA)要求文字跟背景的對比度至少 4.5 比 1。寫一段 Python 算一下:
def luminance(hex_color):
# ...省略
return 0.2126*adj(r) + 0.7152*adj(g) + 0.0722*adj(b)
def ratio(c1, c2):
l1, l2 = luminance(c1), luminance(c2)
return (max(l1,l2)+0.05) / (min(l1,l2)+0.05)
結果發現我用的 --text-mute 顏色全部不及格:
| 情境 | 原色 | 對比度 | 新色 |
|---|---|---|---|
| 深色主題 mute 文字 | #6c757d | 3.29 ❌ | #9ba3ab |
| 淺色主題 mute 文字 | #868e96 | 3.13 ❌ | #666f76 |
| 白卡片上 mute 文字 | #6c757d | 4.45 ❌ | #666f76 |
改三個 hex 字串,重新 build。預期分數 89 → 95+,理論上沒其他問題就會直接到 100。
5. 最終戰績
| 指標 | 起點 | 終點 |
|---|---|---|
| 效能 | 67 ❌ | 93 ✅ |
| LCP | 19.8 秒 ❌ | 2.3 秒 ✅ |
| CLS | 0.336 ❌ | < 0.1 ✅ |
| 無障礙 | 89 | 95+ ✅ |
| SEO | 100 ✅ | 100 ✅ |
| 最佳做法 | 100 ✅ | 100 ✅ |
6. 我從這個過程學到什麼
三輪下來我最大的收穫,不是分數本身。是「先看數字、再修」這個流程。
第一次看到紅字,我會想「整個專案是不是要重寫」。第二次學會了問:
- Lighthouse 報告裡,LCP 元素是哪一個?
- CLS 是哪個元素在跳?
- 報告會直接告訴你,不用猜
這跟我做交易學到的東西一樣。不是看到價格往下就砍倉,是先讀數據,找出原因,再決定要不要動。
一次只動一個變因,動完看結果,再決定下一個。
7. PageSpeed 卡在 60-80,該按什麼順序修?(4 步驟 checklist)
如果你的網站 PageSpeed 也卡在 60-80,按這個順序走:
- 打開 assets 看圖片大小:超過 200KB 的全部壓縮。WebP 通常能壓掉 90%。
- Hero 圖(首頁第一眼看到的圖)加 fetchpriority='high' + <link rel='preload'>
- 用非系統字體?把 font-display 從 swap 改成 optional,CLS 直接歸零。
- 用 Lighthouse 報告裡的「待改善項目」逐項點開,每項都會告訴你修哪裡。
這個檢查清單我自己跑完,從 67 到 93 大概花 1.5 小時。包括寫 Pillow 腳本、查 font-display 文件、跑三次 PageSpeed 驗證。
8. 下一步
PageSpeed 跑完,網站大致算是「Google 看了會點頭」的狀態。
但這只是一張門票。真正的搜尋排名還要靠內容、內鏈、外部連結,還有長期穩定的累積。
白老鼠實驗下一篇 #3 會回到 GSC:經過一週後,sitemap 到底抓了沒、哪幾頁先進索引、第一個搜尋查詢長什麼樣。
效能這條線後來還有續集。三個月後同一個站又從 79 衝到 89,那次處理的是關鍵路徑跟阻塞渲染,寫在 #11 PageSpeed 79 → 89:阻塞渲染的關鍵路徑優化。
名詞解釋
- PageSpeed Insights
- Google 提供的免費網站速度體檢工具,輸入網址就給 0-100 分跟改善建議。本文的 67 → 93 講的就是這個分數。
- Lighthouse
- PageSpeed 背後的檢測引擎,Chrome 瀏覽器也內建。報告會逐項列出「哪裡慢、該修什麼」,照著修就好,不用猜。
- 最大內容繪製(LCP, Largest Contentful Paint)
- 頁面上「最大那塊內容」(通常是首圖或大標題)出現所需的秒數。Google 標準 ≤ 2.5 秒,本站曾經 19.8 秒。
- 累積版面位移(CLS, Cumulative Layout Shift)
- 畫面亂跳指數:載入過程版面移動越多、分數越高。標準 < 0.1,常見元兇是圖片沒寫尺寸跟字型替換。
- 互動回應(INP, Interaction to Next Paint)
- 從你點按鈕到畫面有反應的延遲毫秒數,標準 ≤ 200 毫秒。跟 LCP、CLS 合稱 Google 三大網站體驗指標(Core Web Vitals)。
- WebP
- Google 推的圖片格式,同樣畫質下檔案比 PNG / JPG 小很多 — 本文實測一張 1907 KB 的 PNG 壓成 56 KB,省 97%。
- 字型顯示策略(font-display)
- 告訴瀏覽器「網路字型還沒載好時怎麼辦」的 CSS 設定。swap = 先用備用字體再換(會跳版);optional = 100 毫秒內載不到就整次都用備用字體(不跳版)。
- 備用字體(fallback font)
- 指定字型載不到時,瀏覽器改用的替代字體。例如本站 pixel 字型載不到時,改用系統內建的微軟正黑體。
- 無障礙(accessibility)
- 讓視力不佳、不便操作的人也能順利使用網站的設計標準。WCAG AA 是國際標準的中間等級,要求文字與背景對比度 ≥ 4.5:1。
- 預載(preload)
- 在網頁開頭先宣告「這個檔案很重要,先下載」。把首圖設成預載,使用者第一眼的畫面就會更早出現。
- Pillow
- Python 程式語言的圖片處理工具庫,幾行程式就能批次縮圖、轉檔。本文壓圖的 10 行腳本就是用它。
看完這篇之前先確認:
- 想把 Lighthouse 紅燈調綠的個人站
- 不想花錢上 CDN / 付費圖床的人
- 願意一刀只改一個變因再測的人
- 已經 90 分以上的成熟站
- 主要靠付費廣告流量的電商
- 企業級站(需另一套 perf 架構)
相關閱讀
這篇背後的真實開發過程記錄在 Build Log。
搜尋標籤:pagespeed、lcp、cls、a11y。
本篇為個人學習與實驗紀錄。PageSpeed Insights 演算法持續變動,本文方法不保證在你的網站產生相同效果,請依自身網站狀況實驗驗證。本站不接 YMYL 高風險站、不做 PBN、不做品牌矩陣 SEO。
