再来看看「从输入 URL 到看到页面」的整个流程

220 阅读4分钟

大家好,我是有一点想法的thinkmars,目前在准备面试与工作,借着间隙时间学习复习,写一点基础文章,欢迎想找工作的人与我一起学习,一起讨饭吃~

前言

理解页面加载流程对于性能优化至关重要,前端性能优化无外乎就是优化这个流程。相对底层的协议来说,前端优化的空间比较小,难度较大,而后端服务通信可以选用一些更高效的协议或者自定义协议。前端优化通常集中在建立连接后的阶段,比如缩短传输距离、减少传输次数、减小资源传输体积、降低浏览器渲染压力、使用资源缓存等等。


整个流程大致分为以下步骤:

1. 输入 URL 并解析

  • 用户行为:在浏览器地址栏输入 https://www.example.com 并按下回车。
  • 浏览器解析 URL
    • 检查 URL 的协议(https)、域名(www.example.com)、端口(默认443)、路径(/)等。
    • 如果输入的不是完整的 URL,浏览器会尝试补全(比如自动添加http://或搜索关键词)。

2. DNS 域名解析

  • 目的:将域名(如www.example.com)转换成服务器的 IP 地址(如192.0.2.1)。
  • 具体步骤
    1. 浏览器缓存:检查浏览器是否缓存过该域名的 IP。
    2. 系统缓存:查询本地 hosts 文件或操作系统缓存。
    3. 路由器缓存:检查路由器 DNS 缓存。
    4. ISP DNS 服务器:向互联网服务提供商(如电信、联通)的 DNS 服务器发起请求。
    5. 递归查询:如果 ISP 的 DNS 没有缓存,会从根域名服务器(.)开始逐级查询:
      • 根域名服务器 → .com顶级域名服务器 → example.com权威域名服务器。
    6. 返回 IP:最终获得www.example.com对应的 IP 地址。
graph TD
    A[浏览器缓存] --> B[系统缓存]
    B --> C[路由器缓存]
    C --> D[ISP DNS服务器]
    D --> E[根域名服务器]
    E --> F[顶级域名服务器]
    F --> G[权威域名服务器]
    G --> H[返回IP地址]

3. 建立 TCP 连接(三次握手)

  • 目的:浏览器和服务器通过 TCP 协议建立可靠连接。
  • 三次握手过程
    1. 浏览器 → 服务器:发送SYN=1, Seq=x(同步请求)。
    2. 服务器 → 浏览器:回复SYN=1, ACK=x+1, Seq=y(确认并同步)。
    3. 浏览器 → 服务器:发送ACK=y+1(最终确认)。
  • 结果:连接建立,可以传输数据。
graph LR
    A[浏览器] -- SYN=1,Seq=x --> B[服务器]
    B -- SYN=1,ACK=x+1,Seq=y --> A
    A -- ACK=y+1 --> B

4. 发送 HTTP 请求

  • 浏览器构造 HTTP 请求,例如:
    GET / HTTP/1.1
    Host: www.example.com
    User-Agent: Chrome/...
    Accept: text/html, */*
    
  • 如果是 HTTPS
    • 先进行 TLS 握手(交换密钥、验证证书)。
    • 加密后续通信内容。

5. 服务器处理请求

  • Web 服务器(如 Nginx/Apache)
    • 解析请求路径,可能转发给后端应用(如 PHP、Node.js)。
  • 后端应用
    • 处理业务逻辑(如查询数据库)。
    • 生成 HTML 响应(或 JSON 数据)。

6. 服务器返回 HTTP 响应

  • 响应示例

    HTTP/1.1 200 OK
    Content-Type: text/html
    Content-Length: 1234
    
    <!DOCTYPE html>
    <html>...</html>
    
  • 状态码200表示成功,404表示页面不存在等。


7. 浏览器解析和渲染页面

  1. 解析 HTML:构建 DOM 树(文档对象模型)。
  2. 解析 CSS:构建 CSSOM 树(CSS 样式规则)。
  3. 合并为渲染树:结合 DOM 和 CSSOM,排除不可见元素(如<head>)。
  4. 布局(Layout):计算每个元素的位置和大小。
  5. 绘制(Paint):将像素点绘制到屏幕上。
  6. 执行 JavaScript
    • 如果遇到<script>标签,会暂停 HTML 解析,先执行 JS(除非标记为asyncdefer)。
graph TD
    A[解析HTML] --> B[构建DOM树]
    B --> C[解析CSS]
    C --> D[构建CSSOM树]
    D --> E[合并渲染树]
    E --> F[布局计算]
    F --> G[绘制页面]
    G --> H[执行JavaScript]
    H -->|遇到<script>| I[暂停HTML解析]
    I --> J[执行JS代码]
    J -->|完成| K[继续HTML解析]

8. 加载静态资源

  • 页面中可能包含图片、CSS、JS 等资源,浏览器会再次发起请求获取它们(可能并行下载)。

9. 关闭 TCP 连接(四次挥手)

  • 目的:数据传输完成后释放连接。
  • 四次挥手过程
    1. 浏览器 → 服务器:发送FIN=1(请求关闭)。
    2. 服务器 → 浏览器:回复ACK(确认收到)。
    3. 服务器 → 浏览器:发送FIN=1(服务器也准备关闭)。
    4. 浏览器 → 服务器:回复ACK(最终确认)。
graph LR
    A[浏览器] -- FIN=1 --> B[服务器]
    B -- ACK --> A
    B -- FIN=1 --> A
    A -- ACK --> B

完整流程图

graph TD
    A[输入URL] --> B[DNS解析]
    B --> C[TCP三次握手]
    C --> D[发送HTTP请求]
    D --> E[服务器处理请求]
    E --> F[返回HTTP响应]
    F --> G[浏览器解析渲染]
    G --> H[加载静态资源]
    H --> I[TCP四次挥手]

关键点总结

  1. DNS 解析:把域名变成 IP 地址。
  2. TCP 握手:确保可靠传输。
  3. HTTP 请求/响应:获取网页内容。
  4. 渲染引擎:将 HTML/CSS/JS 变成可视化页面。

如此复杂的流程,跑完也不过秒级甚至毫秒级,不得不感叹网络技术的神奇。当然,这也得益于硬件技术与软件工程的进步。