从输入 URL 到页面显示——浏览器工作原理全解析

这篇文章的起因很朴素:被面试官问到"浏览器输入 URL 后发生了什么",我当时答得磕磕绊绊。事后复盘,发现自己其实每天都在和这条链路打交道,却从没认真梳理过它。所以这篇更多是我的学习笔记------不追求教科书式的完整,而是希望用对话感把每个概念说清楚。如果你也对这条链路模糊,欢迎一起往下读。


一、为什么要理解这条链路?

先说面试:这是前端面试里的"经典送命题"。问法很宽,可以从 DNS 聊到渲染,每个环节都能展开一个小时。

但比面试更重要的是:理解浏览器在帮你做什么

为什么 <script> 放底部?为什么 transformtop 流畅?为什么 HTTPS 比 HTTP 安全?这些问题的答案,都藏在这条链路里。

完整流程如下,我们逐段拆解:

css 复制代码
URL 输入
  ↓
DNS 解析(域名 → IP)
  ↓
TCP 三次握手(建立连接)
  ↓
TLS 握手(HTTPS 加密,若有)
  ↓
HTTP 请求 / 响应
  ↓
浏览器解析渲染(HTML → 像素)
  ↓
页面显示

二、DNS 解析:找到服务器地址

域名是个"电话簿"

你输入的是 www.example.com,但网络层面真正认的是 IP 地址(比如 93.184.216.34)。域名只是给人看的别名。

DNS(Domain Name System)就是把域名翻译成 IP 的"电话簿"。

查询顺序:从近到远

浏览器不会每次都跑去问根服务器,它有一套缓存优先的查询链:

复制代码
浏览器缓存
  ↓(没有?)
操作系统缓存(hosts 文件 / 系统 DNS 缓存)
  ↓(没有?)
路由器缓存
  ↓(没有?)
ISP(运营商)DNS 服务器
  ↓(没有?)
根域名服务器 → 顶级域服务器(.com)→ 权威域名服务器
  ↓
返回 IP 地址,逐层缓存

类比一下:你想找某个老同学的电话,你会先翻自己的手机通讯录,再问共同朋友,最后才去翻毕业纪念册。每一层都比下一层"近"。

TTL:为什么不能永久缓存?

DNS 记录带有 TTL(Time To Live,缓存有效期),过期后必须重新查询。

原因很简单:映射关系会变。比如网站迁移服务器,IP 换了,如果客户端永久缓存旧 IP,就再也找不到新服务器了。TTL 的存在,是在"缓存命中率"和"数据新鲜度"之间做权衡。


三、TCP 三次握手:建立可靠连接

找到 IP 之后,浏览器需要和服务器建立连接。HTTP 跑在 TCP 之上,而 TCP 是面向连接的协议------发数据之前,双方必须先"握手"确认线路通畅。

为什么是三次,不是两次或四次?

这是个很好的问题。我的理解是,三次握手需要确认三件事:

次序 方向 目的
第一次 客户端 → 服务器(SYN) 确认:客户端能发
第二次 服务器 → 客户端(SYN+ACK) 确认:服务器能收、能发
第三次 客户端 → 服务器(ACK) 确认:客户端能收

三次之后,双方都知道对方能收能发,通信信道建立完毕。

少一次(两次握手)的问题:客户端能收这件事没人确认,存在单向通道风险,且会引发"历史连接"问题(旧的延迟 SYN 包触发服务器建立无效连接)。

多一次没必要:四次就是冗余了,三次已经能确认所有需要确认的状态。

类比:打电话前的确认------"喂,你能听到我吗?"→"能,你能听到我吗?"→"能"。三句话,线路通畅,开始正式通话。


四、TLS 握手:加密 + 身份验证(HTTPS)

TCP 建好连接后,如果是 HTTPS,还要多一步:TLS 握手。

为什么需要它?

HTTP 是明文传输的。你发出去的每一个请求,路径上的任何节点(路由器、运营商、同一 WiFi 下的其他人)理论上都能看到完整内容。用户密码、信用卡号......全部裸奔。

TLS 解决了两个问题:

  • 身份验证 :你连接的是真的 example.com,不是被人劫持的钓鱼站
  • 加密传输:内容只有你和服务器能读

握手流程(简化版)

markdown 复制代码
1. 浏览器 → 服务器:我支持这些加密算法 [列表],给我你的证书

