从 URL 输入到页面展示,到底发生了什么?

7 阅读7分钟

这道题是前端面试的经典必考题,考察范围横跨计算机网络、操作系统、浏览器架构和前端渲染,能答好的人并不多。大多数人要么只讲 DNS + TCP + HTTP,要么堆砌知识点却没有逻辑。本文尝试按照真实的执行链路,把每个环节串起来讲清楚。


浏览器是多进程架构

在讲 URL 流程之前,先建立一个基础认知:浏览器是多进程架构

操作系统中:

  • 进程(Process) :资源分配的最小单元,拥有独立的内存空间
  • 线程(Thread) :执行的最小单元,线程跑在进程里,共享进程内存

浏览器不是一个单一进程,它由多个进程协同工作:

进程职责
浏览器主进程用户交互、子进程管理、文件存储(缓存/Cookie/localStorage)
网络进程负责网络请求的发起与响应
渲染进程负责 HTML、CSS、JS 的解析与页面渲染
GPU 进程合成图层、硬件加速
插件进程隔离运行浏览器插件

进程之间通过 IPC(Inter-Process Communication,进程间通信) 来传递消息。后面整个 URL 流程,本质上就是这些进程不断协作、通过 IPC 传递数据的过程。


第一阶段:浏览器主进程处理输入

用户在地址栏输入内容,浏览器主进程首先介入。它需要判断用户输入的是什么:

情况一:输入的是搜索关键词

浏览器会拼接默认搜索引擎的 URL,比如 Google:

https://www.google.com/search?q=关键词

情况二:输入的是网址

浏览器会对 URL 进行补全,例如用户输入 time.geekbang.org,浏览器自动补全为:

https://time.geekbang.org

情况三:HTTP 跳转 HTTPS

如果用户手动输入了 http://time.geekbang.org,服务器会返回 301302 重定向响应:

HTTP/1.1 301 Moved Permanently
Location: https://time.geekbang.org

浏览器读取 Location 字段,强制跳转到 HTTPS 地址,重新发起请求。这是服务器帮用户"纠正习惯"的常见做法。

确定最终 URL 后,浏览器主进程通过 IPC 将 URL 转发给网络进程,同时页面标签开始显示 loading 图标,浏览历史栈压入新记录,旧页面触发 beforeunload 事件。


第二阶段:DNS 解析——域名换 IP

网络进程拿到 URL 后,第一步是解析出目标服务器的 IP 地址。计算机底层通信用的是 IP,而不是人类可读的域名,这个转换过程由 DNS(Domain Name System) 完成。

DNS 是一个分布式的 key-value 数据库:

time.geekbang.org36.155.132.55

查询链路从近到远,依次是:

  1. 浏览器本地 DNS 缓存:访问过的域名会被短暂缓存
  2. 操作系统 hosts 文件:本地配置的域名映射
  3. 局域网/本地 DNS 服务器:由运营商或企业提供
  4. 根域名服务器:全球 13 组,中国通过海底光缆连接
  5. 顶级域名服务器(TLD) :负责 .com.org
  6. 权威域名服务器:持有该域名的真实 IP 记录

这是 OSI 七层协议中应用层的工作,最终目的就是拿到一个 IP 地址,让后续 TCP 连接有目标可打。


第三阶段:建立连接——TCP 三次握手

有了 IP 地址,网络进程开始与服务器建立 TCP 连接。TCP 是可靠传输协议,三次握手确保双方都具备收发数据的能力:

客户端 → 服务端:SYN(我要连你)
服务端 → 客户端:SYN + ACK(收到,我也准备好了)
客户端 → 服务端:ACK(好的,开始吧)

三次握手完成后,连接建立。如果是 HTTPS,还需要在 TCP 之上完成 TLS 握手:交换证书、协商加密算法、生成会话密钥,整个过程会多 1~2 个 RTT(往返延迟)。


第四阶段:发送 HTTP 请求

连接建立后,网络进程构造并发送 HTTP 请求,主要包含两部分:

请求行:

GET /index.html HTTP/1.1

包含请求方法(GET/POST 等)、请求路径、HTTP 版本。

