核心原理

详解 浏览器渲染
Browser Rendering Pipeline

从 HTML 字节到屏幕像素 —— 深入理解浏览器将代码转化为可视化页面的六个关键步骤, 以及如何利用这些知识打造高性能 Web 应用。

6 个核心阶段关键渲染路径性能优化策略

什么是浏览器渲染?

浏览器渲染是将 HTML、CSS 和 JavaScript 转化为屏幕上可视化像素的过程。 这个过程涉及多个关键步骤:解析 → 构建树 → 布局 → 绘制 → 合成。 理解渲染流水线是优化 Web 性能的基础 —— 每一帧的渲染目标是在 16.6ms(60fps) 内完成,任何超出这个时间的操作都可能导致用户感知到卡顿。

渲染流水线 6 步走

1

解析 HTML → DOM 树

DOM Tree Construction

浏览器接收 HTML 字节流,通过分词器(Tokenizer)将其转化为 Token,再构建成 DOM 节点树。遇到 <script> 标签会阻塞解析,遇到 async/defer 则异步处理。

字节 → 字符 → Token → 节点 → DOM 树
遇到 <link> 不阻塞 HTML 解析,但阻塞渲染
遇到 <script> 默认阻塞 HTML 解析
预解析器(Preload Scanner)提前发现外部资源
2

解析 CSS → CSSOM 树

CSSOM Construction

浏览器解析所有 CSS 来源(内联、外链、继承),构建 CSSOM(CSS Object Model)树。CSS 是渲染阻塞资源,解析完成前页面不会渲染。

CSS 下载和解析不阻塞 DOM 解析
但 CSSOM 构建完成前会阻塞渲染
CSS 选择器从右向左匹配以提升效率
样式继承和层叠在此阶段计算
3

合并 → 渲染树

Render Tree

将 DOM 树和 CSSOM 树合并为渲染树(Render Tree)。只包含可见节点:display:none 的元素不包含,visibility:hidden 仍占据空间并包含在内。

排除 display:none 和 <head> 等不可见节点
visibility:hidden 仍占据布局空间
每个可见节点存储对应的计算样式
伪元素 (::before / ::after) 也会生成节点
4

布局(回流)

Layout / Reflow

计算渲染树中每个节点的几何信息——位置(x, y)和尺寸(width, height)。也称为「回流」。输出盒模型信息,以视口坐标为基准。

计算每个元素的确切位置和大小
基于盒模型:content + padding + border + margin
根节点是 <html>,布局以视口为坐标系
Flex/Grid 布局在此阶段完成复杂计算
5

绘制(光栅化)

Paint / Rasterization

将布局信息转化为屏幕上的实际像素。浏览器创建绘制记录(Paint Records),然后光栅化线程将指令转化为位图。通常分为多层(Layers)进行。

绘制记录描述:背景 → 文字 → 阴影等顺序
光栅化将矢量指令转为位图像素
GPU 参与纹理上传和合成
分层(Layer)可优化重绘范围
6

合成(Composite)

Compositing

合成器(Compositor)将各层按照正确的顺序(z-index、层叠上下文)合并为最终图像,发送到屏幕。合成是最高效的操作,因为它只移动图层而不重新布局或绘制。

独立层(will-change / transform)可单独合成
合成由 GPU 高效处理,不影响主线程
translate / opacity 动画可跳过布局和绘制
层爆炸(Layer Explosion)反而会降低性能

关键渲染路径 可视化

收到 HTML0ms
构建 DOM~100ms
请求 CSS并行
构建 CSSOM~200ms
合并渲染树~250ms
Layout~260ms
Paint~280ms
首屏渲染~300ms

关键渲染路径 (Critical Rendering Path) 指从收到 HTML 到首次渲染像素之间必须完成的所有步骤。 优化 CRP 的目标是最小化关键资源数量最小化关键路径长度最小化关键字节数

回流 vs 重绘

Reflow(回流)

高开销

修改了几何属性(尺寸、位置),浏览器需要重新计算布局树。

常见触发条件
增删可见 DOM 元素
修改 width / height / margin / padding
修改窗口大小(resize)
读取 offsetWidth / clientWidth 等属性
修改字体大小 / 内容变化
激活 CSS 伪类(:hover)

Repaint(重绘)

中开销

修改了外观属性但不影响布局,浏览器只需重新绘制受影响的区域。

常见触发条件
修改 color / background-color
修改 visibility
修改 box-shadow / outline
修改 border-radius(仅视觉)

性能优化 实战策略

减少回流 (Reflow)

批量修改样式:使用 cssText 或 class 切换
使用 transform 代替 top/left 动画
避免频繁读取 offsetWidth 等布局属性
使用 documentFragment 批量操作 DOM

减少重绘 (Repaint)

将频繁变动元素提升为独立图层 (will-change)
使用 opacity 做透明度动画
避免使用 box-shadow 的大范围模糊
隐藏元素修改后再显示

优化关键渲染路径

CSS 放 <head>,JS 放 </body> 前或使用 defer
内联关键 CSS,异步加载非关键 CSS
减少关键资源数量和文件大小
使用 preload / prefetch 预加载资源

合成层优化

使用 transform 和 opacity 做动画
合理使用 will-change(不要滥用)
减少合成层的数量(避免层爆炸)
利用 content-visibility: auto 跳过离屏渲染

渲染引擎 架构对比

Blink
Chrome / Edge / Opera
多进程架构,每个 Tab 独立进程
V8 引擎执行 JS
Skia / DirectWrite 绘制
Compositor 线程处理合成
Gecko
Firefox
Quantum 项目并行化渲染
Stylo 引擎用 Rust 重写样式系统
WebRender 基于 GPU 的合成
Servo 引擎集成研究
WebKit
Safari
Nitro (JavaScriptCore) 引擎
单进程模型为主
Metal 图形后端 (macOS)
对 iOS 电量优化深度适配

核心要点速记

01

渲染流水线:HTML → DOM → CSSOM → Render Tree → Layout → Paint → Composite,六步缺一不可。

02

CSS 是渲染阻塞资源,JS 既阻塞解析又阻塞渲染。合理使用 async / defer / preload 解耦。

03

Reflow 代价最高 —— 修改几何属性触发布局重算。尽量用 transform/opacity 实现动画。

04

合成层 (Composite) 由 GPU 处理,是最高效的更新路径。善用 will-change 但切勿滥用。