網路請求的一生:從輸入 URL 到頁面渲染
當你在瀏覽器的網址列輸入 https://example.com 並按下 Enter,看似簡單的動作背後,其實經歷了一連串精密的步驟。理解這個完整的流程,是掌握 HTTP 協定的第一步,也是最重要的一步。
本篇將帶你走過一個網路請求的「一生」,從 DNS 查詢到頁面渲染,讓你對整個過程有完整的認識。
一、 旅程總覽
在深入每個步驟之前,讓我們先看看完整的流程圖:
這個流程可以分為六大階段:
- URL 解析:瀏覽器解讀你輸入的網址
- DNS 查詢:將域名轉換為 IP 位址
- TCP 連線:與伺服器建立穩定的連線通道
- TLS 握手:建立加密的安全連線(HTTPS)
- HTTP 交換:發送請求、接收回應
- 頁面渲染:將收到的資料轉換為你看到的網頁
接下來,我們將深入每個階段。
二、 第一站:URL 解析
什麼是 URL?
URL(Uniform Resource Locator)是網路資源的「地址」。當你輸入 https://www.example.com:443/path/page?name=value#section 時,瀏覽器會將其拆解為以下組成部分:
https://www.example.com:443/path/page?name=value#section
│ │ │ │ │ │
│ │ │ │ │ └─ Fragment(片段)
│ │ │ │ └─ Query String(查詢參數)
│ │ │ └─ Path(路徑)
│ │ └─ Port(埠號)
│ └─ Host(主機名稱)
└─ Scheme(協定)| 組件 | 說明 | 範例 |
|---|---|---|
| Scheme | 協定類型 | https、http、ftp |
| Host | 伺服器位址 | www.example.com |
| Port | 埠號(可省略) | 443(HTTPS 預設)、80(HTTP 預設) |
| Path | 資源路徑 | /path/page |
| Query | 查詢參數 | ?name=value |
| Fragment | 頁面錨點 | #section |
TIP
關於 URI、URL 與 URN 的詳細定義差異與網址結構解剖,可以參考:URI/URL/URN 完全指南:網位址的結構與奧秘。
瀏覽器的預處理:在發出請求之前
當網址被解析完成後,瀏覽器並不會立刻衝向伺服器,而是會先執行一套「內部檢查」,以確保安全性並節省不必要的網路資源消耗。
1. HSTS 檢查:強迫加密通信
HSTS (HTTP Strict Transport Security) 是一種安全機制,告訴瀏覽器:「這個網站只能透過 HTTPS 訪問。」
- 為什麼需要? 避免 SSL Strip (釣魚攻擊)。如果使用者手動輸入
http://,瀏覽器會查看內部的 HSTS 清單(如內建的 Preload List 或之前的快取)。 - 結果:如果命中,瀏覽器會直接發動 307 Internal Redirect。這是一個在瀏覽器內部發生的轉向,完全沒有網路流量出去,直接將請求升級為
https://。
TIP
關於 SSL Strip 的詳細運作原理與攻擊過程,可以參考這篇專題:深入淺出 SSL Strip:強行剝離加密層的中間人攻擊。
2. 快取檢查:省下網路頻寬
瀏覽器會先看「我之前有沒有存過這項資源?」。它會檢查 Disk Cache 或 Memory Cache 中的內容。
- 強快取判斷:瀏覽器會解析
Cache-Control或ExpiresHeader。- 命中 (Cache Hit):狀態碼顯示
200 OK (from disk cache)。不會發生任何網路存取,速度極快。 - 未命中:才進入下一步「DNS 查詢」。
- 命中 (Cache Hit):狀態碼顯示
TIP
「完美的請求,就是不發出請求。」 透過 HSTS 與快取檢查,瀏覽器在與外界溝通前就排除了大量安全隱患與頻寬浪費。
三、 第二站:DNS 查詢
為什麼需要 DNS?
電腦之間的通訊使用 IP 位址(如 93.184.216.34),但人類更容易記住域名(如 example.com)。DNS(Domain Name System)就是將域名轉換為 IP 位址的「電話簿」。
DNS 查詢的層級
DNS 查詢是一個逐層查找的過程,瀏覽器會按照以下順序尋找:
各層快取說明
| 層級 | 位置 | TTL(存活時間) |
|---|---|---|
| 瀏覽器快取 | Chrome/Firefox 內部 | 通常 1 分鐘 |
| 作業系統快取 | 系統層級 | 依 DNS 記錄設定 |
| 路由器快取 | 家用/公司路由器 | 依設定而異 |
| ISP DNS | 網路服務商 | 依 DNS 記錄設定 |
DNS 記錄類型
DNS 不只回傳 IP 位址,它支援多種記錄類型:
| 記錄類型 | 用途 | 範例 |
|---|---|---|
| A | IPv4 位址 | 93.184.216.34 |
| AAAA | IPv6 位址 | 2606:2800:220:1:... |
| CNAME | 別名指向 | www.example.com → example.com |
| MX | 郵件伺服器 | mail.example.com |
| TXT | 文字資訊 | 用於 SPF、DKIM 驗證 |
| NS | 域名伺服器 | 指定管理該域名的 DNS |
> **冷知識**:為什麼 IPv6 的記錄叫 `AAAA` 而不是 `A6`?這是工程師式的幽默——IPv4 地址長度是 32 bits,IPv6 是 128 bits,剛好是 4 倍(128 ÷ 32 = 4),所以就把 A 寫了四次!
實際觀察 DNS 查詢
你可以使用命令列工具來觀察 DNS 查詢:
# macOS / Linux
nslookup example.com
# 或使用 dig 獲得更詳細資訊
dig example.com
# 查詢特定記錄類型
dig example.com AAAA輸出範例:
;; ANSWER SECTION:
example.com. 86400 IN A 93.184.216.34這表示 example.com 的 A 記錄指向 93.184.216.34,TTL 為 86400 秒(24 小時)。
四、 第三站:TCP 連線
為什麼是 TCP?
HTTP 建立在 TCP(Transmission Control Protocol)之上。TCP 提供:
- 可靠傳輸:確保資料完整送達,遺失會重傳
- 有序傳輸:資料按順序到達
- 流量控制:避免發送方壓垮接收方
三向交握(Three-Way Handshake)
在發送任何 HTTP 資料之前,瀏覽器必須先與伺服器建立 TCP 連線。這個過程稱為「三向交握」:
TIP
關於 TCP 協定 的詳細機制、三向交握的深層意義以及如何優雅斷開連線,可以參考:深入淺出 TCP 協定:網路傳輸的可靠基石。
各步驟詳解
| 步驟 | 發送方 | 內容 | 意義 |
|---|---|---|---|
| 1. SYN | 客戶端 | seq=x | 請求建立連線,同步序列號 |
| 2. SYN-ACK | 伺服器 | seq=y, ack=x+1 | 同意連線,確認收到 SYN |
| 3. ACK | 客戶端 | ack=y+1 | 確認收到伺服器的 SYN-ACK |
TCP 封包結構(簡化)
┌─────────────────────────────────────────────────────┐
│ 來源埠 (16 bits) │ 目的埠 (16 bits) │
├─────────────────────────────────────────────────────┤
│ 序列號 Sequence Number (32 bits) │
├─────────────────────────────────────────────────────┤
│ 確認號 Acknowledgment Number (32 bits) │
├─────────────────────────────────────────────────────┤
│ 標誌位:SYN ACK FIN RST PSH URG │ 視窗大小 │
├─────────────────────────────────────────────────────┤
│ 資料 (Payload) │
└─────────────────────────────────────────────────────┘IMPORTANT
三向交握需要一個 RTT(Round-Trip Time,往返時間)。如果 RTT 是 50ms,光是建立 TCP 連線就需要至少 50ms。這就是為什麼 HTTP/2 和 HTTP/3 都致力於減少連線建立的開銷。
五、 第四站:TLS 握手
為什麼需要 TLS?
HTTP 是明文傳輸,任何中間節點(路由器、WiFi 熱點)都可以偷看或竄改內容。TLS(Transport Layer Security)為 HTTP 加上一層加密保護,形成 HTTPS。
NOTE
很多人會把加密稱為 SSL,但其實 SSL 是 TLS 的前身且已經過時。關於這兩者的歷史糾葛與命名由來,可以參考:SSL 與 TLS 的恩怨情仇:為什麼我們還在說 SSL?。
TLS 提供三大保障:
- 加密:資料被加密,中間人無法讀取
- 完整性:資料無法被竄改
- 身份驗證:確認伺服器的真實身份
TLS 握手流程
TIP
關於 TLS 協定 的運作細節、憑證驗證機制以及 TLS 1.3 的加速革命,可以參考:深入淺出 TLS 協定:保護網路通訊的安全鎖。
TLS 1.2 vs TLS 1.3
TLS 1.3 大幅簡化了握手流程:
| 特性 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 握手往返次數 | 2 RTT | 1 RTT |
| 0-RTT 支援 | ❌ | ✅(重連時) |
| 廢棄的不安全算法 | 仍支援 | 已移除 |
| 握手加密 | 部分明文 | 完全加密 |
TIP
可以使用 openssl s_client -connect example.com:443 來查看網站使用的 TLS 版本和加密套件。
六、 第五站:HTTP 請求與回應
終於到了主角登場的時刻!在 TCP 連線建立(如果是 HTTPS,還要完成 TLS 握手)之後,瀏覽器就可以發送 HTTP 請求了。
HTTP 請求結構
一個標準的 HTTP 請求由三部分組成:
GET /index.html HTTP/1.1 ← 請求行(Request Line)
Host: www.example.com ← 請求頭(Headers)
User-Agent: Mozilla/5.0 ...
Accept: text/html
Accept-Language: zh-TW
Accept-Encoding: gzip, deflate
Connection: keep-alive
← 空行
← 請求體(Body,GET 通常沒有)請求行組成
GET /index.html HTTP/1.1
│ │ │
│ │ └─ HTTP 版本
│ └─ 請求路徑(URI)
└─ 請求方法(Method)HTTP 回應結構
伺服器處理請求後,回傳 HTTP 回應:
HTTP/1.1 200 OK ← 狀態行(Status Line)
Date: Wed, 08 Jan 2025 10:00:00 GMT ← 回應頭(Headers)
Content-Type: text/html; charset=UTF-8
Content-Length: 1256
Cache-Control: max-age=3600
← 空行
<!DOCTYPE html> ← 回應體(Body)
<html>
<head>...</head>
<body>...</body>
</html>狀態碼分類
| 範圍 | 類別 | 說明 |
|---|---|---|
| 1xx | 資訊 | 請求已接收,繼續處理 |
| 2xx | 成功 | 請求成功處理 |
| 3xx | 重導向 | 需要進一步操作 |
| 4xx | 客戶端錯誤 | 請求有誤 |
| 5xx | 伺服器錯誤 | 伺服器處理失敗 |
TIP
這些概念在後續文章會有更深入的探討。本篇的重點是讓你先對整體流程有個完整的認識。
七、 第六站:頁面渲染
當瀏覽器收到 HTML 回應後,渲染之旅才正式開始:
渲染流程詳解
| 階段 | 說明 |
|---|---|
| 解析 HTML | 將 HTML 轉換為 DOM(Document Object Model)樹 |
| 解析 CSS | 將 CSS 轉換為 CSSOM(CSS Object Model)樹 |
| 建構 Render Tree | 結合 DOM 和 CSSOM,決定哪些元素要顯示 |
| Layout | 計算每個元素的位置和大小 |
| Paint | 繪製像素到各個圖層 |
| Composite | 將多個圖層合成最終畫面 |
阻塞渲染的資源
並非所有資源都能平行載入,有些會阻塞渲染:
| 資源類型 | 阻塞行為 |
|---|---|
| CSS | 阻塞渲染(必須等 CSSOM 建構完成) |
| JavaScript | 阻塞 DOM 解析(除非加上 async 或 defer) |
| 圖片 | 不阻塞渲染,但可能造成重新布局 |
| 字體 | 可能造成 FOIT(Flash of Invisible Text) |
八、 完整時間線
讓我們把所有階段放在一起,看看一個請求的完整時間線:
時間 →
│
├── DNS Lookup ──────────┤ (20-200ms)
│ │
├── TCP Handshake ───────┤ (1 RTT, ~50ms)
│ │
├── TLS Handshake ───────┤ (1-2 RTT, ~100ms)
│ │
├── HTTP Request ────────┤ (發送時間,通常很短)
│ │
├── Server Processing ───┤ (視後端複雜度)
│ │
├── HTTP Response ───────┤ (視回應大小)
│ │
├── Content Download ────┤ (視內容大小和頻寬)
│ │
└── Rendering ───────────┘ (視頁面複雜度)在 Chrome DevTools 的 Network 面板中,你可以看到這些階段的詳細時間:
| Timing 名稱 | 對應階段 |
|---|---|
| Queueing | 請求排隊 |
| Stalled | 等待可用連線 |
| DNS Lookup | DNS 查詢 |
| Initial connection | TCP 握手 |
| SSL | TLS 握手 |
| Request sent | 發送請求 |
| Waiting (TTFB) | 等待首位元組 |
| Content Download | 下載內容 |
總結
一個看似簡單的網路請求,實際上經歷了六大階段:
| 階段 | 關鍵技術 | 耗時影響因素 |
|---|---|---|
| URL 解析 | URI 規範 | 幾乎不耗時 |
| DNS 查詢 | DNS 協定 | 快取命中率、DNS 伺服器距離 |
| TCP 連線 | TCP 三向交握 | 網路延遲(RTT) |
| TLS 握手 | TLS 1.2/1.3 | TLS 版本、是否重用 Session |
| HTTP 交換 | HTTP 協定 | 請求/回應大小、伺服器處理時間 |
| 頁面渲染 | DOM/CSSOM | 頁面複雜度、資源數量 |
理解這個完整流程後,你會更清楚:
- 為什麼 CDN 能加速網站(減少 RTT)
- 為什麼 HTTP/2 比 HTTP/1.1 快(多路複用)
- 為什麼 TLS 1.3 成為新標準(減少握手次數)
- 為什麼 快取策略 如此重要(跳過大量步驟)
進階挑戰
實作挑戰:使用 Chrome DevTools 的 Network 面板,觀察你常用網站的請求時間線。找出 DNS Lookup、TCP 連線、TLS 握手各花了多少時間。
深度思考:為什麼在行動網路(4G/5G)上,網頁載入速度往往比有線網路慢?除了頻寬因素,還有什麼原因?(提示:RTT 與連線建立成本)
探索實驗:使用
curl -v https://example.com命令,觀察完整的連線過程。找出 TLS 握手的詳細資訊。
延伸閱讀與資源
- Google Web Fundamentals:Critical Rendering Path
- MDN Web Docs:How the Web works
- High Performance Browser Networking:Primer on Web Performance