从输入 URL 到页面渲染完成的完整过程
Contents
概述
整个过程可拆分为 7大核心阶段,涉及网络、浏览器内核(渲染引擎/JS引擎)、GPU 协同工作,核心目标是通过「关键渲染路径(Critical Rendering Path)」快速生成可视化页面。
7大核心阶段
阶段1:URL 解析与 DNS 域名解析(网络准备)
核心目标:将用户输入的 URL 转换为服务器 IP 地址,建立网络连接的前提。
- URL 解析:
- 浏览器解析 URL 结构(协议
http/https、域名www.example.com、端口、路径、查询参数),判断是否为合法 URL。 - 若为相对路径(如
/index.html),结合当前页面基准 URL 补全为绝对 URL。
- 浏览器解析 URL 结构(协议
- DNS 域名解析(Domain Name System):
- 核心:将域名(如
www.example.com)映射为服务器 IP 地址(如192.168.1.1)。 - 解析流程(缓存优先,减少网络请求):
- 浏览器缓存 → 操作系统缓存(如
hosts文件) → 路由器缓存 → ISP DNS 缓存。 - 若缓存未命中,发起递归 DNS 查询(本地 DNS 服务器 → 根 DNS → 顶级域 DNS → 目标域名 DNS),最终返回 IP 地址。
- 浏览器缓存 → 操作系统缓存(如
- 优化点:DNS 预解析(
<link rel="dns-prefetch" href="https://cdn.example.com">)、HTTPDNS 绕过 ISP 缓存,减少解析耗时。
- 核心:将域名(如
阶段2:TCP 连接建立(HTTPS 含 TLS 握手)
核心目标:基于 IP 地址建立可靠的端到端网络连接,确保数据传输的完整性和有序性。
- TCP 三次握手(HTTP 协议基础):
- 客户端 → 服务器:发送 SYN 包(同步序列编号),请求建立连接。
- 服务器 → 客户端:发送 SYN+ACK 包(确认客户端请求,同步自身序列编号)。
- 客户端 → 服务器:发送 ACK 包(确认服务器响应),连接建立完成。
- 核心作用:确认双方收发能力正常,协商初始序列号,避免数据丢失或重复。
- TLS 握手(HTTPS 协议必需,加密传输):
- 若协议为 HTTPS,TCP 连接建立后需额外完成 TLS 1.2/1.3 握手:
- 客户端发送支持的 TLS 版本、加密套件列表,生成随机数。
- 服务器选择加密套件,返回证书(含公钥)、随机数。
- 客户端验证证书合法性(通过 CA 根证书),生成会话密钥(用服务器公钥加密),发送给服务器。
- 双方基于会话密钥协商对称加密算法(如 AES),后续数据通过对称加密传输(高效且安全)。
- 优化点:TLS 1.3 简化握手流程(1-RTT 完成),Session Resumption 复用会话密钥,减少握手耗时。
- 若协议为 HTTPS,TCP 连接建立后需额外完成 TLS 1.2/1.3 握手:
阶段3:HTTP 请求发送与响应接收
核心目标:客户端向服务器发送资源请求,服务器返回页面核心资源(HTML/CSS/JS/图片等)。
- HTTP 请求构建与发送:
- 客户端构建 HTTP 请求报文:
- 请求行:
GET /index.html HTTP/1.1(方法、路径、协议版本)。 - 请求头:
Host: www.example.com、User-Agent: Chrome/120.0.0.0、Accept: text/html等(告知服务器客户端信息和需求)。 - 请求体:GET 方法无请求体,POST 方法包含表单数据/JSON 等(如登录请求的用户名密码)。
- 请求行:
- 基于 TCP 连接发送请求报文,服务器接收后解析请求。
- 客户端构建 HTTP 请求报文:
- HTTP 响应构建与返回:
- 服务器处理请求(如查询数据库、读取静态资源),构建响应报文:
- 状态行:
HTTP/1.1 200 OK(协议版本、状态码,200 表示成功,404 表示资源未找到)。 - 响应头:
Content-Type: text/html; charset=utf-8(资源类型和编码)、Cache-Control: max-age=3600(缓存策略)、Content-Length: 1024(资源大小)。 - 响应体:核心资源数据(如 HTML 字符串、CSS 代码、JS 脚本)。
- 状态行:
- 服务器通过 TCP 连接返回响应报文,客户端接收后关闭连接(HTTP/1.1 默认为长连接
Keep-Alive,可复用连接发送多个请求)。
- 服务器处理请求(如查询数据库、读取静态资源),构建响应报文:
- 关键优化点:
- 资源缓存:通过
Cache-Control/ETag/Last-Modified减少重复请求。 - 复用连接:HTTP/1.1 长连接、HTTP/2 多路复用(同一连接并发传输多个资源)、HTTP/3 QUIC(UDP 协议,减少连接建立耗时)。
- 压缩传输:
gzip/brotli压缩响应体(如 HTML/CSS/JS),减少传输体积。
- 资源缓存:通过
阶段4:响应解析与资源加载(关键渲染路径启动)
核心目标:浏览器解析 HTTP 响应体,提取核心资源(HTML),并递归加载依赖资源(CSS/JS/图片等),启动关键渲染路径。
- HTML 解析与 DOM 构建:
- 浏览器接收 HTML 响应体后,由 渲染引擎(如 Blink) 的 HTML 解析器处理:
- 词法分析:将 HTML 字符串拆分为 Token(如
<div>、</div>、文本节点)。 - 语法分析:根据 Token 构建 DOM 树(Document Object Model),DOM 树是页面结构的抽象表示,每个节点对应 HTML 元素/文本/属性。
- 词法分析:将 HTML 字符串拆分为 Token(如
- 关键特性:HTML 解析是增量解析(边接收 HTML 边解析,无需等待完整资源),解析过程中若遇到非阻塞资源(如图片),会并行加载;若遇到阻塞资源(如
<script>无async/defer),会暂停解析,优先加载并执行 JS。
- 浏览器接收 HTML 响应体后,由 渲染引擎(如 Blink) 的 HTML 解析器处理:
- CSS 解析与 CSSOM 构建:
- 浏览器解析 CSS 资源(内联 CSS、
<link rel="stylesheet">外部 CSS),由 CSS 解析器处理:- 词法分析:将 CSS 字符串拆分为 Token(如
body、color、red)。 - 语法分析:构建 CSSOM 树(CSS Object Model),CSSOM 树记录所有样式规则,用于计算元素最终样式。
- 词法分析:将 CSS 字符串拆分为 Token(如
- 关键特性:CSS 是渲染阻塞资源(阻塞布局和绘制),浏览器必须等待 CSSOM 构建完成后,才能进行后续的布局阶段;若 CSS 资源未加载完成,页面会呈现空白(白屏)。
- 浏览器解析 CSS 资源(内联 CSS、
- JS 加载与执行:
- JS 是双重阻塞资源:
- 阻塞 DOM 构建:解析 HTML 时遇到
<script>(无async/defer),会暂停 HTML 解析,优先加载 JS 资源,执行完成后再继续解析 DOM(因为 JS 可能通过document.write()修改 DOM)。 - 阻塞 CSSOM 构建:JS 可能通过
document.styleSheets访问 CSS 样式,因此浏览器必须等待 CSSOM 构建完成后,才能执行 JS。
- 阻塞 DOM 构建:解析 HTML 时遇到
- 优化方案:
async:JS 异步加载,加载完成后立即执行(不保证顺序),不阻塞 DOM 解析。defer:JS 异步加载,等待 DOM 解析完成后(DOMContentLoaded事件前)执行,保证加载顺序。- 动态导入:
import()函数异步加载 JS 模块,按需执行。
- JS 是双重阻塞资源:
阶段5:布局(Layout/Reflow)
核心目标:结合 DOM 树和 CSSOM 树,计算每个元素的几何信息(位置、大小、尺寸),生成 Render 树(渲染树)和布局树(Layout Tree)。
- Render 树构建:
- 筛选 DOM 树中可见元素(排除
display: none的元素、<head>标签、meta等不可见节点)。 - 将 DOM 节点与 CSSOM 样式规则匹配(样式计算),为每个可见节点分配最终样式(如
width: 200px、position: absolute)。
- 筛选 DOM 树中可见元素(排除
- 布局计算(Reflow):
- 以 Render 树为基础,从根节点(
<html>)开始,递归计算每个元素的几何属性:- 位置:
top、left、right、bottom(基于父元素坐标系)。 - 大小:
width、height、padding、margin、border。 - 其他:
font-size、line-height(影响文本布局)。
- 位置:
- 关键特性:布局是自上而下的递归过程,父元素的几何信息会影响子元素;若元素几何信息发生变化(如修改
width、display),会触发重排(重新执行布局阶段),性能开销较大。
- 以 Render 树为基础,从根节点(
- 优化点:
- 避免频繁修改几何属性(如
width、top),集中修改后批量更新。 - 使用
transform、opacity替代几何属性修改(仅触发合成阶段,不触发重排)。 - 脱离文档流(
position: absolute/fixed),减少重排影响范围。
- 避免频繁修改几何属性(如
阶段6:绘制(Paint)
核心目标:根据布局树的几何信息,将元素的视觉样式(颜色、背景、阴影、文本、边框)绘制到屏幕的像素缓冲区(Pixel Buffer)。
- 绘制流程:
- 浏览器将布局树分解为多个绘制层(Paint Layer),每个层对应一个或多个元素(如
z-index不同的元素、透明元素、视频元素),分层绘制可减少重绘范围。 - 每个层内部执行绘制操作:按顺序绘制背景色、背景图、边框、文本、阴影等,生成层的像素数据。
- 绘制方式:通过浏览器的绘制 API(如 Skia 引擎)操作 GPU 或 CPU 完成像素渲染。
- 浏览器将布局树分解为多个绘制层(Paint Layer),每个层对应一个或多个元素(如
- 关键特性:
- 绘制是像素级操作,性能开销低于重排,但频繁重绘(如修改
background-color、color)仍会影响性能。 - 重排必然导致重绘,但重绘不一定导致重排(如修改
color仅触发重绘)。
- 绘制是像素级操作,性能开销低于重排,但频繁重绘(如修改
- 优化点:
- 避免频繁修改非几何属性(如
color、background-color)。 - 合并绘制层(如避免过多
z-index嵌套),减少绘制次数。 - 使用 CSS 硬件加速(
transform: translateZ(0)),将层交给 GPU 绘制,提升效率。
- 避免频繁修改非几何属性(如
阶段7:合成(Composite)
核心目标:将所有绘制层的像素数据,通过 GPU 合成到最终的屏幕帧缓冲区(Frame Buffer),并显示在屏幕上。
- 合成流程:
- 浏览器的合成线程(Compositor Thread)接收各绘制层的像素数据,处理层的位置、透明度(如
transform: scale(1.2)、opacity: 0.8)。 - 合成线程将层按
z-index顺序排列,合并为单个屏幕帧(Frame),发送到 GPU 的帧缓冲区。 - GPU 控制显示器的刷新频率(通常 60Hz,每 16.6ms 刷新一帧),将帧缓冲区的像素数据显示到屏幕。
- 浏览器的合成线程(Compositor Thread)接收各绘制层的像素数据,处理层的位置、透明度(如
- 关键特性:
- 合成阶段是独立于主线程的(JS 执行、布局、绘制在主线程,合成在合成线程),因此修改
transform、opacity时,仅需在合成线程处理,无需触发主线程的布局和绘制,性能最优(“零重排零重绘”)。 - 若合成线程无法在 16.6ms 内生成一帧,会导致帧率下降(低于 60fps),出现页面卡顿。
- 合成阶段是独立于主线程的(JS 执行、布局、绘制在主线程,合成在合成线程),因此修改
- 优化点:
- 优先使用
transform实现动画(如平移、缩放、旋转),避免使用top、left。 - 控制动画元素的数量和复杂度,避免 GPU 过载。
- 避免大尺寸元素的频繁动画(如全屏视频、高清图片)。
- 优先使用
总结
关键渲染路径(Critical Rendering Path)
指从 HTML/CSS/JS 资源加载到合成显示的核心流程:HTML 解析 → DOM 构建 → CSS 解析 → CSSOM 构建 → Render 树构建 → 布局 → 绘制 → 合成。
核心目标:最小化首屏渲染时间(First Contentful Paint, FCP),关键是减少阻塞资源、优化布局和绘制效率。
全流程优化核心方向
| 阶段 | 核心优化手段 |
|---|---|
| DNS 解析 | DNS 预解析、HTTPDNS、缓存优化 |
| 网络连接 | 启用 HTTPS(TLS 1.3)、HTTP/2/3、长连接复用 |
| 资源加载 | 关键 CSS 内联、JS 异步加载(async/defer)、资源压缩与缓存 |
| DOM/CSSOM 构建 | 简化 HTML 结构、减少 CSS 选择器复杂度、避免阻塞资源 |
| 布局/绘制 | 避免重排重绘、使用 GPU 加速、分层优化 |
| 合成 | 优先使用 transform/opacity 实现动画 |