第一阶段:网络通信 (Network Navigation)
在这个阶段,目标是把你的请求发给服务器,并拿到 HTML 文件。
1. URL 解析与缓存检查
输入解析:浏览器判断你输入的是一个合法的 URL 还是搜索关键字。如果是 URL,它会补全协议(如
https://)。检查缓存:浏览器会先检查本地是否有强缓存(
Cache-Control/Expires)。如果有且未过期,直接使用缓存,不发送网络请求(状态码 200 from memory cache)。
2. DNS 解析 (Domain Name System)
如果缓存没命中,浏览器不知道域名的 IP 地址(服务器的门牌号),需要进行 DNS 查询。
查询顺序:
浏览器缓存:浏览器自己存了一份。
系统缓存 (hosts):操作系统的 hosts 文件。
路由器缓存。
ISP DNS 服务器:网络运营商的 DNS。
递归查询:如果都没找到,ISP DNS 会像洋葱剥皮一样去问根域名服务器 -> .com 顶级域名服务器 -> 目标权威 DNS 服务器,最终拿到 IP 地址。
3. 建立 TCP 连接 (三次握手)
拿到 IP 后,浏览器需要与服务器建立可靠的连接。这就涉及著名的 TCP 三次握手:
SYN:客户端发送“我想和你建立连接”。
SYN-ACK:服务器回复“好的,我准备好了”。
ACK:客户端回复“知道了,那我们开始吧”。
如果是 HTTPS (TLS 握手):
在 TCP 握手之后,还会多一步 TLS/SSL 握手,用于校验证书、交换加密密钥,确保数据传输安全。
4. 发送 HTTP 请求
连接建立后,浏览器发送具体的请求报文。
请求行:
GET /index.html HTTP/1.1请求头:携带
Cookie,User-Agent,Accept等信息。
5. 服务器处理与响应
服务器收到请求后,经过后端处理(Nginx 转发 -> 业务代码 -> 查询数据库),返回响应报文。
响应头:
Content-Type: text/html(告诉浏览器这是个网页),Set-Cookie等。响应体:HTML 字符串代码。
第二阶段:浏览器渲染 (Critical Rendering Path)
这是前端开发最核心的部分。浏览器拿到 HTML 代码后,内核(如 Webkit/Blink)开始工作。
1. 解析 HTML,构建 DOM 树
浏览器从上到下解析 HTML 文档,将标签(Tags)转换成 DOM 节点 (Nodes),最终形成 DOM 树 (DOM Tree)。
注意:如果遇到
<script>标签,默认会阻塞解析(除非加了async或defer),因为 JS 可能会修改 DOM。
2. 解析 CSS,构建 CSSOM 树
同时,浏览器下载并解析 CSS 文件(以及 <style> 里的代码),构建 CSS 对象模型树 (CSSOM Tree)。
这棵树包含了所有的样式规则(层叠、继承等)。
3. 合成渲染树 (Render Tree)
浏览器将 DOM 树和 CSSOM 树结合,生成 渲染树 (Render Tree)。
关键点:渲染树只包含可见元素。
<head>不在里面。display: none的元素不在渲染树中。visibility: hidden的元素在渲染树中(因为它虽然看不见,但占位置)。
4. 布局 (Layout / Reflow)
有了渲染树,浏览器知道了有哪些节点、样式是什么,但还不知道它们在屏幕上的具体位置和大小。
这一步叫 布局(也叫 回流/重排)。
浏览器计算每个节点在视口(Viewport)中的几何信息(x, y, width, height)。
5. 绘制 (Painting)
布局确定后,浏览器开始填充像素。
这一步叫 绘制。
包括画背景色、文字颜色、边框、阴影等。
6. 合成 (Composite)
现代浏览器(尤其是 Chrome)会将页面分成多个图层(Layer)。
比如
<video>、canvas、transform: translateZ(0)会创建新的图层。GPU 负责将这些图层像 Photoshop 图层一样叠加在一起,最终显示在屏幕上