Appearance
浏览器渲染原理
目录
- 2. DOM 构建过程
- 3. CSSOM 构建过程
- 4. 渲染树(Render Tree)构建
- 5. 布局(Layout/Reflow)
- 6. 绘制(Paint)
- 7. 合成(Composite)
- 8. 关键渲染路径优化
浏览器渲染页面的完整流程如下:
- 解析 HTML 构建 DOM 树
- 解析 CSS 构建 CSSOM 树
- 合并 DOM 和 CSSOM 构建渲染树
- 布局 计算元素位置和尺寸
- 绘制 将元素像素化
- 合成 将各层合并显示
2. DOM 构建过程
2.1 HTML 解析
HTML 解析器将 HTML 字节流转换为 DOM 树的过程:
- 字节解码:将网络接收的字节数据解码为字符
- 标记化(Tokenization):将字符流解析为标记(开始标签、结束标签、文本等)
- 树构建:根据标记构建 DOM 树
示例:HTML 解析过程
html
<!DOCTYPE html>
<html>
<body>
<h1>Hello World</h1>
</body>
</html>解析器会生成以下标记:
DOCTYPEStartTag: htmlStartTag: bodyStartTag: h1Characters: Hello WorldEndTag: h1EndTag: bodyEndTag: html
2.2 DOM 树生成
DOM(Document Object Model)树是 HTML 文档的内存表示,每个 HTML 元素对应一个 DOM 节点。
DOM 树特点:
- 根节点是
document - 父子关系反映 HTML 嵌套结构
- 包含所有 HTML 元素,包括不可见元素(如
<script>、<meta>) - 不包含 CSS 样式信息
3. CSSOM 构建过程
3.1 CSS 解析
CSS 解析过程与 HTML 类似:
- 字节解码:将 CSS 字节流解码为字符
- 标记化:识别选择器、属性、值等
- 规则构建:构建 CSS 规则对象
示例:CSS 解析
css
body {
font-size: 16px;
color: #333;
}
h1 {
font-weight: bold;
}解析后生成两条 CSS 规则,每条规则包含选择器和声明块。
3.2 CSSOM 树生成
CSSOM(CSS Object Model)树是 CSS 样式的内存表示。
CSSOM 树特点:
- 树形结构,继承关系反映 CSS 继承规则
- 包含所有样式规则
- 计算最终样式时需要考虑优先级(特异性)、继承和层叠
样式计算过程
- 收集规则:收集所有适用于元素的 CSS 规则
- 计算特异性:确定规则优先级
- 应用层叠:按优先级覆盖样式
- 继承:应用父元素继承的样式
- 默认值:填充未指定的默认值
4. 渲染树(Render Tree)构建
渲染树由 DOM 树和 CSSOM 树合并生成,只包含需要渲染的元素。
构建过程
- 遍历 DOM 树:从根节点开始遍历每个可见节点
- 过滤不可见节点:
- 排除
display: none的元素 - 排除
<script>、<meta>等不可见元素
- 排除
- 匹配样式:为每个可见节点匹配对应的 CSSOM 规则
- 创建渲染对象:生成 RenderObject 节点
渲染树 vs DOM 树
| 特性 | DOM 树 | 渲染树 |
|---|---|---|
| 包含内容 | 所有 HTML 元素 | 仅可见元素 |
| 样式信息 | 无 | 有 |
| 用途 | JS 操作、语义 | 渲染显示 |
5. 布局(Layout/Reflow)
布局阶段计算渲染树中每个节点的几何信息(位置和尺寸)。
布局过程
- 从根节点开始:从
<html>根元素开始递归计算 - 盒模型计算:根据 CSS 盒模型计算宽高、边距、边框、填充
- 定位计算:确定元素在视口中的具体位置
- 流式布局:根据文档流排列元素
触发重排(Reflow)的操作
- 添加/删除 DOM 元素
- 元素位置变化
- 元素尺寸变化(宽高、边距、边框等)
- 内容变化(文本、图片尺寸)
- 浏览器窗口大小变化
- 获取某些属性(offsetWidth、offsetHeight、clientWidth、clientHeight、scrollTop 等)
6. 绘制(Paint)
绘制阶段将渲染树节点转换为屏幕上的像素。
绘制过程
- 分层绘制:将渲染树分为多个图层
- 填充像素:为每个图层绘制像素(颜色、图片、阴影等)
- 记录绘制命令:保存绘制操作的指令列表
绘制顺序(Stacking Context)
- 背景和边框
- 负 z-index 的子元素
- 常规流中的块级元素
- 浮动元素
- 常规流中的行内元素
- 正 z-index 的子元素
触发重绘(Repaint)的操作
- 颜色变化
- 背景变化
- 阴影变化
- 透明度变化(opacity)
- visibility 变化
注意:重绘不一定触发重排,但重排一定触发重绘。
7. 合成(Composite)
合成阶段将绘制好的图层合并为最终的屏幕图像。
合成过程
- 图层排序:按 z-index 顺序排列图层
- 图层合成:将多个图层合并为一个最终图像
- 显示到屏幕:将最终图像显示在屏幕上
硬件加速
现代浏览器使用 GPU 进行合成,支持硬件加速的属性:
transformopacityfilterwill-change
这些属性的变化不会触发重排和重绘,只会触发合成,性能最优。
8. 关键渲染路径优化
8.1 优化 DOM
- 减少 DOM 节点数量
- 避免深层嵌套
- 使用语义化 HTML
8.2 优化 CSS
- 关键 CSS 内联:将首屏所需 CSS 内联到 HTML 中
- 延迟加载非关键 CSS:使用
media属性或 JavaScript 异步加载 - 简化选择器:避免过于复杂的 CSS 选择器
- 减少 CSS 规则数量
8.3 优化 JavaScript
- 异步加载脚本:使用
async或defer - 避免阻塞渲染的 JS:将脚本放在
</body>前 - 减少 DOM 操作:批量操作 DOM
- 避免强制同步布局:避免在修改样式后立即读取布局属性
8.4 优化渲染性能
- 减少重排和重绘:使用
transform和opacity替代 top/left/width/height - 使用 GPU 加速:合理使用
will-change和transform - 避免频繁的布局抖动:不要在循环中读取布局属性
- 使用 requestAnimationFrame:将视觉变化放在
requestAnimationFrame中执行
8.5 使用开发者工具
- Performance 面板:记录和分析渲染性能
- Layers 面板:查看图层分层情况
- Rendering 面板:开启 Paint flashing、Layer borders 等调试选项
总结
浏览器渲染管道是一个复杂的过程,理解每个阶段的工作原理对于优化网页性能至关重要。通过优化关键渲染路径,可以显著提升页面加载速度和用户体验。