2026-02-03 19:41:14 +08:00
|
|
|
|
# 从 URL 到网页显示:一次网络"快递"之旅
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
<script setup>
|
|
|
|
|
|
import UrlToBrowserQuickStart from '../../.vitepress/theme/components/appendix/url-to-browser/UrlToBrowserQuickStart.vue'
|
|
|
|
|
|
</script>
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
> **学习指南**:本章节无需编程基础。我们将用**"网购"**的生活化比喻,配合**真实的技术过程**,带你一步步理解浏览器如何将一行网址变成丰富多彩的页面。
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 0. 引言:当你按下回车键的那一刻
|
|
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
想象你正在进行一次**网购**。你需要:
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
1. **填写订单**(选好商品,确认收货地址)
|
|
|
|
|
|
2. **系统查找仓库**(根据店铺名找到具体的发货仓库)
|
|
|
|
|
|
3. **建立物流通道**(确保仓库正常营业且能发货)
|
|
|
|
|
|
4. **仓库发货**(快递员把包裹送上门)
|
|
|
|
|
|
5. **拆箱体验**(打开包裹,看到心仪的商品)
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
**访问网页的过程和网购惊人地相似!**
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
当你在浏览器输入 `google.com` 并按下回车,你就是那个"买家",浏览器通过一系列操作,最终把远方服务器上的"商品"(网页内容)送到你的屏幕上。
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
<UrlToBrowserQuickStart />
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
## 1. 第一步:填写"订单" —— URL 解析
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
### 生活比喻:填写购物单
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
假设你只在订单上写"买鞋子",仓库肯定不知道发哪双。你需要写清楚:
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
- **店铺类型**(官方旗舰店/普通店)
|
|
|
|
|
|
- **店铺名称**(Nike 官方店)
|
|
|
|
|
|
- **商品位置**(男鞋区/跑鞋系列)
|
|
|
|
|
|
- **具体型号**(Air Max 90)
|
|
|
|
|
|
- **备注信息**(我要红色的)
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
### 真实过程:浏览器解析 URL
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
**URL(Uniform Resource Locator,统一资源定位符)**就是浏览器世界的"商品定位码"。当你在地址栏输入 `https://www.example.com:8080/path/page.html?id=123#section`,浏览器会立即拆解它:
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-02-14 12:14:07 +08:00
|
|
|
|
| URL 部分 | 示例值 | 网购类比 | 技术作用 |
|
|
|
|
|
|
| -------------------------- | -------------------- | -------------------------------------------------- | ------------------------------------------------------------------------ |
|
|
|
|
|
|
| **协议** `https://` | 安全超文本传输协议 | **物流方式**:保密配送(HTTPS)vs 普通配送(HTTP) | 决定使用什么规则通信。`http` 是普通传输,`https` 是加密传输 |
|
|
|
|
|
|
| **域名** `www.example.com` | 服务器的人类可读名字 | **店铺名称**:京东超市 | 告诉浏览器要找哪台服务器。域名是为了让人记住,最终要转换成 IP 地址 |
|
|
|
|
|
|
| **端口** `:8080` | 服务器的具体"门牌号" | **柜台编号**:3号柜台(默认不写) | 服务器上可能有多个服务,端口指定访问哪一个。HTTP 默认 80,HTTPS 默认 443 |
|
|
|
|
|
|
| **路径** `/path/page.html` | 服务器上的文件位置 | **货架位置**:日用品区/第三排 | 指定服务器上的具体资源位置 |
|
|
|
|
|
|
| **查询参数** `?id=123` | 附加信息 | **订单备注**:红色、XL码 | 传递给服务器的额外数据,如搜索关键词、页码等 |
|
|
|
|
|
|
| **锚点** `#section` | 页面内的位置 | **说明书页码**:翻到第5页 | 页面加载后自动滚动到指定位置,不发送给服务器 |
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
<UrlParserDemo />
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
> **关键理解**:URL 的存在是为了让**人类**能记住和输入。计算机最终需要的是 **IP 地址**(就像快递员最终需要的是具体的仓库地址,而不是"Nike 官方店"这个名字)。
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
## 2. 第二步:查"地址簿" —— DNS 查询
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
### 生活比喻:查仓库地址
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
你下单写的是"Nike 官方店",但物流系统不知道仓库在哪。它需要查地址簿:
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
1. 先查**常用地址**(最近买过这家吗)→ 浏览器缓存
|
|
|
|
|
|
2. 没有的话问**小区快递点**(他们知道大区域的分配)→ 本地 DNS 服务器
|
|
|
|
|
|
3. 问**总部调度中心**(知道.com类店铺归谁管)→ 根域名服务器
|
|
|
|
|
|
4. 问**品牌管理处**(最终找到 Nike 店铺的真实发货仓库)→ 权威域名服务器
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
### 真实过程:DNS 分层查询
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
**DNS(Domain Name System,域名系统)**是互联网的"分布式地址簿查询系统"。由于全球有数十亿个域名,采用分层架构来分散查询压力:
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
```
|
|
|
|
|
|
你(浏览器)
|
|
|
|
|
|
↓ 问:google.com 的 IP 是多少?
|
|
|
|
|
|
本地 DNS 服务器(你的网络运营商,如电信/联通)
|
|
|
|
|
|
↓ 问:.com 归谁管?
|
|
|
|
|
|
根域名服务器(全球13组根服务器,管理所有顶级域)
|
|
|
|
|
|
↓ 告诉:去问 .com 的管理者
|
|
|
|
|
|
顶级域服务器(Verisign 管理 .com)
|
|
|
|
|
|
↓ 告诉:去问 google.com 的管理者
|
|
|
|
|
|
权威域名服务器(Google 自己的 DNS 服务器)
|
|
|
|
|
|
↓ 告诉:google.com 的 IP 是 142.250.80.46
|
|
|
|
|
|
返回 IP 地址给浏览器
|
|
|
|
|
|
```
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
**查询类型说明:**
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
- **递归查询(Recursive Query)**:浏览器只发一次请求,本地 DNS 负责层层查询后返回结果
|
|
|
|
|
|
- **迭代查询(Iterative Query)**:每一层只告诉下一层去哪查,浏览器需要多次查询
|
|
|
|
|
|
- **缓存机制**:查询结果会被缓存,下次直接返回,大大加速访问
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
<DnsLookupDemo />
|
|
|
|
|
|
|
|
|
|
|
|
> **为什么需要这么多层?** 想象一下如果全世界只有一个地址簿,几十亿人同时查,早就崩溃了。分层设计让每个层级只管理自己的"辖区",既高效又可靠。
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
## 3. 第三步:打电话确认 —— TCP 三次握手
|
|
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
### 生活比喻:建立物流通道
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
假设物流车直接开到仓库,结果:
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
- 仓库关门了 → 白跑一趟
|
|
|
|
|
|
- 仓库爆仓不接单 → 无法发货
|
|
|
|
|
|
- 找不到卸货口 → 无法对接
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
**所以在真正发货之前,必须先建立可靠的运输通道**。
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
### 真实过程:TCP 三次握手
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
**TCP(Transmission Control Protocol,传输控制协议)**是确保数据可靠传输的规则。在传输商品(数据)前,必须通过"三次握手"建立连接:
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
|
|
|
|
|
```
|
2026-02-04 16:16:34 +08:00
|
|
|
|
客户端(你的电脑) 服务器(商家仓库)
|
2026-02-03 19:41:14 +08:00
|
|
|
|
| |
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|--- SYN=1 --------------------->| 第1次:你好,我在家,准备收货!(SYN)
|
2026-02-03 19:41:14 +08:00
|
|
|
|
| |
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|<-- SYN=1, ACK=1 ---------------| 第2次:收到!我也准备好发货了,你在家吗?(SYN-ACK)
|
2026-02-03 19:41:14 +08:00
|
|
|
|
| |
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|--- ACK=1 --------------------->| 第3次:在的!请发货吧。(ACK)
|
2026-02-03 19:41:14 +08:00
|
|
|
|
| |
|
2026-02-04 16:16:34 +08:00
|
|
|
|
===== 通道建立,开始发货 =====
|
2026-02-03 19:41:14 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**为什么是三次,不是两次?**
|
|
|
|
|
|
|
|
|
|
|
|
- **第一次(SYN)**:客户端证明自己能发送
|
|
|
|
|
|
- **第二次(SYN-ACK)**:服务器证明自己能接收和发送
|
|
|
|
|
|
- **第三次(ACK)**:客户端证明自己能接收
|
|
|
|
|
|
|
|
|
|
|
|
三次握手确保:**双方都能发、双方都能收** —— 四个条件都满足,才能可靠传输。
|
|
|
|
|
|
|
|
|
|
|
|
**TCP 还负责:**
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
- **数据分包**:大数据拆成小数据包传输
|
|
|
|
|
|
- **顺序重组**:确保数据包按正确顺序组装
|
|
|
|
|
|
- **错误重传**:丢包后自动重新发送
|
|
|
|
|
|
- **流量控制**:根据网络状况调整发送速度
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-01-16 19:10:21 +08:00
|
|
|
|
<TcpHandshakeDemo />
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
> **HTTPS 的额外步骤**:如果是 HTTPS(安全的网站),在 TCP 握手后还会进行 **TLS 握手**(1-RTT 或 2-RTT),双方交换加密密钥,确保之后的对话内容只有双方能看懂,就像用暗语通话。
|
2026-01-15 20:10:19 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
## 4. 第四步:"买家"和"商家"的对话 —— HTTP 请求与响应
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
### 生活比喻:仓库发货
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
物流车到达仓库:"这是订单(HTTP请求),**我要取回商品(网页 HTML 源代码)!**"
|
|
|
|
|
|
仓库管理员核对:"订单有效,这是你要的包裹(**HTML 文件**),请拿好。"
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
|
|
|
|
|
### 真实过程:HTTP 协议通信
|
|
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
**HTTP(HyperText Transfer Protocol,超文本传输协议)**是浏览器和服务器之间的"对话规则"。通道建立后,浏览器发送**取货请求**,**核心目标是拿回网页的源代码(HTML 文件)**:
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
|
|
|
|
|
**HTTP 请求示例:**
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
```http
|
|
|
|
|
|
GET /index.html HTTP/1.1 ← 请求方法 + 路径 + 协议版本
|
|
|
|
|
|
Host: www.example.com ← 目标主机(支持虚拟主机,一台服务器可托管多个网站)
|
|
|
|
|
|
User-Agent: Chrome/120.0 ← 客户端标识(服务器可据此返回适配内容)
|
|
|
|
|
|
Accept: text/html,application/xhtml+xml ← 可接受的响应格式
|
|
|
|
|
|
Accept-Language: zh-CN,zh;q=0.9 ← 偏好的语言
|
|
|
|
|
|
Accept-Encoding: gzip, deflate ← 支持的压缩格式
|
|
|
|
|
|
Connection: keep-alive ← 保持连接(复用 TCP 连接)
|
|
|
|
|
|
Cookie: session_id=abc123 ← 身份凭证
|
|
|
|
|
|
```
|
|
|
|
|
|
|
2026-02-04 16:16:34 +08:00
|
|
|
|
::: tip 💡 开发者顿悟:这不就是 API 吗?
|
|
|
|
|
|
**一模一样!**
|
|
|
|
|
|
你平时写的 API 调用(`fetch` / `axios`)和浏览器访问网页,在 **HTTP 层面完全是同一个东西**。
|
|
|
|
|
|
|
|
|
|
|
|
它们都是发送一个请求,服务器返回一段文本数据。
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
|
|
|
|
|
- 如果服务器给的是 **HTML**,浏览器就把它**画出来**(变成网页)。
|
|
|
|
|
|
- 如果服务器给的是 **JSON**,你的代码就把它**存起来**(用于逻辑处理)。
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
|
|
|
|
|
**根本就没有"两种"请求,只有同一种 HTTP 请求,只是返回的数据格式(Content-Type)不同而已。**
|
|
|
|
|
|
这也是为什么理解了 HTTP,你就理解了 90% 的后端 API 原理。
|
|
|
|
|
|
|
|
|
|
|
|
如果你想深入学习 API 开发,请参考 [API 章节](./api-intro.md)。
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
**常见 HTTP 方法:**
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
- `GET`:获取资源(安全、幂等,可被缓存)
|
|
|
|
|
|
- `POST`:提交数据(创建资源,如注册、登录)
|
|
|
|
|
|
- `PUT`:更新资源(完整替换)
|
|
|
|
|
|
- `PATCH`:部分更新资源
|
|
|
|
|
|
- `DELETE`:删除资源
|
|
|
|
|
|
- `HEAD`:获取响应头(不返回主体,用于检查资源是否存在)
|
|
|
|
|
|
|
|
|
|
|
|
**服务器返回 HTTP 响应:**
|
2026-02-14 12:14:07 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
```http
|
|
|
|
|
|
HTTP/1.1 200 OK ← 协议版本 + 状态码 + 状态描述
|
|
|
|
|
|
Date: Mon, 23 May 2025 12:00:00 GMT ← 服务器时间
|
|
|
|
|
|
Content-Type: text/html; charset=UTF-8 ← 内容类型和编码
|
|
|
|
|
|
Content-Length: 1234 ← 内容长度(字节)
|
|
|
|
|
|
Cache-Control: max-age=3600 ← 缓存策略
|
|
|
|
|
|
Set-Cookie: user_id=xyz789 ← 设置 Cookie
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**HTTP 状态码分类:**
|
|
|
|
|
|
|
|
|
|
|
|
| 状态码 | 类别 | 含义 | 生活类比 |
|
2026-02-14 12:14:07 +08:00
|
|
|
|
| ----------- | ---------- | ---------------- | -------------------------------- |
|
|
|
|
|
|
| **200** | 成功 | 请求成功处理 | "订单确认,马上发货" |
|
|
|
|
|
|
| **301/302** | 重定向 | 资源已移动 | "本店搬家了,请去新店下单" |
|
|
|
|
|
|
| **304** | 未修改 | 缓存仍有效 | "你上次买的还能用,不用重新发货" |
|
|
|
|
|
|
| **400** | 客户端错误 | 请求格式错误 | "订单填写模糊,看不懂" |
|
|
|
|
|
|
| **401** | 未授权 | 需要身份验证 | "请先出示会员卡" |
|
|
|
|
|
|
| **403** | 禁止访问 | 权限不足 | "非内部人员禁止入内" |
|
|
|
|
|
|
| **404** | 未找到 | 资源不存在 | "仓库里没这款商品" |
|
|
|
|
|
|
| **500** | 服务器错误 | 服务器内部错误 | "仓库起火了,暂时发不了货" |
|
|
|
|
|
|
| **502** | 网关错误 | 上游服务器无响应 | "总仓没货了,分仓也调不到" |
|
|
|
|
|
|
| **503** | 服务不可用 | 服务器过载或维护 | "爆单了,暂停接单" |
|
|
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
<HttpExchangeDemo />
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 5. 第五步:拆开"包裹" —— 浏览器渲染
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
### 生活比喻:拆箱与组装
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
你终于收到了快递包裹(HTTP 响应),但打开一看,里面不是现成的家具,而是一堆**零件**(HTML)和一本**组装说明书**(CSS)。作为"买家"(浏览器),你需要亲自动手组装:
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
|
|
|
|
|
1. **拆开包装**:取出所有零件,核对清单(解析 HTML → DOM 树)。
|
|
|
|
|
|
2. **阅读说明**:看懂说明书,知道哪个零件该装哪、什么颜色(解析 CSS → CSSOM 树)。
|
|
|
|
|
|
3. **分类整理**:挑出需要组装的零件,扔掉包装泡沫(`display: none`),准备组装(构建渲染树)。
|
|
|
|
|
|
4. **测量位置**:用尺子量好房间尺寸,决定每个家具具体摆在哪(布局/回流)。
|
|
|
|
|
|
5. **上色装饰**:给家具刷漆、贴贴纸(绘制)。
|
|
|
|
|
|
6. **最终展示**:打扫干净,开灯展示(合成)。
|
|
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
### 真实过程:浏览器渲染引擎
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
浏览器收到的是 **HTML/CSS/JavaScript 代码**(枯燥的文本),但它要变成**像素画面**(精美的网页)。这个过程叫做**渲染(Rendering)**,由浏览器的**渲染引擎**(如 Chrome 的 Blink、Safari 的 WebKit)执行。
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
#### 步骤1:解析 HTML → 构建 DOM 树 (零件清单)
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
浏览器读取 HTML 字节流,将其解析为**DOM(Document Object Model,文档对象模型)树**。这就像把一堆散乱的零件整理成一个有层级关系的清单:
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
```html
|
2026-02-03 19:41:14 +08:00
|
|
|
|
<!-- 原始 HTML -->
|
|
|
|
|
|
<div class="header">标题</div>
|
2026-02-04 16:16:34 +08:00
|
|
|
|
<div class="content">内容</div>
|
|
|
|
|
|
```
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
```text
|
2026-02-04 16:16:34 +08:00
|
|
|
|
DOM 树结构:
|
|
|
|
|
|
Document
|
|
|
|
|
|
└─ html
|
|
|
|
|
|
└─ body
|
|
|
|
|
|
├─ div.header ("标题")
|
|
|
|
|
|
└─ div.content ("内容")
|
|
|
|
|
|
```
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
#### 步骤2:解析 CSS → 构建 CSSOM 树 (说明书)
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
浏览器解析所有的 CSS(内联、外部文件),构建**CSSOM(CSS Object Model)树**。这就像理解说明书上的样式规则:
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
```css
|
2026-02-03 19:41:14 +08:00
|
|
|
|
.header {
|
2026-02-14 12:14:07 +08:00
|
|
|
|
color: blue;
|
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
|
} /* 标题要是蓝色的 */
|
|
|
|
|
|
.content {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
} /* 内容暂时隐藏 */
|
|
|
|
|
|
```
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
|
|
|
|
|
#### 步骤3:合并 → 渲染树 (准备组装)
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
DOM 树 + CSSOM 树 = **渲染树 (Render Tree)**。
|
2026-02-04 16:16:34 +08:00
|
|
|
|
关键点:**只有"可见"的元素才会在渲染树中**。
|
|
|
|
|
|
|
2026-02-14 12:14:07 +08:00
|
|
|
|
- `.header`:在渲染树中(可见)。
|
|
|
|
|
|
- `.content`:**不在**渲染树中(因为 `display: none`,就像被扔掉的包装纸,不需要组装)。
|
|
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
#### 步骤4:布局 (Layout / Reflow) —— 测量尺寸
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
浏览器计算渲染树中每个节点在屏幕上的**精确坐标和大小**。
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-02-14 12:14:07 +08:00
|
|
|
|
- "这个标题框宽 100px,高 50px,放在屏幕左上角 (0,0) 位置。"
|
|
|
|
|
|
- 这个过程叫**重排 (Reflow)**。如果窗口大小变了(比如手机横屏),所有元素的位置都要重新计算,非常消耗性能。
|
|
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
#### 步骤5:绘制 (Paint) —— 上色
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
知道位置后,浏览器开始填充像素:画背景色、文字颜色、边框、阴影等。
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
#### 步骤6:合成 (Composite) —— 最终展示
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
现代浏览器会将页面分成多个**图层 (Layers)** 分别绘制(比如 3D 变换、滚动条独立图层),最后由 GPU 将它们像 Photoshop 图层一样叠加在一起,呈现在屏幕上。
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
<BrowserRenderingDemo />
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
|
|
|
|
|
> **💡 你知道吗?**
|
2026-02-04 16:16:34 +08:00
|
|
|
|
>
|
|
|
|
|
|
> **布局和绘制**是浏览器最忙碌的时候。网页里的元素越多、结构越复杂,浏览器就需要花更多时间来计算位置和上色。这就是为什么有的复杂网页打开会卡顿的原因。
|
|
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 6. 总结:一次完整的"网购"之旅
|
2026-02-04 16:16:34 +08:00
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
让我们回顾整个旅程:
|
|
|
|
|
|
|
|
|
|
|
|
| 阶段 | 技术术语 | 网购类比 | 核心任务 | 关键技术 |
|
2026-02-14 12:14:07 +08:00
|
|
|
|
| ----------- | ---------- | -------- | ------------------ | ------------------------------ |
|
|
|
|
|
|
| **1. 解析** | URL 解析 | 填写订单 | 理解买家想买什么 | 协议、域名、端口、路径、参数 |
|
|
|
|
|
|
| **2. 查询** | DNS 查询 | 查仓库址 | 找到店铺的发货仓库 | 递归/迭代查询、缓存机制 |
|
|
|
|
|
|
| **3. 连接** | TCP 握手 | 建立通道 | 确保物流通畅 | 三次握手、序列号、流量控制 |
|
|
|
|
|
|
| **4. 对话** | HTTP 交换 | 仓库发货 | 提交订单并收货 | 请求方法、状态码、头部字段 |
|
|
|
|
|
|
| **5. 展示** | 浏览器渲染 | 拆箱组装 | 把商品展示出来 | DOM、CSSOM、渲染树、布局、绘制 |
|
|
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
**整个过程通常在几百毫秒内完成** —— 想想这有多么不可思议!
|
|
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
你的浏览器在不到1秒的时间里:
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
2026-02-14 12:14:07 +08:00
|
|
|
|
- 解析了一个复杂的地址
|
2026-02-03 19:41:14 +08:00
|
|
|
|
- 查询了分布在全球的 DNS 服务器
|
|
|
|
|
|
- 和千里之外的服务器建立了可靠连接
|
|
|
|
|
|
- 进行了一次完整的 HTTP 对话
|
|
|
|
|
|
- 把枯燥的代码变成了精美的画面
|
|
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
这就是互联网的魅力:**复杂的技术,简单的体验**。
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 7. 名词速查表 (Glossary)
|
|
|
|
|
|
|
|
|
|
|
|
| 名词 | 全称 | 简单解释 |
|
2026-02-14 12:14:07 +08:00
|
|
|
|
| ----------- | ----------------------------- | -------------------------------------------------------------------------- |
|
|
|
|
|
|
| **URL** | Uniform Resource Locator | **统一资源定位符**。网页的"地址",告诉浏览器去哪里找资源。 |
|
|
|
|
|
|
| **DNS** | Domain Name System | **域名系统**。互联网的"电话簿",把人类可读的域名转换成机器可读的 IP 地址。 |
|
|
|
|
|
|
| **IP 地址** | Internet Protocol Address | **互联网协议地址**。每台联网设备的唯一"门牌号",如 `192.168.1.1`。 |
|
|
|
|
|
|
| **TCP** | Transmission Control Protocol | **传输控制协议**。确保数据可靠传输的"规则",通过三次握手建立连接。 |
|
|
|
|
|
|
| **HTTP** | HyperText Transfer Protocol | **超文本传输协议**。浏览器和服务器"对话"的规则。 |
|
|
|
|
|
|
| **HTTPS** | HTTP Secure | **安全的 HTTP**。在 HTTP 基础上加了加密(TLS/SSL),保护数据安全。 |
|
|
|
|
|
|
| **HTML** | HyperText Markup Language | **超文本标记语言**。网页的"骨架",定义内容的结构。 |
|
|
|
|
|
|
| **CSS** | Cascading Style Sheets | **层叠样式表**。网页的"皮肤",定义内容的外观。 |
|
|
|
|
|
|
| **DOM** | Document Object Model | **文档对象模型**。浏览器把 HTML 转换成的树形结构,方便操作。 |
|
|
|
|
|
|
| **CSSOM** | CSS Object Model | **CSS 对象模型**。浏览器把 CSS 转换成的树形结构。 |
|
|
|
|
|
|
| **渲染** | Rendering | 浏览器把代码转换成屏幕像素的过程。 |
|
|
|
|
|
|
| **RTT** | Round Trip Time | **往返时间**。数据包从发送到接收确认的时间,影响网页加载速度。 |
|
|
|
|
|
|
|
2026-02-03 19:41:14 +08:00
|
|
|
|
---
|
|
|
|
|
|
|
2026-01-15 20:10:19 +08:00
|
|
|
|
> **恭喜!** 现在当你再次在地址栏输入网址时,你已经能看到屏幕背后的那个忙碌而精彩的数字世界了。
|
2026-02-03 19:41:14 +08:00
|
|
|
|
|