参考视频
- 浏览器渲染页面的流程
- 【干货】浏览器是如何运作的?
浏览器渲染机制:从 HTML 到像素的完整解析
渲染流水线概览
详细渲染阶段解析
1. 解析 HTML 构建 DOM 树
- 过程:
- 字节 → 字符 → 令牌(token化) → 节点 → DOM 树
- 遇到
<script> 标签会暂停解析,执行 JavaScript
- 优化点:
- 使用
async 或 defer 属性异步加载脚本
- 将脚本放在 body 底部
2. 解析 CSS 构建 CSSOM 树
- 特点:
- 优化点:
- 精简 CSS 选择器复杂度
- 使用媒体查询避免不必要的加载
3. 构建渲染树(Render Tree)
- 组合过程:
- DOM + CSSOM = 渲染树
- 只包含可见节点(排除
display: none 等元素)
- 关键规则:
4. 布局(Layout / Reflow)
- 计算:
- 确定所有元素的几何位置和尺寸
- 基于视口大小计算位置
- 触发条件:
5. 分层(Layer)
- 分层原因:
- 创建层条件:
- 3D 变换
- 视频/Canvas 元素
- 有动画的元素
will-change: transform 属性
6. 绘制(Paint)
7. 光栅化(Rasterization)
8. 合成显示(Compositing)
- 过程:
- 合成器线程组合所有层
- 通过 IPC 传递给浏览器进程
- 最终显示在屏幕上
- 优势:
关键渲染路径(Critical Rendering Path)

回流与重绘
1. 回流(Reflow)
定义:当渲染树(Render Tree)中的一部分或全部因为元素的尺寸、布局、隐藏等改变而需要重新构建的过程称为回流。回流会导致子元素和后续元素重新计算布局,成本很高。
触发条件(常见):
- 页面首次渲染(无法避免)
- 浏览器窗口大小改变
- 元素尺寸、位置、内容改变(如宽度、高度、内边距变化)
- 添加或删除可见的DOM元素
- 激活CSS伪类(如
:hover)
- 查询某些属性或调用某些方法(如
offsetWidth、scrollTo()等)
影响:回流会使浏览器重新计算所有受影响元素的几何属性,然后重新构建渲染树。
2. 重绘(Repaint)
定义:当元素的外观(如颜色、背景、边框等)发生改变,但不影响布局时,浏览器会重新绘制元素,这个过程称为重绘。重绘的成本通常小于回流。
触发条件:
- 颜色、背景色、边框颜色等样式改变
- 文本方向修改
- 阴影变化(但不影响布局)
visibility属性改变(注意:display: none会触发回流,而visibility: hidden只触发重绘)
关键区别:
| 特点 |
回流(Reflow) |
重绘(Repaint) |
| 触发原因 |
布局改变(几何属性) |
外观改变(非几何属性) |
| 性能影响 |
高(涉及子元素和后续元素重新布局) |
低(只重新绘制,不重新计算布局) |
| 依赖关系 |
必然引起重绘 |
不一定引起回流 |
渲染性能优化策略
1. 减少渲染阻塞
- CSS:
- 内联关键 CSS
- 使用媒体查询分割 CSS
- 避免使用
@import
- JavaScript:
1 2 3
| <script defer src="script.js"></script> <script async src="analytics.js"></script>
|
2. 优化布局和重绘
- 减少回流(Reflow):
- 避免频繁读写布局属性(offsetTop 等)
- 使用 CSS 类批量修改样式
- 使用
position: absolute/fixed 脱离文档流
- 减少重绘(Repaint):
- 使用
transform 和 opacity 实现动画
- 使用
will-change 提示浏览器
- 避免使用渐变和阴影等昂贵效果
3. 高效利用图层
1 2 3 4
| .animate-element { will-change: transform; transform: translateZ(0); }
|
4. 虚拟滚动和列表优化
- 大数据集处理:
- 实现虚拟滚动:只渲染可视区域元素
- 使用内容分块加载
- 懒加载非关键资源
5. 性能检测工具
- Chrome DevTools:
- Performance 面板分析渲染瀑布流
- Layers 面板查看图层结构
- Rendering 面板检测重绘区域
- API:
1 2 3 4 5
| const perfEntries = performance.getEntriesByType("layout"); perfEntries.forEach(entry => { console.log(`布局耗时: ${entry.duration}ms`); });
|
现代浏览器渲染优化技术
1. 合成器线程(Compositor Thread)
- 独立于主线程运行(浏览器渲染进程的主线程)
- 处理滚动、动画等无需 JS 的操作
- 直接操作已光栅化的图层
2. 时间切片(Time Slicing)
- 将大型任务拆分为小任务
- 通过
requestIdleCallback 实现
1 2 3 4 5 6 7 8
| function processTask() { if (hasMoreWork) { requestIdleCallback(processTask); } } requestIdleCallback(processTask);
|
3. 增量渲染
- 逐步显示部分渲染内容
- 优先渲染视口内内容
- 后台继续处理剩余内容
4. GPU 加速
1 2 3 4 5
| .accelerated { transform: translate3d(0, 0, 0); backface-visibility: hidden; }
|
渲染过程中的 JavaScript 交互
JS 执行对渲染的影响
- 同步 JS:
- 异步 JS:
defer:HTML 解析完成后执行
async:下载完成后立即执行
事件循环与渲染协调
- 处理模型:
- 执行 JavaScript 任务
- 处理微任务队列
- 执行渲染步骤(可选)
- 处理宏任务队列
- requestAnimationFrame:
1 2 3 4 5 6 7 8 9 10
| function update() { element.style.transform = `translateX(${position}px)`;
position += 5; if (position < 300) { requestAnimationFrame(update); } } requestAnimationFrame(update);
|
最佳时机:在浏览器重绘前执行动画更新
移动端渲染的特殊考虑
触摸事件处理:
- 300ms 点击延迟问题
- 使用 `touch-action` 优化滚动
1 2 3
| .scrollable { touch-action: pan-y; }
|
电池效率优化:
- 减少不必要的动画
- 使用
matchMedia 检测设备能力
1 2 3 4
| const isLowPower = matchMedia("(prefers-reduced-motion: reduce)").matches; if (isLowPower) { }
|
内存限制:
- 移动设备图层内存限制更严格
- 避免大型 Canvas 操作
- 及时释放不再使用的资源
未来趋势:WebGPU 和渲染新特性
- WebGPU:
- 下一代图形 API
- 更直接的 GPU 访问
- 适用于复杂 3D 和计算任务
- Houdini API:
1 2 3 4 5 6 7 8 9
| registerPaint('circle-ripple', class { paint(ctx, size) { ctx.fillStyle = 'rgba(255,0,0,0.5)'; ctx.beginPath(); ctx.arc(size.width/2, size.height/2, 50, 0, 2*Math.PI); ctx.fill(); } });
|
- 使开发者能介入渲染管线
- 创建高性能自定义渲染效果
- OffscreenCanvas:
- 在 Web Worker 中执行 Canvas 操作
- 避免阻塞主线程
1 2
| const offscreen = canvas.transferControlToOffscreen(); worker.postMessage({ canvas: offscreen }, [offscreen]);
|