
high-perf-browser
熱門透過網路協定、資源載入與瀏覽器渲染機制來優化網頁效能。當使用者提到「我的網站很慢」、「Core Web Vitals」、「HTTP/2 或 HTTP/3」、「資源提示」、「網路延遲」、「渲染阻塞」、「TCP/TLS 優化」、「Service Worker」、「Cache-Control 或快取策略」或「關鍵渲染路徑」時使用。也適用於診斷頁面載入緩慢、優化第一個位元組時間(TTFB)、在 WebSocket 與 SSE 之間做選擇,或減少 bundle 大小。若需 UI 視覺效能,請參考 refactoring-ui。若需字型載入,請參考 web-typography。
透過網路協定、資源載入與瀏覽器渲染機制來優化網頁效能。當使用者提到「我的網站很慢」、「Core Web Vitals」、「HTTP/2 或 HTTP/3」、「資源提示」、「網路延遲」、「渲染阻塞」、「TCP/TLS 優化」、「Service Worker」、「Cache-Control 或快取策略」或「關鍵渲染路徑」時使用。也適用於診斷頁面載入緩慢、優化第一個位元組時間(TTFB)、在 WebSocket 與 SSE 之間做選擇,或減少 bundle 大小。若需 UI 視覺效能,請參考 refactoring-ui。若需字型載入,請參考 web-typography。
高效能瀏覽器網路框架
一套系統化的網頁效能方法,奠基於瀏覽器、協定與網路的實際運作方式。在建構前端應用程式、設定效能預算、配置伺服器或診斷頁面載入緩慢時,應用這些原則。
核心原則
瓶頸是延遲,而非頻寬。 大多數網頁效能問題源自過多的往返次數,而非吞吐量不足。頻寬增加 5 倍帶來的效益遞減;延遲減少 5 倍則能徹底改變使用者體驗。
基礎: 每個請求在內容的第一個位元組送達前,都必須經過 DNS 解析、TCP 握手、TLS 協商與 HTTP 交換——每一步都增加往返延遲。高效能應用程式會最小化往返次數、平行化請求,並消除不必要的網路跳躍。理解協定堆疊是進行有意義優化的先決條件。
評分
目標:10/10。 根據八項快速診斷問題中有幾項通過來評分,並以現場指標加權:9-10 = 全部八項通過(四項現場指標行在綠區,加上內容雜湊、HTTP/2+、最小化渲染阻塞與壓縮);5-6 = 四項現場指標行通過,但一項或多項傳輸/快取/壓縮行未通過;<=3 = 任一項現場指標行在紅區。務必回報分數、哪些診斷項目未通過,以及每項的具體修正方式。
高效能瀏覽器網路框架
六個領域,用於建構快速且具韌性的網頁應用程式:
1. 網路基礎
核心概念: 每個 HTTP 請求都需支付延遲稅——DNS 查詢、TCP 三向握手、TLS 協商——之後應用程式資料才會開始流動。減少或消除這些往返次數是效益最高的單一優化手段。
為何有效: 光速有限:紐約到倫敦的封包單程約需 28 毫秒,與頻寬無關。這些物理層級的限制無法靠更大的管道解決——只能靠更少的往返次數。
關鍵見解:
- TCP 三向握手在資料傳輸開始前增加一個完整的 RTT
- TCP 慢啟動在第一個往返次數中將初始吞吐量限制在約 14KB(10 個區段)——將關鍵資源維持在此閾值以下
- 升級至 TLS 1.3:將 TLS 1.2 的握手往返次數減半,並為回訪使用者啟用 0-RTT 恢復
- TCP 的隊頭阻塞(Head-of-line blocking)意味著一個遺失的封包會阻塞該連線上的所有串流
- 頻寬延遲乘積(BDP)限制在途資料量;高延遲鏈路會使頻寬利用率不足
程式碼應用:
| 情境 | 模式 | 範例 |
|---|---|---|
| 連線預熱 | 預先建立與關鍵來源的連線 | <link rel="preconnect" href="https://cdn.example.com"> |
| DNS 預取 | 提早解析第三方網域(節省 20-120 毫秒) | <link rel="dns-prefetch" href="https://analytics.example.com"> |
| TLS 優化 | TLS 1.3 + 工作階段恢復 | ssl_protocols TLSv1.3; 搭配 session tickets |
| 連線重用 | Keep-alive 避免重複握手 | Connection: keep-alive(HTTP/1.1+ 預設) |
詳見 references/network-fundamentals.md 以調整伺服器或診斷握手延遲——包含完整的 TLS 1.2 與 1.3 RTT 推導、慢啟動加倍表、initcwnd/BDP 計算、OCSP-stapling Nginx 配置以及 DNS 快取階層。
2. HTTP 協定演進
核心概念: HTTP 從簡單的請求-回應協定演進為多工的二進位系統。選擇正確的協定版本並妥善配置,能消除整類效能問題。
為何有效: HTTP/1.1 因無法多工而迫使開發者使用變通方法(域名分片、精靈圖、合併檔案)。HTTP/2 實現多工,但繼承了 TCP 的隊頭阻塞;HTTP/3(基於 UDP 的 QUIC)則消除了它。每一代都移除一個瓶頸——並使前一代的變通方法變得適得其反。
關鍵見解:
- HTTP/1.1 每條 TCP 連線只允許一個未完成的請求;瀏覽器為每個主機開啟 6 條連線作為變通
- HTTP/2 在一條連線上多工無限串流——域名分片反而適得其反
- HTTP/2 的 HPACK 標頭壓縮可減少 85-95% 的重複標頭開銷
- HTTP/3(QUIC)消除 TCP 隊頭阻塞,並啟用 0-RTT 恢復與連線遷移
- 偏好
103 Early Hints而非 HTTP/2 Server Push(後者容易過度推送且已被廣泛棄用) - 連線合併(Connection coalescing)讓一條 HTTP/2 連線可服務多個共用憑證的主機名稱
程式碼應用:
| 情境 | 模式 | 範例 |
|---|---|---|
| HTTP/2 遷移 | 移除 HTTP/1.1 的變通方法 | 取消域名分片、精靈圖、檔案合併 |
| 103 Early Hints | 在完整回應前發送預載提示 | 103 搭配 Link: </style.css>; rel=preload |
| QUIC/HTTP/3 | 在 CDN 或來源伺服器上宣告 HTTP/3 | Alt-Svc: h3=":443" 標頭 |
| 串流優先順序 | 標示資源重要性 | CSS 與字型最高優先;圖片較低 |
詳見 references/http-protocols.md 以選擇或遷移協定版本——包含 HTTP/1.1、2、3 的並排比較、逐步取消分片的遷移指南,以及為何 Server Push 輸給 103 Early Hints。
3. 資源載入與關鍵渲染路徑
核心概念: 瀏覽器必須先建立 DOM、CSSOM 與渲染樹,才能繪製像素:HTML → DOM → CSSOM → Render Tree → Layout → Paint → Composite。任何阻塞此管線的資源都會延遲首次繪製。
為何有效: CSS 會阻塞渲染(CSSOM 準備好之前無法繪製),而 JavaScript 會阻塞解析器(<script> 會暫停 DOM 建構直到下載並執行完畢)——因此兩者需要不同的優化策略。每個阻塞資源都會直接增加首次繪製時間的延遲。
關鍵見解:
async平行下載並立即執行(用於獨立腳本);defer平行下載但於 DOM 解析後執行(用於大多數腳本)<link rel="preload">以高優先順序立即擷取關鍵資源;rel="prefetch"以低優先順序擷取可能的下個導航資源- 內聯首屏 CSS 並非同步載入其餘部分,以消除阻塞渲染的 CSS 請求
- 字型可能阻塞文字渲染長達 3 秒——使用
font-display: swap
程式碼應用:
| 情境 | 模式 | 範例 |
|---|---|---|
| 關鍵 CSS | 在 <head> 中內聯首屏樣式 |
<style>/* critical */</style> + 非同步完整 CSS |
| 腳本載入 | 預設使用 defer;獨立腳本用 async |
<script src="app.js" defer></script> |
| 資源提示 | 預載關鍵字型、英雄圖片 | <link rel="preload" href="font.woff2" as="font" crossorigin> |
| 圖片優化 | 懶加載折疊以下圖片;使用現代格式 | <img loading="lazy" src="photo.avif" srcset="..."> |
詳見 references/resource-loading.md 以縮短首次繪製時間——包含精確的 async/defer/module 執行順序、完整的資源提示決策樹,以及圖片與字型(font-display、srcset、AVIF)的操作手冊。
4. 快取策略
核心概念: 最快的網路請求是從未發生的請求。分層快取——瀏覽器記憶體、磁碟、Service Worker、CDN、來源伺服器——為回訪使用者消除往返次數。
為何有效: Cache-Control 標頭告訴瀏覽器與中介伺服器回應的有效期限;內容雜湊 URL 讓積極的不可變快取變得安全。每次快取命中都消除一次完整的網路往返。
關鍵見解:
Cache-Control: no-cache仍會快取但每次重新驗證;no-store永不快取——不要混淆ETag/Last-Modified啟用條件式請求(304 Not Modified),跳過主體傳輸- Service Worker 提供可程式化的快取層,可離線運作(快取優先的 shell,網路優先的動態內容)
- 配置錯誤的
Vary標頭會導致 CDN 快取污染——對錯誤的客戶端提供錯誤的編碼或格式
程式碼應用:
| 情境 | 模式 | 範例 |
|---|---|---|
| 靜態資源 | 不可變快取 + 雜湊版本 | style.a1b2c3.css 搭配 Cache-Control: max-age=31536000, immutable |
| HTML 文件 | 每次請求重新驗證 | Cache-Control: no-cache 搭配 ETag |
| API 回應 | 短 TTL + 背景重新整理 | Cache-Control: max-age=60, stale-while-revalidate=3600 |
| CDN 配置 | 在邊緣快取並設定正確的 Vary | Vary: Accept-Encoding, Accept |
詳見 references/caching-strategies.md 以設計快取策略——包含完整的瀏覽器/SW/CDN/來源階層、可複製貼上的 Service Worker 快取優先與網路優先範本,以及會污染 CDN 的 Vary 陷阱。
5. Core Web Vitals 優化
核心概念: Core Web Vitals——LCP、INP、CLS——是 Google 以使用者為中心的指標,涵蓋載入、互動性與視覺穩定性。它們影響搜尋排名,並反映真實的使用者體驗。
為何有效: 如果英雄圖片仍然很晚載入(LCP)或主執行緒 JavaScript 阻塞互動(INP),那麼即使 TTFB 很快也毫無意義——因此伺服器端時間可能看起來是綠的,但使用者仍在等待。優化使用者感知的里程碑,而非位元組傳遞的時鐘。
關鍵見解(數值通過/失敗閾值位於快速診斷中):
- LCP——優化最大的可見元素(英雄圖片、標題區塊、影片海報)
- INP——保持主執行緒空閒;分解長任務,使每次互動(不僅是第一次)都能保持回應
- CLS——為動態內容在載入前預留空間
- TTFB 與 FCP(< 1.8 秒)是上游關卡:它們限制了所有下游里程碑,因此應優先修正
- 在生產環境中使用真實使用者監控(RUM)測量——實驗室/合成測試會遺漏真實裝置與網路變異
程式碼應用:
| 情境 | 模式 | 範例 |
|---|---|---|
| LCP | 預載 LCP 元素;提高其優先順序 | <img src="hero.webp" fetchpriority="high"> |
| INP | 分解長任務;讓出主執行緒 | scheduler.yield() 或 setTimeout 分塊 |
| CLS | 為非同步內容預留空間 | <img width="800" height="600"> 或 CSS aspect-ratio |
| 效能預算 | 當關鍵指標退化超過快速診斷閾值時,在 CI 中標記失敗 | Lighthouse CI 對 LCP/INP/CLS 的斷言 |
詳見 references/core-web-vitals.md 以處理紅區指標——包含每個指標的除錯工作流程(如何檢查不良的 LCP/INP/CLS)、實驗室與 RUM 工具對照表,以及每個指標的優化檢查清單。
6. 即時通訊
核心概念: 當資料需要持續流動時,傳輸方式的選擇——WebSocket、SSE 或長輪詢——決定了延遲、資源使用率與可擴展性。
為何有效: HTTP 的請求-回應模型為每次即時更新增加了開銷。WebSocket 提供全雙工通訊,框架僅約 2 位元組;SSE 透過純 HTTP 提供更簡單的伺服器到客戶端推送。根據資料流方向與頻率選擇傳輸方式,而非預設使用最強大的選項。
關鍵見解:
- WebSocket:雙向(聊天、遊戲、協作編輯);SSE:僅伺服器到客戶端,自動重新連線,對代理友善,更簡單
- 長輪詢僅作為備用方案——重複的 HTTP 請求開銷很高
- 每個 WebSocket 是一條獨立的 TCP 連線,繞過 HTTP/2 多工
- 發送心跳/ping 幀——行動網路會無聲地丟棄空閒連線
- 使用指數退避重新連線,並在斷線時佇列訊息
程式碼應用:
| 情境 | 模式 | 範例 |
|---|---|---|
| 聊天 / 協作 | WebSocket + 心跳 + 重新連線 | new WebSocket('wss://...') 每 30 秒 ping 一次 |
| 即時動態 / 通知 | SSE 用於伺服器到客戶端串流 | new EventSource('/api/updates') |
| 連線韌性 | 重新連線時使用指數退避 | 1 秒、2 秒、4 秒、8 秒……上限 30 秒 |
| 擴展 | WebSocket 伺服器後方的發布/訂閱中介 | Redis Pub/Sub 或 NATS |
詳見 references/real-time-communication.md 以建構即時功能——包含 WebSocket 連線/心跳/重新連線的生命週期、SSE 的 EventSource 模式,以及如何透過發布/訂閱中介擴展扇出。
常見錯誤
| 錯誤 | 為何失敗 | 修正方式 |
|---|---|---|
| 增加頻寬來解決頁面緩慢 | 瓶頸是延遲,而非吞吐量 | 減少往返次數:preconnect、快取、CDN |
| 一次載入所有 JavaScript | 阻塞解析器的腳本延遲繪製與互動性 | 程式碼分割;defer;懶加載非關鍵模組 |
| 沒有資源提示 | 瀏覽器太晚發現關鍵資源 | 為首屏關鍵資源使用 preconnect + preload |
缺少 Cache-Control / 到處使用 no-store |
每次訪問都重新下載所有內容 | 適當的 max-age + 內容雜湊 |
| 忽略 CLS | 版面位移破壞信任與排名 | 為圖片、嵌入內容、廣告設定明確尺寸 |
| 什麼都用 WebSocket | 當 SSE/輪詢就足夠時,不必要的複雜性 | 根據資料流選擇傳輸方式;伺服器推送用 SSE |
| 在 HTTP/2 上使用域名分片 | 破壞多工;增加額外 TCP 連線 | 合併來源;讓 HTTP/2 多工 |
| 沒有壓縮 | 文字資源以完整大小傳輸 | 在伺服器/CDN 上啟用 Brotli(優先)或 Gzip |
快速診斷
| 問題 | 若否 | 行動 |
|---|---|---|
| TTFB 是否低於 800 毫秒? | 伺服器或網路太慢 | CDN、伺服器快取、檢查後端 |
| LCP 是否低於 2.5 秒? | 最大元素載入太晚 | 預載 LCP 資源;fetchpriority="high" |
| INP 是否低於 200 毫秒? | 主執行緒被阻塞 | 分解長任務;延遲非關鍵 JS |
| CLS 是否低於 0.1? | 元素在渲染後位移 | 明確尺寸;預留空間 |
| 靜態資源是否經過內容雜湊並快取? | 回訪使用者重新下載 | 雜湊檔名 + Cache-Control: immutable |
| 是否啟用 HTTP/2 或 HTTP/3? | 沒有多工或標頭壓縮 | 在伺服器上啟用 HTTP/2;透過 CDN 啟用 HTTP/3 |
| 是否最小化渲染阻塞資源? | CSS 與同步 JS 延遲首次繪製 | 內聯關鍵 CSS;defer 腳本;修剪未使用的 CSS |
| 是否啟用壓縮(Brotli/Gzip)? | 未壓縮的文字傳輸 | 在伺服器/CDN 上啟用 Brotli;Gzip 備用 |
延伸閱讀
基於 Ilya Grigorik 關於瀏覽器網路與網頁效能的全面指南:
- "High Performance Browser Networking" by Ilya Grigorik(網路協定、瀏覽器內部機制與效能優化的完整參考)
- hpbn.co——作者維護的免費線上版本
關於作者
Ilya Grigorik 是一位網頁效能工程師,在 Google 工作超過十年,專注於 Chrome、網頁平台效能與 HTTP 標準,並共同主持 W3C 網頁效能工作小組。他的著作《High Performance Browser Networking》(O'Reilly, 2013)被廣泛認為是關於瀏覽器如何與網路互動的權威參考。



