从输入 URL 到页面加载完成的全过程解析
这是一道经典的面试题,其深度和广度可以覆盖非常多的知识点。本笔记旨在整理出一个结构清晰、重点突出、难度适中的回答脉络。
流程总览
整个过程可以大致分为两大阶段:网络通信阶段 和 浏览器渲染阶段。
- URL 解析与补全 (URL Parsing & Completion)
- URL 编码 (URL Encoding)
- 浏览器缓存查找 (Browser Cache Lookup)
- DNS 解析 (DNS Resolution)
- 建立 TCP 连接 (Establishing TCP Connection)
- (可选) HTTPS 握手 ((Optional) HTTPS Handshake)
- 确定要发送的 Cookie (Determining Cookies to Send)
- 发送 HTTP 请求 (Sending the HTTP Request)
- 服务器处理与响应 (Server Processing & Response)
- 连接管理 (Connection Management)
- 浏览器处理响应 (Browser Processes the Response)
- 处理响应头 (Processing Response Headers)
- 浏览器渲染页面 (Browser Renders the Page)
- 触发事件 (Event Firing)
详细步骤分解
1. URL 解析与补全
当用户在地址栏输入内容并回车时,浏览器首先会进行解析。
- 协议和端口补全:如果用户只输入了
baidu.com,浏览器会自动补全协议。- 补全为
http://(默认端口80) 或https://(默认端口443)。现代浏览器通常会优先尝试https。
- 补全为
- 关键字搜索:如果输入的内容不符合 URL 格式(如 "高效的知识整理专家"),浏览器会将其识别为搜索关键字,并使用默认配置的搜索引擎(如百度、谷歌)生成搜索 URL。
2. URL 编码
URL 中不能包含非 ASCII 字符(如中文)。如果 URL 中存在这些字符,浏览器会自动进行编码。
- 原因:URL 标准规定了有效字符集,中文字符等需要转换为百分号编码(Percent-encoding)。
- 示例:在百度搜索 "无视",地址栏中的中文会被编码。
- 原始:
https://www.baidu.com/s?wd=无视 - 编码后:
https://www.baidu.com/s?wd=%E6%97%A0%E8%A7%86
- 原始:
- 手动编码:在 JavaScript 中,可以使用
encodeURI()或encodeURIComponent()函数进行手动编码。
3. 浏览器缓存查找
在发起网络请求前,浏览器会检查本地是否存在有效的缓存。
- 缓存协议:根据 HTTP 缓存协议(如
Cache-Control,Expires),浏览器判断资源是否命中缓存且未过期。 - 缓存命中 (Cache Hit):如果命中强缓存,浏览器会直接从本地读取资源副本,不再向服务器发送请求,这极大地提高了加载速度。
- 注意:为了确保用户能获取最新的页面内容,主 HTML 文档通常设置为不进行强缓存或缓存时间很短。
4. DNS 解析
网络通信依赖 IP 地址,而非域名。因此,浏览器必须将域名转换为对应的 IP 地址。
- 目的:将
www.example.com这样的域名翻译成93.184.216.34这样的 IP 地址。 - 过程:这是一个复杂的过程,涉及浏览器缓存、操作系统缓存、本地
hosts文件、路由器缓存、以及向本地 DNS 服务器和根域名服务器的递归查询。
5. 建立 TCP 连接
HTTP 协议是构建在 TCP 协议之上的。在发送 HTTP 请求之前,客户端(浏览器)和服务器之间必须建立一个可靠的连接通道。
- TCP 三次握手 (Three-Way Handshake):
- SYN: 客户端发送一个 SYN 包(同步序列编号)到服务器,请求建立连接。
- SYN+ACK: 服务器收到请求后,回复一个 SYN+ACK 包(同步+确认)。
- ACK: 客户端收到服务器的回复后,再发送一个 ACK 包(确认)。
- 至此,一个可靠的 TCP 连接建立完成。
6. (可选) HTTPS 握手
如果 URL 是 https 协议,那么在 TCP 连接建立后,还需要进行 SSL/TLS 握手来建立一个加密信道。
- 目的:确保后续传输的 HTTP 内容是加密的,防止被窃听和篡改。
- 协议栈:
Application Layer (HTTPS) -> Security Layer (SSL/TLS) -> Transport Layer (TCP) - HTTP/2 协商:在 SSL/TLS 握手过程中,客户端和服务器可以协商是否使用性能更优的 HTTP/2 协议(HTTP/2 强制要求使用 HTTPS)。
7. 确定要发送的 Cookie
浏览器会根据域名、路径等规则,决定将哪些本地存储的 Cookie 附加到即将发送的请求头中。
8. 发送 HTTP 请求
一切准备就绪后,浏览器会构建并发送 HTTP 请求。
- 请求头 (Request Headers):包含请求方法 (
GET)、协议版本 (HTTP/1.1或HTTP/2)、Host、Connection、Cookie等众多字段。 - 发送:将构建好的请求报文通过已建立的 TCP 连接发送给服务器。
9. 服务器处理与响应
服务器(后端)接收并处理请求,然后返回一个 HTTP 响应报文,包含响应头和响应体。
10. 连接管理
- TCP 连接保持:为了避免每次请求都重新建立连接(三次握手开销大),HTTP/1.1 默认启用
Connection: keep-alive,允许在一次 TCP 连接中传输多个 HTTP 请求和响应。 - TCP 连接关闭:如果决定关闭连接,会进行 TCP 四次挥手 (Four-Way Handshake)。
11. 浏览器处理响应
浏览器收到服务器的响应报文后,首先会检查响应头。
- 根据状态码处理 (Status Code):
200 OK: 请求成功,可以继续处理响应体。301/302 Redirect: 浏览器会根据响应头中的Location字段发起一个新的请求到重定向的地址。404 Not Found: 页面不存在,显示 404 错误页。403 Forbidden: 无权限访问,显示 403 错误页。
- 根据
Content-Type头解析内容:这个头字段告诉浏览器响应体到底是什么类型的数据。text/html: 按 HTML 文档解析。image/jpeg: 按 JPEG 图片显示。text/css: 按 CSS 样式表解析。application/javascript: 按 JavaScript 脚本执行。
12. 处理响应头
- 缓存更新:根据响应中的缓存控制字段(
Cache-Control等),决定是否以及如何缓存这次的响应内容。 - Cookie 存储:如果响应头中包含
Set-Cookie字段,浏览器会相应地在本地存储或更新 Cookie。
13. 浏览器渲染页面 (关键渲染路径)
这是前端的核心部分,将服务器返回的数据(主要是 HTML, CSS, JS)绘制成用户看到的页面。
- 解析 HTML 生成 DOM 树 (DOM Tree):浏览器自上而下解析 HTML 源码,生成一个树状的文档对象模型(DOM)。
document对象就是这棵树的根节点。 - 解析 CSS 生成 CSSOM 树 (CSSOM Tree):浏览器解析所有 CSS(外部、内部、内联),生成一个样式规则树(CSSOM)。
- 合并生成渲染树 (Render Tree):将 DOM 树和 CSSOM 树结合起来,生成渲染树。渲染树只包含需要被显示的节点以及它们的样式信息(
display: none的节点不会出现在渲染树中)。 - 布局 (Layout / Reflow):根据渲染树,计算出每个节点在屏幕上的确切位置和大小。这个过程也称为“回流”或“重排”。
- 绘制 (Paint / Repaint):根据布局计算出的信息,调用 GPU 将各个节点绘制到屏幕上。这个过程也称为“重绘”。
- 请求外部资源:在解析 HTML 的过程中,如果遇到
<link>,<img>,<script>等标签,浏览器会立即发起新的 HTTP 请求去获取这些外部资源,这个过程是并行的。
14. 触发事件
在页面加载和渲染的不同阶段,会触发相应的 JavaScript 事件。
DOMContentLoaded: 当初始的 HTML 文档被完全加载和解析完成之后触发,无需等待样式表、图像等外部资源加载完成。load: 当页面上所有的资源(包括图片、样式表、脚本等)都已加载完毕后触发。