No.56
从输入 URL 到页面显示,中间发生了什么?
一句话回答
分两段讲:网络阶段,浏览器解析 URL、查缓存、做 DNS 解析、建立 TCP 连接(HTTPS 还要 TLS 握手),然后发送请求、接收响应;渲染阶段,解析 HTML 生成 DOM 树,解析 CSS 生成 CSSOM,两者合成渲染树,再经过布局、绘制、合成,最终显示在屏幕上。
详细解析
网络阶段
- 处理输入:判断是搜索词还是网址,补全协议;如果域名在 HSTS 列表里,直接改用 HTTPS
- 查缓存:先看 Service Worker,再看 HTTP 缓存。强缓存命中就直接使用,不发请求
- DNS 解析:浏览器缓存 → 操作系统缓存(含 hosts 文件)→ 本地 DNS 服务器。本地 DNS 服务器向根域名服务器、顶级域名服务器、权威域名服务器逐级查询,得到 IP
- 建立连接:TCP 三次握手;HTTPS 再做 TLS 握手(TLS 1.3 只需 1 个 RTT)。HTTP/3 基于 QUIC(UDP),把传输握手和加密握手合在一起
- 发送请求、接收响应:请求带上 Cookie 等信息。响应可能是 301/302 重定向(重新走一遍流程)、304(使用本地缓存)或 200
- 交给渲染进程:根据 Content-Type 判断是 HTML,交给渲染进程处理
渲染阶段
- 构建 DOM:HTML 边下载边解析。遇到没有
defer/async的<script>会暂停解析,等脚本下载并执行完再继续 - 构建 CSSOM:CSS 不阻塞 DOM 解析,但会阻塞渲染,也会阻塞后面 JS 的执行
- 生成渲染树:结合 DOM 和 CSSOM,去掉
display: none的节点 - 布局(Layout):计算每个节点的位置和大小
- 绘制(Paint):生成绘制指令,并按需拆分图层
- 合成(Composite):合成线程把图层分块、栅格化(通常借助 GPU),合成后显示到屏幕
浏览器还有一个预加载扫描器:HTML 解析被脚本阻塞时,它会继续扫描后面的内容,提前下载图片、CSS、JS 等资源。
面试官可能追问
DNS 用的是 TCP 还是 UDP?
通常用 UDP(53 端口),开销小、速度快。响应太大被截断,或者 DNS 服务器之间做区域传送时,会改用 TCP。
为什么 CSS 放在头部,JS 放在底部?
CSS 越早加载,CSSOM 越早构建,可以避免页面先无样式显示再闪一下。同步 JS 会阻塞 HTML 解析,放在底部或加上 defer,可以缩短白屏时间。
script 的 defer 和 async 有什么区别?
两者都是异步下载,不阻塞 HTML 解析。async 下载完立即执行,多个脚本之间不保证顺序;defer 等 HTML 解析完成后、DOMContentLoaded 之前,按书写顺序执行。有依赖关系的脚本用 defer,独立的统计脚本可以用 async。
TCP 握手为什么是三次,不是两次?
双方都需要确认对方能正常收发数据,并同步各自的初始序列号。另外,如果只握手两次,网络中滞留的旧连接请求到达服务器后,服务器会直接建立一个没人用的连接,浪费资源。
易错点
- 强缓存命中时根本不发请求,也就没有 DNS 解析和 TCP 连接
- 渲染树里没有
display: none的节点,但有visibility: hidden的节点
AI 模拟面试官
用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮
登录后就可以和 AI 面试官对练,面试记录也会保存下来。登录
这道题你掌握了吗?
选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。
学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。