当浏览器接收到 HTML 文档后,会创建一个渲染任务,并启动整个渲染流程。这个流程包括以下几个关键阶段:
一、解析 HTML → 构建DOM树
- 过程:逐行解析并构建DOM(文档对象模型)树。DOM树表示页面的结构,每个HTML标签对应一个节点。
- 细节:
- 预解析优化:现代浏览器会启动预解析线程,提前下载外部资源(如CSS、JS、图片)。
- 阻塞问题:遇到
<script>
标签(无async/defer
)会暂停HTML解析,等待脚本下载并执行(因JS可能修改DOM)。
二、 解析CSS → 构建CSSOM树
- 过程:解析所有CSS(默认、内联、外部、行内样式),生成CSSOM(CSS对象模型)树,确定每个节点的样式规则。
- 细节:
- 渲染阻塞:CSSOM 构建会阻塞页面渲染(避免FOUC,即未样式化内容的闪烁)。
- 媒体查询:仅当媒体条件匹配时,对应的CSS才会阻塞渲染,否则异步加载。
三、 合并DOM与CSSOM → 生成渲染树(Render Tree)
- 过程:将 DOM树 与 CSSOM 树合并,生成仅包含可见节点的渲染树。
- 细节:
- 遍历DOM树:过滤不可见节点(如
display: none
)。 - 匹配CSSOM样式:计算每个节点的最终样式(层叠、继承规则)。
- 动态更新:JS 修改 DOM 或 CSSOM 时,可能触发渲染树重建。
- 遍历DOM树:过滤不可见节点(如
四、 布局(Layout/Reflow) → 生成布局树
- 过程:计算渲染树中每个节点的几何信息(位置、尺寸),生成布局树,也称重排。
- 细节:
- 视口尺寸:基于视口大小计算布局,响应式设计依赖于此。
- 性能成本:频繁触发布局(如循环中修改元素尺寸)会导致性能问题。
五、 绘制(Paint) → 进行栅格化
- 过程:将布局结果转换为屏幕上的像素,生成绘制指令列表(如填充颜色、绘制边框)。
- 细节:
- 分层绘制:浏览器将页面分为多个图层(如
will-change
、transform
元素单独分层),提升绘制效率。 - 重绘(Repaint):外观变化(如颜色)触发重绘,无需重新布局。
- 分层绘制:浏览器将页面分为多个图层(如
六、 合成(Composite) → 显示到屏幕
- 过程:将各图层按顺序合并,最终显示到屏幕上。
- 细节:
- GPU加速:某些图层由GPU处理(如CSS 3D变换),提高合成效率。
- 跳过布局与绘制:仅修改合成属性(如
transform
、opacity
)可跳过前两步,直接合成。
关键优化点
-
减少重排与重绘:
- 使用
transform
和opacity
实现动画,跳过布局/绘制。 - 避免频繁操作DOM,合并多次修改(如使用
DocumentFragment
)。
- 使用
-
异步加载资源:
- 使用
async/defer
延迟JS执行,避免阻塞DOM构建。 - 非关键CSS异步加载或内联。
- 使用
-
利用分层技术:
- 将频繁变化的元素提升为独立图层(谨慎使用,过多图层消耗内存)。
-
防抖/节流:
- 优化滚动、调整窗口等高频事件的处理器。