浏览器渲染原理
IntermediateWeb Fundamentals理解浏览器如何将 HTML、CSS、JavaScript 转化为屏幕上的像素,是编写高性能网页的基础。
一、🔄 渲染管线概览
浏览器从接收文件到显示页面,经历以下流水线:
HTML ──► DOM 树
──► 渲染树(Render Tree) ──► 布局(Layout) ──► 绘制(Paint) ──► 合成(Composite)
CSS ──► CSSOM 树| 阶段 | 输入 | 输出 | 说明 |
|---|---|---|---|
| 解析 HTML | HTML 文件 | DOM 树 | 将标签转为节点对象的树形结构 |
| 解析 CSS | CSS 文件 | CSSOM 树 | 将样式规则转为树形结构 |
| 合并 | DOM + CSSOM | 渲染树 | 只包含可见元素及其计算后的样式 |
| 布局 | 渲染树 | 几何信息 | 计算每个元素的精确位置和大小 |
| 绘制 | 几何信息 | 像素数据 | 将元素绘制为屏幕上的像素 |
| 合成 | 图层 | 最终画面 | 将多个图层合并为最终显示的帧 |
二、🌳 DOM(Document Object Model)
2.1 什么是 DOM
DOM 是浏览器将 HTML 文档解析后生成的 树形数据结构,每个 HTML 元素对应树中的一个节点。
html
<!DOCTYPE html>
<html>
<head>
<title>页面标题</title>
</head>
<body>
<h1>Hello</h1>
<p>World</p>
</body>
</html>对应的 DOM 树:
Document
└── html
├── head
│ └── title
│ └── "页面标题"
└── body
├── h1
│ └── "Hello"
└── p
└── "World"2.2 DOM 的特点
| 特性 | 说明 |
|---|---|
| 实时性 | DOM 是"活的"——JS 修改 DOM 后,页面会实时更新 |
| 语言无关 | DOM 是一套标准接口,不限于 JavaScript |
| 可编程 | 可以通过 JS 增删改查任何节点 |
2.3 DOM 操作预览
javascript
// 获取元素
document.getElementById('title')
document.querySelector('.content')
// 修改内容
element.textContent = '新标题'
element.innerHTML = '<strong>加粗</strong>'
// 修改样式
element.style.color = 'red'
element.classList.add('active')TIP
DOM 操作是 JavaScript 控制网页的核心手段,将在 JavaScript 章节详细展开。
三、🎨 CSSOM(CSS Object Model)
3.1 什么是 CSSOM
CSSOM 是浏览器解析 CSS 后生成的树形结构,描述每个元素应该 如何显示。
css
body { font-size: 16px; }
h1 { color: blue; font-weight: bold; }
p { color: gray; }对应的 CSSOM 树:
body (font-size: 16px)
├── h1 (color: blue, font-weight: bold, font-size: 16px ← 继承)
└── p (color: gray, font-size: 16px ← 继承)3.2 CSS 阻塞渲染
浏览器必须 等 CSSOM 构建完成 后才能生成渲染树。这意味着:
- CSS 是 渲染阻塞 资源
- CSS 文件越大,首次渲染越慢
- 应将关键 CSS 放在
<head>中尽早加载
四、🖼️ 渲染树与布局
4.1 渲染树(Render Tree)
渲染树 = DOM + CSSOM,但只包含 可见元素:
| 包含 | 不包含 |
|---|---|
| 可见的 HTML 元素 | <head> 及其子元素 |
| 计算后的样式 | display: none 的元素 |
<script> 标签 |
4.2 布局(Layout / Reflow)
布局阶段计算渲染树中每个节点的 精确几何信息:
- 位置(x, y 坐标)
- 大小(宽度、高度)
- 边距、内边距
布局从根节点开始,逐级向下计算。
4.3 绘制(Paint)
将布局信息转化为屏幕上的 实际像素:
- 文本渲染
- 颜色填充
- 边框绘制
- 阴影、圆角等视觉效果
五、⚡ 重排与重绘
5.1 概念对比
| 概念 | 英文 | 触发条件 | 性能开销 |
|---|---|---|---|
| 重排 | Reflow / Layout | 元素的几何属性变化(大小、位置) | 🔴 高 |
| 重绘 | Repaint | 元素的外观变化(颜色、阴影) | 🟡 中 |
重排一定触发重绘,但重绘不一定触发重排。
5.2 触发重排的操作
- 修改元素尺寸(width、height、padding、margin)
- 添加 / 删除 DOM 节点
- 修改字体大小
- 窗口大小变化(resize)
- 读取某些属性(offsetHeight、scrollTop 等)
5.3 优化建议
| 策略 | 说明 |
|---|---|
| 批量修改样式 | 用 className 一次性修改,避免逐条修改 style |
| 脱离文档流 | 对频繁变化的元素使用 position: absolute/fixed |
| 减少 DOM 操作 | 使用 DocumentFragment 批量插入节点 |
| 避免强制同步布局 | 不要在循环中交替读写 DOM 属性 |
六、🧩 关键渲染路径优化
提升首屏加载速度的关键策略:
| 优化方向 | 具体措施 |
|---|---|
| 减少关键资源 | 合并 CSS/JS 文件,移除未使用的代码 |
| 减小资源体积 | 压缩(Minify)CSS/JS/HTML |
| 缩短关键路径 | 内联关键 CSS,异步加载非关键 JS |
| JS 加载策略 | 使用 defer 或 async 属性避免阻塞解析 |
html
<!-- 阻塞解析 -->
<script src="app.js"></script>
<!-- 不阻塞解析,DOM 就绪后按顺序执行 -->
<script src="app.js" defer></script>
<!-- 不阻塞解析,下载完立即执行(顺序不保证) -->
<script src="app.js" async></script>