请求头:

Host: time.geekbang.org
Authorization: Bearer <jwt_token>
Cookie: session_id=xxx
Cache-Control: max-age=0

这里有几个关键字段:

  • Authorization:携带 JWT Token,用于身份验证
  • Cookie:浏览器自动附带,服务端用于会话识别
  • Cache-Control:告诉服务器/代理如何使用缓存

第五阶段:服务器响应——Content-Type 决定浏览器行为

服务器处理请求后返回响应,网络进程先解析响应头,根据 Content-Type 决定如何处理响应体,然后再通知浏览器主进程:

HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8

Content-Type 的值直接决定了浏览器的下一步动作:

Content-Type浏览器行为
text/html通知渲染进程准备接收,进入页面渲染流程
text/css / image/jpeg触发文件下载或作为子资源缓存
application/octet-stream触发文件下载对话框

状态码也在这里起作用:200 正常、301/302 重定向、304 协商缓存命中、404 资源不存在、500 服务器错误。


第六阶段:导航提交——进程间协作的核心环节

这一段是最容易被忽略的,也是最能体现浏览器多进程架构价值的部分。

当网络进程解析到 Content-Type: text/html 后,整个协作流程如下:

  1. 网络进程 → 浏览器主进程:通过 IPC 告知"已拿到 HTML 响应头,是页面内容"
  2. 浏览器主进程 → 渲染进程:发出"提交导航"消息,通知渲染进程准备接收数据
  3. 渲染进程 → 浏览器主进程:回复"确认提交",表示准备就绪
  4. 渲染进程与网络进程之间建立数据管道:HTML 数据流开始传输
  5. 渲染进程 → 浏览器主进程:数据接收完毕,发出"提交文档"消息
  6. 浏览器主进程:移除旧文档,更新页面状态,loading 图标消失

从用户输入 URL 到页面开始解析的这整个过程,就叫做导航(Navigation)


第七阶段:渲染进程的工作——从 HTML 到像素

数据到达渲染进程后,进入前端最熟悉的渲染流水线:

1. 构建 DOM 树 HTML 字节流 → 词法分析(Tokenization)→ 构建 DOM Tree

2. 构建 CSSOM 树 解析 CSS,构建样式规则树(CSSOM)

3. 合并为渲染树(Render Tree) DOM + CSSOM 合并,只包含可见节点(display:none 的节点不在其中)

4. 布局(Layout) 计算每个节点的位置和尺寸(回流/Reflow 就发生在这里)

5. 分层(Layer) 根据层叠上下文、will-changetransform 等属性,将页面分成多个图层

6. 绘制(Paint) 生成每个图层的绘制指令列表

7. 合成(Composite) GPU 进程将各图层合并,最终输出到屏幕

这也是为什么 CSS 动画优先使用 transformopacity——它们只触发合成阶段,跳过了 Layout 和 Paint,性能最优。


一张思维导图串联全流程

用户输入 URL
  ↓
浏览器主进程:判断输入类型 → URL 补全 / 搜索词处理
  ↓
网络进程:DNS 解析 → 获取 IP
  ↓
TCP 三次握手 → (HTTPS) TLS 握手
  ↓
发送 HTTP 请求(请求行 + 请求头)
  ↓
服务器返回响应(响应头 → Content-Type 判断)
  ↓
导航提交:主进程 ↔ 渲染进程 ↔ 网络进程 IPC 协作
  ↓
渲染进程:DOM → CSSOM → Render Tree → Layout → Paint → Composite
  ↓
页面呈现

小结

这道题真正考的是知识体系的完整性和表达的逻辑性,而不是某个孤立知识点的深度。建议答题时按照"输入处理 → DNS → TCP → HTTP → 响应判断 → 导航提交 → 渲染流水线"这条主线展开,每个环节点到核心概念即可,切忌把 TCP 三次握手的 Flag 位全背一遍却忘了讲渲染进程是怎么拿到数据的。

前端工程师能把浏览器的多进程架构和进程间 IPC 协作讲清楚,往往是和其他候选人拉开差距的地方。