我是吳承學,做 SEO 二十年。速度這件事我看法很直接:使用者不會為了慢半拍的網站多等,搜尋引擎也把體驗指標納入排名考量。這篇不談玄的,就講三件對速度影響最大的事,怎麼減少與延後 JavaScript 和 CSS、怎麼把伺服器回應時間壓下來,以及這些調整最後如何反映在核心體驗指標與真實體感上。
1. 先看懂 JS 和 CSS 為什麼會拖慢你的頁面
很多人以為頁面慢是圖片太大,但在互動型網站上,臃腫的 JavaScript 往往才是主因。要優化之前,得先理解瀏覽器是怎麼被這些資源卡住的。
1.1 阻塞渲染的資源是什麼
瀏覽器解析 HTML 時,遇到沒有特別標記的 <script> 會停下來先下載並執行它,遇到 CSS 也要等樣式表下載完才能繼續繪製。這些會打斷繪製流程的資源,就是所謂阻塞渲染的資源。它們越多、越大,使用者盯著白畫面的時間就越長。
1.2 主執行緒被佔滿的代價
瀏覽器處理版面、繪製與使用者互動,靠的是同一條主執行緒。當一大包 JavaScript 在執行時,主執行緒被佔住,使用者這時點按鈕、捲頁面都得排隊等待。這種「畫面出來了卻按不動」的卡頓,是很多互動指標不理想的根源。
1.3 一張表看清各類資源的影響
| 資源類型 | 主要影響 | 優化方向 |
|---|---|---|
| 阻塞渲染的 JS | 延後首次繪製 | 加 defer 或 async、延後載入 |
| 大型 JS 套件 | 佔用主執行緒、拖慢互動 | 分割程式碼、移除未用的部分 |
| 阻塞渲染的 CSS | 延後首次繪製 | 抽出首屏關鍵樣式內嵌 |
| 第三方腳本 | 不可控的額外負擔 | 延後或改用非同步載入 |
2. 把 JavaScript 減量、延後、切開
處理 JavaScript 有三個方向,一是減少總量,二是延後非必要的執行,三是把大檔案切成需要時才載入的小塊。這三招搭配起來,效果最實在。
2.1 用 defer 與 async 解除阻塞
大部分的腳本並不需要在解析 HTML 的當下就執行。加上 defer,腳本會在背景下載、等 HTML 解析完才依序執行,不會打斷繪製;async 則是下載完就執行,適合彼此獨立、不依賴順序的腳本,例如分析工具。光是把主要腳本從阻塞改成 defer,首次繪製往往就能提早不少。
<script src="/js/app.js" defer></script>
<script src="/js/analytics.js" async></script>
2.2 移除用不到的程式碼
網站用久了,經常殘留早就停用的追蹤碼、被註解掉卻仍載入的舊套件、整包引入卻只用到一兩個功能的函式庫。這些都是白白增加的負擔。我稽核時一定會抓這類殘留。曾有個網站還掛著早已停止運作的舊版分析代碼,雖然被註解,仍在增加請求與解析成本,清掉之後乾淨不少。定期檢視載入了哪些資源、哪些其實沒被用到,是很值得養成的習慣。我通常會建議團隊在每次改版或季度檢視時,把瀏覽器開發者工具的網路面板打開,逐一看哪些檔案被載入、體積多大、實際用到多少,把那些「以前需要、現在早就沒用」的東西一併清掉。這種清理不會改變任何功能,卻能實實在在減輕每一次載入的負擔。
2.3 依需求切割與延後載入
不是每一段功能都要在頁面一開始就載入。像是彈窗、下方才出現的互動模組、非首屏的功能,可以等使用者真的需要、或捲動到附近時再載入。把首屏必要的程式碼跟其餘切開,讓一開始下載的量降到最低,首屏互動會明顯變輕快。
3. 讓 CSS 不再擋住第一眼畫面
CSS 雖然不像 JavaScript 那樣佔用執行緒,但它會阻擋首次繪製。使用者要等瀏覽器拿到樣式才看得到有樣子的畫面,所以 CSS 的載入策略同樣關鍵。
3.1 抽出首屏關鍵樣式
一個有效的做法,是把首屏(使用者一開始就看得到的區域)所需的關鍵樣式抽出來,直接內嵌在 HTML 的 <head> 裡,其餘完整樣式表則以非阻塞方式在後面載入。這樣瀏覽器拿到 HTML 幾乎就能立刻畫出有樣式的首屏,不必空等整份樣式表。
3.2 清掉沒在用的樣式
許多網站直接引入整套前端框架的樣式表,但實際只用到其中一小部分。多出來的規則不只增加檔案大小,也拉長瀏覽器解析的時間。我建議定期用工具找出頁面實際沒用到的 CSS,該精簡就精簡。維持樣式表精瘦,對每一次載入都有幫助。我的經驗是,網站經過幾輪改版後,樣式表裡往往堆積了對應到早已刪除區塊的舊規則,這些死掉的樣式沒人敢動、也沒人記得,就一直留著。趁改版時做一次盤點,把確定不再使用的樣式移除,長期下來樣式表不會無止盡膨脹,載入也更輕快。
3.3 減少字型與外部樣式的往返
除了自家的樣式表,網頁字型與外部載入的樣式檔也常是被忽略的阻礙。載入太多種字重、字型檔案又大,會延後文字正確顯示的時間;從外部網域拉樣式,則多了一次連線與往返的成本。我會建議只保留真正用到的字重、盡量使用效率較好的字型格式,並讓文字在字型載入期間先以系統字顯示,避免使用者盯著一片空白等字出現。這些細節單獨看不起眼,累積起來對首屏的呈現速度影響不小。
4. 壓低 TTFB,並看它如何反映在體驗指標
前面談的是資源本身,這一段回到更前面的環節,伺服器要多久才吐出第一個位元組,也就是 TTFB。這個數字若一開始就慢,後面再怎麼優化,起跑點都輸人一截。
4.1 TTFB 慢通常卡在哪
伺服器回應慢,常見原因包括後端運算太重、資料庫查詢沒有最佳化、每次請求都即時運算而沒有快取、主機所在位置離使用者太遠。我看過一些網站每一次請求都重新跑完整套邏輯生成頁面,明明內容不常變動,卻不做任何快取,TTFB 自然居高不下。
4.2 快取與內容傳遞是兩帖良藥
對不常變動的頁面,導入伺服器端快取或改用預先產生好靜態頁的方式,能讓伺服器省下重複運算,回應快很多。搭配內容傳遞網路把靜態資源放到離使用者較近的節點,也能縮短傳輸距離。這兩件事處理好,TTFB 通常有相當程度的改善。下表整理常見成因與對應手段:
| TTFB 偏慢的成因 | 對應做法 |
|---|---|
| 每次請求即時運算 | 導入伺服器端快取或預先產生靜態頁 |
| 資料庫查詢緩慢 | 優化查詢、建立適當索引 |
| 主機距使用者遠 | 透過內容傳遞網路就近提供資源 |
| 後端邏輯過重 | 精簡流程、非必要運算移到背景 |
4.3 這些調整最後對應到哪些指標
把上面幾件事做好,會直接反映在核心體驗指標上。抽出關鍵 CSS、把主要腳本改成延後執行,能讓最大內容元素更早出現,也就是最大內容繪製時間變短。減少主執行緒被大包 JavaScript 佔用,使用者互動的回應會更即時,互動延遲指標跟著改善。而穩定的版面配置、不因資源晚到而位移,則對應到版面位移的分數。TTFB 壓低則像是替所有後續指標爭取到更早的起跑點。這些數字背後,其實就是使用者「打開就看得到、想按就按得動」的真實體感,這也是我一直認為速度優化最值得投入的原因。
5. 常見問題
defer 和 async 到底該用哪一個
如果腳本之間有執行順序的依賴、或需要等 HTML 解析完再跑,用 defer;如果腳本完全獨立、誰先誰後都沒差,例如第三方分析工具,用 async。多數網站的主要腳本用 defer 會比較安全。
把所有 CSS 都內嵌進 HTML 是不是更快
不建議全部內嵌。只把首屏關鍵樣式內嵌就好,其餘樣式表非阻塞載入。若把整份龐大的樣式表都塞進 HTML,會讓 HTML 本身變得笨重,反而拖慢首個位元組與解析。
TTFB 多少才算好
沒有適用所有情況的單一數字,會受主機、地區、頁面性質影響。與其追某個絕對值,我更建議跟自己過去的表現與同類頁面比較,看調整快取與後端之後是否穩定下降。方向對了比死守一個門檻實際。
用了很多第三方腳本,速度就一定救不回來嗎
不會完全沒救。可以把第三方腳本改成非同步或延後載入,評估哪些是真的必要、哪些可以移除,並留意它們對主執行緒的佔用。減量加上延後,通常能把影響壓到可接受的範圍。
減少 JavaScript 會不會影響網站功能
只要做法正確就不會。重點是移除確實沒被使用的程式碼、延後非首屏必要的功能,而不是砍掉正在用的邏輯。切割與延後載入的目的是讓功能在需要時才出現,體驗反而更順。
這些優化做完,排名會馬上上升嗎
速度是眾多排名考量之一,改善體驗指標有幫助,但排名還受內容品質、連結、競爭程度等因素影響。我會把速度優化看成改善使用者體驗與降低跳出的基本功,成效通常是逐步累積,而非一夜見效。
