Lighthouse 分數提高攻略 - Next.js
2025-04-221.08Front EndNextjsPerformanceReact
最近在開發公司日本官網,研究了一番 Lighthouse 提高分數的方法,因 Lighthouse 分數對網站品質的影響非常直接,不只工程師自己會參考,連顧客看到網站體驗好不好,來檢視公司產出的品質。它幾乎就是評估網站品質的最直觀量化依據之一。
其中 Lighthouse 的四大項目中,「效能(Performance)」是最難搞的一個。其他像是「無障礙(Accessibility)」、「最佳做法(Best Practices)」、「SEO」老實說都還算容易加分(至少可以照 checklist 改),但效能這塊,完全是另一回事。
先講無障礙、SEO、Best Practices(比較容易處理)
這三個項目其實照著工具或官方建議就蠻容易滿分 :
無障礙(Accessibility)
我是用 shadcn/ui 的元件庫,它天生就有考慮很多無障礙的東西,像是:
- 元件都有 - aria-*屬性
- Dialog、Popover 這類互動元件有正確的 focus 管理 
- 支援鍵盤操作 
不過還是有遇到一些地方要跟 UI 設計師協調,例如文字與背景對比不夠、hover 狀態太不明顯等,以這次開發為例,我們就有針對某些字體顏色做微調,這點真的得溝通協作才能搞好。
Best Practices
其實用 Next.js 的話大致上沒太大問題,很多安全性或結構上的東西框架都幫你處理好了,例如:
- 自動防範 path traversal 攻擊 
- 有內建的 Image 最佳化 
- 禁止 inline script 等等 
SEO
這邊要提醒的是:
- 每頁只能有一個 - h1(這個不少開發者都沒注意)
- h2~- h6標籤要順序遞增,不能亂跳,不要- h2接- h4這種
- meta 標籤該寫的要寫,像 - description、- og:image、- robots等等
接下來進入正題:效能(Performance)
這一項分數難拉的原因有幾個:
- 牽涉到使用者裝置、網路速度 
- 不是單靠設定可以解決,需要針對真實瀏覽體驗做細緻調整 
- 你可能在某個地方塞了一個字體、圖片或套件,整體分數就被拖垮 
以下是這次實戰中踩到的一些坑,還有具體怎麼優化:
一 、避免大量網路資源
這一項是我在 Lighthouse 最常看到被扣分的項目之一,因為它直接關係到首屏載入時間,下面幾個東西特別容易出事:
1. 字體
為了日文排版美觀,引用了 Google Fonts 裡幾個日文字體,結果 Lighthouse 一測直接大扣分。因為單是字體就佔了整體傳輸資源的 50~60%。


解法是這樣的:
- 若真的要用 Google Fonts,請只載入需要的字重和子集,不要整包。 
 → 我採用的是 Next.js 內建的- next/font/google,可以選擇只載你需要的部分。
- 更好的做法:自託管字體,只打包你要的部分,完全不經外部請求,穩又快。 
- 或乾脆改用系統字體 stack:日文可參考這個組合 → - "游ゴシック体", "Yu Gothic", "Hiragino Kaku Gothic ProN", sans-serif。
2. 首屏加載的圖片
因為公司官網本身圖片就偏多,如果一進頁面就全部載入,勢必影響這個項目評分。
解法:
- 使用 lazy load:不要一進來就載圖,讓瀏覽器「看到再載」。 
 Next.js 的- <Image>元件預設就已經有 lazy loading 功能,基本上拿來用就很夠用。
3. 第三方插件
像 reCAPTCHA 這類第三方服務,只是為了某一個功能(像是底部的聯絡我們表單),但它本身會引入一堆額外 JS,而且大多是同步載入,會嚴重拖累效能。
解法:
- 我自己封裝了一個 - useIntersectionObserver的 hook,搭配- ref去監聽表單區塊的出現時機;- 只有當使用者「真的滑到底部」看到表單時,才會動態載入 reCAPTCHA 的 script。 

二 、最大內容繪製元素(LCP)
LCP(Largest Contentful Paint)指的是「畫面中最主要的內容載入完成的時間」,通常是一張 Hero 圖或大的標題文字。
常見問題:
- Hero 圖是用 - <img src="...">而不是- <Image />
- 太大張沒壓縮,或直接塞了一張 4K 畫質的背景圖 
解法:
- Hero 圖建議用 Next.js 的 - <Image />並加上- priority,會幫我們做- preload
- 採用 mobile-first 的圖片策略,讓不同螢幕尺寸載入不同大小的圖片 
- 轉成 WebP 

三 、 DOM 結構不要太複雜
有時候 UI 太動態、太多巢狀層級會讓 DOM 太大,尤其是用了什麼無限列表、複雜的元件樹:
- DOM 元素總數盡量控制在幾千以內 
- 深層巢狀不要超過 10 層 
- 沒必要的 div、span,請勇敢刪掉(不要為了排版加一堆 wrapper) 
四 、減少無用的 CSS
過去使用大型 UI library(像 MUI、Ant Design)時,常常會引入一大堆你根本沒用到的 CSS,結果造成首屏載入 CSS 體積爆炸,Lighthouse 效能分數低落。
這次我選擇使用 shadcn,它的最大優點就是「你用什麼,就只引入什麼」。所有元件都是 base on Tailwind + Radix 的組合,不像 UI 庫會一次塞一包。
換句話說:
- 沒有多餘的樣式,載入快 
- 所有樣式都在你控制範圍內,要客製也方便 
- 不怕 purgeCSS 或 Tailwind 把你沒用到的 class 清不掉 
簡單來說,shadcn 的設計哲學很接近「按需載入」,比起傳統 UI 庫,在 Lighthouse 的 CSS audit 裡會輕鬆很多。

總結一下
效能優化真的是一場持久戰,不要指望一次搞定、一測就 100 分,因為每個專案都有不同的效能難關需要克服。
幾個我自己踩雷後得到的心得:
- Lighthouse 分數 ≠ 使用體驗,但它還是一個不錯的參考。像我們這次就靠它找到一些資源過重的問題。 
- 能省就省,字體、圖片、第三方腳本,全部都是能優化的地方。 
- 善用 Next.js 提供的好工具,像是: - <Image>幫你處理 lazy load + size 最佳化
- <Script strategy="lazyOnload">控制 script 加載時機
- dynamic()延遲載入非首要元件
- <Head>處理 meta / SEO 等設定
 
- 組件設計階段就考慮 accessibility、標籤結構,這真的很重要,等到開發完再補救,通常會很痛苦 
額外補充一些可考慮的手段:
- 頁面可以考慮用 SSG (Static Site Generation),讓內容先在 build 時就生成好,使用者打開網頁時不用等伺服器跑。 
- 圖片、自託管字體、甚至 JS lib 都可以考慮搭配 CDN 或 edge-based hosting,效果非常有感。 
- 可以搭配 VS Code 的 Import Cost 插件,幫你即時看到每個 import 進來的套件大小,在下載套件前,先考慮一番 
- 使用 - @next/bundle-analyzer檢查你的 bundle 裡面塞了什麼,是否不小心 import 整包 lodash 或 date-fns,或是引用了專案非必要的套件
效能優化的細節實在太多了,很難在一篇文章裡全部講完。以後有機會我會再慢慢分享。
希望這篇能讓你在優化的路上少走一些冤枉路,哪怕只是 Lighthouse 多拿個 10 分,也絕對值得!
 
參考