Skip to content

从输入 URL 到页面加载完成的全过程解析

这是一道经典的面试题,其深度和广度可以覆盖非常多的知识点。本笔记旨在整理出一个结构清晰、重点突出、难度适中的回答脉络。


流程总览

整个过程可以大致分为两大阶段:网络通信阶段浏览器渲染阶段

  1. URL 解析与补全 (URL Parsing & Completion)
  2. URL 编码 (URL Encoding)
  3. 浏览器缓存查找 (Browser Cache Lookup)
  4. DNS 解析 (DNS Resolution)
  5. 建立 TCP 连接 (Establishing TCP Connection)
  6. (可选) HTTPS 握手 ((Optional) HTTPS Handshake)
  7. 确定要发送的 Cookie (Determining Cookies to Send)
  8. 发送 HTTP 请求 (Sending the HTTP Request)
  9. 服务器处理与响应 (Server Processing & Response)
  10. 连接管理 (Connection Management)
  11. 浏览器处理响应 (Browser Processes the Response)
  12. 处理响应头 (Processing Response Headers)
  13. 浏览器渲染页面 (Browser Renders the Page)
  14. 触发事件 (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)
    1. SYN: 客户端发送一个 SYN 包(同步序列编号)到服务器,请求建立连接。
    2. SYN+ACK: 服务器收到请求后,回复一个 SYN+ACK 包(同步+确认)。
    3. 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)。

浏览器会根据域名、路径等规则,决定将哪些本地存储的 Cookie 附加到即将发送的请求头中。

8. 发送 HTTP 请求

一切准备就绪后,浏览器会构建并发送 HTTP 请求。

  • 请求头 (Request Headers):包含请求方法 (GET)、协议版本 (HTTP/1.1HTTP/2)、HostConnectionCookie 等众多字段。
  • 发送:将构建好的请求报文通过已建立的 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)绘制成用户看到的页面。

  1. 解析 HTML 生成 DOM 树 (DOM Tree):浏览器自上而下解析 HTML 源码,生成一个树状的文档对象模型(DOM)。document 对象就是这棵树的根节点。
  2. 解析 CSS 生成 CSSOM 树 (CSSOM Tree):浏览器解析所有 CSS(外部、内部、内联),生成一个样式规则树(CSSOM)。
  3. 合并生成渲染树 (Render Tree):将 DOM 树和 CSSOM 树结合起来,生成渲染树。渲染树只包含需要被显示的节点以及它们的样式信息(display: none 的节点不会出现在渲染树中)。
  4. 布局 (Layout / Reflow):根据渲染树,计算出每个节点在屏幕上的确切位置和大小。这个过程也称为“回流”或“重排”。
  5. 绘制 (Paint / Repaint):根据布局计算出的信息,调用 GPU 将各个节点绘制到屏幕上。这个过程也称为“重绘”。
  6. 请求外部资源:在解析 HTML 的过程中,如果遇到 <link>, <img>, <script> 等标签,浏览器会立即发起新的 HTTP 请求去获取这些外部资源,这个过程是并行的。

14. 触发事件

在页面加载和渲染的不同阶段,会触发相应的 JavaScript 事件。

  • DOMContentLoaded: 当初始的 HTML 文档被完全加载和解析完成之后触发,无需等待样式表、图像等外部资源加载完成。
  • load: 当页面上所有的资源(包括图片、样式表、脚本等)都已加载完毕后触发。