Coolkid mascot CoolkidLab Build in Public. Level up together.

SEO 菜鳥成長史 · #2

閱讀

PageSpeed 效能 67 → 93:非工程師背景的三輪優化全紀錄

先講重點

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.8s 降到 2.3s、從 CLS 0.336 修到 0.05 以下。三輪、每輪只修一個東西。

1. 為什麼這篇值得寫

PageSpeed 的教學文章一抓一大把,但大部分都是「給工程師看的清單」:

我這種非工程師背景的看了只會更慌。實際上,對於一個普通靜態網站,90% 的問題集中在三件事:圖片太大、字型載得慢、版面在跳。把這三個處理完,分數就會從 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
)

結果:

順手做了三件事讓 hero 圖更早顯示:

  1. 包 WebP source + PNG fallback(舊瀏覽器仍可用)
  2. Hero img 加 fetchpriority='high' + decoding='async'
  3. 首頁 加 提前下載

再跑一次:效能 67 → 78,LCP 19.8s → 2.3s(綠燈)。但分數還沒過 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,整列 nav 跟著跳。

修法:把 img 屬性改成跟 CSS 一致的 84×84。順便重新產 168×168 的 mascot 給 retina 顯示用。

(2)Press Start 2P 字型用 swap 模式

我整站用 Press Start 2P 這個 pixel 字體(從 Google Fonts 抓)。預設是 font-display: swap:先用系統字體畫,等 web font 載入後再「換」過來。換的瞬間整個版面回流(pixel 字寬度跟一般字差很多),CLS 大爆炸。

修法很簡單,URL 一個字改掉:

// 改前
fonts.googleapis.com/css?family=Press+Start+2P&display=swap

// 改後
fonts.googleapis.com/css?family=Press+Start+2P&display=optional

optional 模式:給瀏覽器 100ms 載字型,超過就一律用 fallback,整次造訪都不換。第一次造訪可能看到中文 fallback 字體(Microsoft JhengHei),第二次以後字型已在快取會正常顯示。代價:第一次的視覺體驗略差。但 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 文字#6c757d3.29 ❌#9ba3ab
淺色主題 mute 文字#868e963.13 ❌#666f76
白卡片上 mute 文字#6c757d4.45 ❌#666f76

改三個 hex 字串,重新 build。預期分數 89 → 95+,理論上沒其他問題就會直接到 100。

5. 最終戰績

指標起點終點
效能67 ❌93 ✅
LCP19.8 秒 ❌2.3 秒 ✅
CLS0.336 ❌< 0.1 ✅
無障礙8995+ ✅
SEO100 ✅100 ✅
最佳做法100 ✅100 ✅

6. 我從這個過程學到什麼

三輪下來我最大的收穫,不是分數本身。是「先看數字、再修」這個流程。

第一次看到紅字,我會想「整個專案是不是要重寫」。第二次學會了問:

這跟我做交易學到的東西一樣:不是看到價格往下就砍倉,是先讀數據、找原因、再下手。一次只動一根線,動完看結果,再決定下一根。

7. PageSpeed 卡在 60-80,該按什麼順序修?(4 步驟 checklist)

如果你的網站 PageSpeed 也卡在 60-80,按這個順序走:

  1. 打開 assets 看圖片大小:超過 200KB 的全部壓縮。WebP 通常能壓掉 90%。
  2. Hero 圖(首頁第一眼看到的圖)加 fetchpriority='high' +
  3. 用非系統字體?把 font-display 從 swap 改成 optional,CLS 直接歸零。
  4. 用 Lighthouse 報告裡的「待改善項目」逐項點開,每項都會告訴你修哪裡。

這個檢查清單我自己跑完,從 67 到 93 大概花 1.5 小時。包括寫 Pillow 腳本、查 font-display 文件、跑三次 PageSpeed 驗證。

8. 下一步

PageSpeed 跑完,網站基本上算「Google 看了會點頭」的狀態了。但這只是門票。真正的搜尋排名還要靠:內容、內鏈、外部連結、長期穩定累積。

白老鼠實驗下一篇 #3 會回到 GSC:經過一週後,sitemap 到底抓了沒、哪幾頁先進索引、第一個搜尋查詢長什麼樣。

效能這條線後來還有續集:三個月後同一個站又從 79 衝到 89,那次處理的是 critical path 與 render-blocking,寫在 #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 架構)
最常踩
  • 只看 Lighthouse 分數忽略真實使用者體驗
  • 改完只測桌面忘記測手機
  • 壓圖片忘了檢查 LCP 元素本身

這篇是收斂後寫的版本。
我每兩週寄一封電子報,講「正在做但還沒寫成文章」的東西——
包含每月幫你過濾值得花時間的新 AI 工具,
以及 Lab 新文的個人版(你會比公開版早一週收到)。

→ 訂閱(雙週一封,第一封自動寄起步清單)

跳轉 Substack、隨時取消、不轉賣 email。

如果內容對你有用就太好了
隨喜斗內

Buy Me a Coffee at ko-fi.com
NEXT CHAPTER ▸ #0 GSC 是什麼?非工程師 5 分鐘看懂 Google Search Console

相關閱讀

這篇背後的真實開發過程記錄在 Build Log搜尋標籤:pagespeedlcpclsa11y

本篇為個人學習與實驗紀錄。PageSpeed Insights 演算法持續變動,本文方法不保證在你的網站產生相同效果,請依自身網站狀況實驗驗證。本站不接 YMYL 高風險站、不做 PBN、不做品牌矩陣 SEO。

← 回 SEO 菜鳥成長史

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