2. 服务器 → 浏览器:用这个算法,这是我的证书(含公钥)

3. 浏览器验证证书(向 CA 机构核实真实性)
   生成随机数,用服务器公钥加密后发过去

4. 服务器用私钥解密,得到随机数

5. 双方用这个随机数生成"会话密钥"(对称密钥)

6. 后续所有通信用会话密钥加密

两个角色分开理解

初学时我一直搞混"证书"和"加密",其实它们是两件事:

角色 类比 作用
证书 身份证 + 公证处盖章 证明"我真的是 example.com"
加密 双方约定的暗语本 保证通信内容只有双方能读

证书由 CA(证书颁发机构)签发,浏览器内置了受信任的 CA 列表。如果证书是自签名的或已过期,浏览器会弹出警告。

为什么不全程用公钥加密?

这是个常被忽略的细节。非对称加密(RSA)安全,但比对称加密(AES)慢约 100 倍

所以 TLS 的设计是:非对称加密只用于握手阶段安全交换密钥,真正的通信内容用对称密钥(AES)加密。兼顾了安全性和性能。

加密类型 代表算法 速度 用途
非对称加密 RSA、ECDH 密钥交换、签名
对称加密 AES 实际数据加密

TLS 管加密,Cookie 管身份

还有一个常见混淆点:TLS 建立的是加密信道,不等于"记住了你是谁"。

服务器如何区分不同用户?那是 HTTP 层面 Cookie / session_id 的事。TLS 每次连接都会重新握手(虽然有会话恢复机制),但识别"这个请求属于哪个用户",靠的是请求头里的 Cookie。


五、HTTP 请求与响应

握手完成,浏览器发出第一个 HTTP 请求:

javascript 复制代码
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 ...
Accept: text/html
Cookie: session_id=abc123
Cache-Control: no-cache

几个重要的请求头:

  • Host:告诉服务器你访问的是哪个域名(一台服务器可能托管多个域名)
  • Cookie:带上本地存储的会话标识
  • Cache-Control:告诉服务器/中间缓存怎么处理这个请求的缓存

服务器返回响应:

javascript 复制代码
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Cache-Control: max-age=3600

<!DOCTYPE html>...

常见状态码速查:

状态码 含义 常见场景
200 成功 正常响应
301 永久重定向 域名迁移
304 内容未修改 使用本地缓存
404 资源不存在 路径错误
500 服务器内部错误 后端异常

六、浏览器解析:从 HTML 到像素

拿到 HTML 之后,浏览器开始做"最后一公里"的工作:把代码变成屏幕上的像素。这个过程叫关键渲染路径(Critical Rendering Path)

Step 1:解析 HTML → DOM 树

浏览器从上到下解析 HTML,构建 DOM(Document Object Model)树。DOM 是页面结构的内存表示,每个标签对应一个节点。

html 复制代码
<!-- 这段 HTML -->
<body>
  <div class="container">
    <p>Hello</p>
  </div>
</body>

<!-- 对应的 DOM 树(简化) -->
body
  └── div.container
        └── p
              └── "Hello"

Step 2:下载并解析 CSS → CSSOM 树

并行下载 CSS 文件,解析生成 CSSOM(CSS Object Model)树。结构和 DOM 类似,但存的是样式信息。

关键阻塞规则

这里有个绕不开的问题,很多性能优化都源于此:

