FE-03-浏览器渲染原理
本节目标:理解浏览器从 URL 输入到页面呈现的完整流程,掌握 DOM/CSSOM/渲染树/布局/绘制/合成的各个阶段,知道如何优化。
1. 浏览器架构
现代浏览器(以 Chromium 为例)是多进程架构:
1 | ┌─────────────────────────────────────────────────┐ |
为什么多进程:
- 稳定性:一个 tab 崩溃不影响其他
- 安全性:渲染进程在沙箱里,权限受限
- 性能:多个 tab 可并行
为什么有时合并进程:节省内存(多 tab 共用)。
2. URL 输入到页面呈现
1 | URL 输入 |
3. 关键概念
3.1 DOM(文档对象模型)
HTML 解析成的树形结构:
1 | <html> |
1 | Document |
3.2 CSSOM(CSS 对象模型)
1 | body { color: #333; } |
CSSOM 树结构(也是树形)。
3.3 渲染树(Render Tree)
DOM + CSSOM 合并 = 渲染树(只包含可见元素):
display: none的元素不在渲染树visibility: hidden的元素在渲染树(占位但不可见)<head>,<meta>,<script>不在渲染树
3.4 布局树(Layout Tree)
渲染树 → 布局树,包含每个节点的盒模型信息(x, y, width, height, margin, padding 等)。
4. 重排(Reflow / Layout)
布局阶段计算元素几何信息的过程。DOM 变化、样式变化、读取某些属性都可能触发重排。
触发重排的操作:
1 | // DOM 增删改 |
重排开销:可能影响整个文档树(或子树)。
5. 重绘(Repaint)
绘制阶段把元素绘制到屏幕。几何信息没变,只改外观。
只触发重绘(不重排):
color,background,border-color,box-shadowvisibility: hidden(元素仍占位)outline
触发重排 + 重绘:
width,height,margin,paddingtop,left,right,bottom(定位属性)display,position,floatfont-size,font-family,line-height
只触发合成(最便宜):
transform: translate/scale/rotateopacityfilterwill-change: transform
6. 性能优化原则
6.1 减少重排次数
批处理 DOM 变更:
1 | // 错:3 次重排 |
离线 DOM 操作:
1 | // 错:每次循环都触发重排 |
避免强制同步布局:
1 | // 错:连续读 offsetHeight 触发多次重排 |
6.2 减少重绘范围
1 | /* 用 transform 而不是 left/top */ |
6.3 提升合成层
触发层提升的属性:
1 | .layer { |
注意:不要滥用层(每个层都占显存)。一般只对动画元素用。
7. 关键渲染路径(CRP)
Critical Rendering Path:从 HTML/CSS/JS 到首次绘制(First Paint)的过程。
优化目标:缩短关键渲染路径时间。
7.1 渲染阻塞资源
1 | <head> |
优化方法:
1 | <!-- 关键 CSS 内联 --> |
defer vs async:
defer:按顺序执行,DOMContentLoaded 前async:下载完就执行,顺序不保证
7.2 资源加载优先级
1 | <!-- 高优先级:阻塞渲染的关键资源 --> |
8. 浏览器事件循环(Event Loop)
1 | console.log('1'); |
宏任务 vs 微任务:
- 宏任务:setTimeout, setInterval, I/O, UI 渲染
- 微任务:Promise.then, queueMicrotask, MutationObserver
事件循环:
1 | 执行栈 (Call Stack) → 同步代码 |
requestAnimationFrame 在下一次重绘前执行(不是微任务)。
9. 实战:性能优化清单
- 减少 DOM 树深度
- 用 CSS
transform/opacity做动画 - 长列表用虚拟滚动(react-window、vue-virtual-scroller)
- 图片用
loading="lazy"+decoding="async" - CSS 放在
<head>,JS 放<body>末尾或用 defer - 大 CSS 拆成关键路径 + 非关键(异步加载)
- 用
content-visibility: auto跳过视口外内容渲染 - 字体用
font-display: swap避免阻塞 - 避免 layout thrashing(读写交错)
- 用 Chrome DevTools Performance 面板分析
10. DevTools 实战
Performance 面板:
1 | 1. 录制操作 |
Layers 面板:
1 | 查看页面有多少合成层 |
Rendering 面板(实验性):
1 | - Paint flashing:重绘时高亮 |
小结
| 阶段 | 优化点 |
|---|---|
| 解析 | 减小 HTML/CSS 体积、关键 CSS 内联 |
| 样式 | 选择器高效(避免深嵌套) |
| 布局 | 减少重排、批处理 DOM |
| 绘制 | 减少重绘、缩小影响范围 |
| 合成 | transform/opacity 动画 |
| 加载 | preload/prefetch/async/defer |
黄金法则:
- 优先 transform/opacity(合成层最快)
- 避免 layout thrashing(读写交错)
- 批处理 DOM 变更
- 关键资源优先,非关键资源异步
- 测量,不要猜(用 DevTools)
下一节讲 JavaScript 高级:闭包、原型链、异步、模块化。
- 本文作者: CoderSong
- 本文链接: https://jack-song-gif.github.io/2026/09/29/FE-03-浏览器渲染原理/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!