资源类型 阻塞什么 原因
CSS 阻塞渲染 没 CSSOM 就没法确定元素最终样式
JS(无属性) 阻塞HTML 解析 JS 可能操作 DOM,所以得等 JS 执行完
JS(defer 不阻塞解析 延迟到 HTML 解析完才执行
JS(async 下载不阻塞,执行阻塞 下载完立刻执行

这就是为什么 <script> 推荐放在 </body> 前,或者使用 defer:避免阻塞 HTML 解析,提升首屏速度。

Step 3:DOM + CSSOM → Render Tree

合并 DOM 和 CSSOM,生成只包含可见节点的 Render Tree(渲染树)。

注意:display: none 的元素不进入 Render Tree(它不占空间、不显示);但 visibility: hidden 的元素会进入(它仍然占位)。

Step 4:Layout(重排 / Reflow)

基于 Render Tree,计算每个节点的精确位置和尺寸------相对视口的坐标、宽高、边距......

这步代价较高。任何改变元素几何属性的操作(改 widthmarginposition)都会触发 Reflow,浏览器需要重新计算布局。

Step 5:Paint(重绘 / Repaint)

按照布局结果,把每个元素"画"出来:填充颜色、绘制边框、阴影、文字......

Step 6:Composite(合成)

浏览器把不同图层合并,最终送到屏幕显示。

这里有个重要的性能优化点:

css 复制代码
/* 只触发 Composite,性能最好 */
.card {
  transform: translateY(-4px);
  opacity: 0.9;
}

/* 触发 Layout + Paint + Composite,代价最高 */
.card {
  top: -4px; /* 改变几何属性 */
}

transformopacity 的变化不影响布局,浏览器可以直接在 GPU 层面处理,跳过 Layout 和 Paint,性能最优。这就是为什么 CSS 动画推荐优先用 transform


七、整条链路总结

css 复制代码
用户输入 URL
        │
        ▼
┌──────────────────┐
│   DNS 解析        │  域名 → IP(电话簿查询,逐层缓存)
└──────────────────┘
        │
        ▼
┌──────────────────┐
│  TCP 三次握手     │  确认双方能收发(SYN → SYN+ACK → ACK)
└──────────────────┘
        │
        ▼
┌──────────────────┐
│  TLS 握手(HTTPS)│  证书验证 + 交换会话密钥(非对称→对称)
└──────────────────┘
        │
        ▼
┌──────────────────┐
│  HTTP 请求/响应   │  发送 Request,接收 HTML/CSS/JS
└──────────────────┘
        │
        ▼
┌──────────────────────────────────────────┐
│             浏览器渲染流水线              │
│  HTML → DOM  ┐                           │
│              ├→ Render Tree → Layout     │
│  CSS → CSSOM ┘         → Paint → 合成   │
└──────────────────────────────────────────┘
        │
        ▼
      页面显示 🎉

延伸与发散

在梳理这条链路的过程中,我产生了一些新的疑问,记录在这里:

  1. HTTP/2 和 HTTP/3 对这条链路的影响是什么? HTTP/2 的多路复用是不是意味着 TCP 握手的成本被摊薄了?HTTP/3 基于 UDP 的 QUIC 协议又是如何处理可靠性的?
  2. Service Worker 如何介入这条链路? PWA 的离线缓存是在哪个环节"截胡"请求的?
  3. 浏览器的预加载机制<link rel="preconnect"><link rel="prefetch">)是在提前做哪几步?

这些可能会是后续文章的方向,也欢迎有经验的朋友交流。


🧠 面试常问版(核心记忆点)

如果只有 5 分钟时间,记住这 5 条:

  1. DNS:域名→IP,查询链是浏览器缓存→OS→路由→ISP→根服务器,TTL 控制缓存时效。
  2. TCP 三次握手:确认双方能收发,三次刚好,少一次有安全隐患,多一次冗余。
  3. TLS:证书验证身份,非对称加密只用于交换密钥,实际内容用 AES(对称)加密,快 100 倍。
  4. 渲染阻塞 :CSS 阻塞渲染,JS 阻塞 HTML 解析,所以 <script> 放底部或用 defer
  5. 渲染性能transform/opacity 只触发合成层,跳过 Layout 和 Paint,动画优先使用。

参考资料

相关推荐
weixin_408099672 小时前
【完整教程】天诺脚本如何调用 OCR 文字识别 API?自动识别屏幕文字实战(附代码)
前端·人工智能·后端·ocr·api·天诺脚本·自动识别文字脚本
吴声子夜歌2 小时前
ES6——Generator函数详解
前端·javascript·es6
吴声子夜歌2 小时前
ES6——Set和Map详解
前端·javascript·es6
码喽7号2 小时前
vue学习四:Axios网络请求
前端·vue.js·学习
粥里有勺糖3 小时前
视野修炼-技术周刊第129期 | 上一次古法编程是什么时候
前端·javascript·github
whuhewei3 小时前
JS获取CSS动画的旋转角度
前端·javascript·css
蓝黑20203 小时前
Vue组件通信之v-model
前端·javascript·vue
像素之间4 小时前
为什么运行时要加set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve
前端·javascript·vue.js
M ? A4 小时前
Vue转React实战:defineProps精准迁移实战
前端·javascript·vue.js·经验分享·react.js·开源·vureact