技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTBR

浏览器渲染流程与 Composite(合成)

所属馆藏
Browser
文件格式
Markdown
原始路径
Browser/31-浏览器渲染流程&Composite(渲染层合并)简单总结
本文目录10 个章节
  1. 一、从请求到像素
  2. 二、什么是层
  3. 三、哪些情况可能产生合成层
  4. 四、绘制列表和图块
  5. 五、合成为什么可能更快
  6. 六、隐式合成和层爆炸
  7. 七、常见优化方式
  8. 八、如何在 DevTools 中观察
  9. 九、结论
  10. 参考资料

浏览器渲染流程与 Composite(合成)

Category(分类): Browser Status: 已更新

本文保留早期文章中“渲染层合并”的学习路线,同时把 WebKit/旧版 Chrome 的内部名词与现代浏览器实现区分开。RenderLayer、GraphicsLayer、纹理和 GPU 是理解历史资料的好入口,但它们不是 Web 平台 API,也不是今天所有浏览器都完全相同的内部结构。

一、从请求到像素

页面从网络到屏幕,通常可以抽象为:

导航
  -> DNS / 连接 / TLS / HTTP
  -> HTML、CSS、JavaScript 和其他资源
  -> DOM、CSSOM、样式计算
  -> Layout / fragment tree
  -> Paint display list
  -> Layerize / property trees
  -> Rasterize tiles
  -> Composite / Draw
  -> 屏幕

现代渲染流水线示意

这不是每一帧都必须完整执行的固定流水线:

  • 没有 DOM 或样式变化时,不必重新布局;
  • 仅改变某些合成属性时,可能只更新合成状态;
  • 只改变颜色、背景或阴影时,可能跳过布局但仍需重新绘制;
  • 滚动、输入、动画、视口变化和资源加载可能触发不同范围的更新;
  • 浏览器也可能合并、延迟、取消或增量处理工作。

1. Layout、Paint、Raster 和 Composite 分别做什么

  • Layout:计算参与布局的盒子或 fragment 的尺寸和位置;
  • Paint:把背景、文本、边框、阴影、图片等记录为绘制指令/显示列表;
  • Raster:执行绘制指令,生成图块位图或纹理;
  • Composite:按照层、裁剪、变换、透明度和滚动状态,把已栅格化内容合成为最终画面。

早期文章把 Paint 也称作“绘画”,把 Raster 也混称为“光栅化”。学习时应把它们区分开:记录绘制指令和执行绘制指令不是同一件事。

二、什么是层

1. 层叠上下文不是合成层

CSS 的层叠上下文决定绘制顺序和层叠关系,常见创建条件包括根元素、定位元素配合 z-index、非 1 的 opacitytransformfilterisolation: isolate、某些 will-change 值等。

但层叠上下文不等于浏览器一定会创建独立的合成层。一个元素可以创建层叠上下文,却仍然和其他内容一起绘制;浏览器是否把它提升为独立合成资源,取决于动画、滚动、裁剪、视频、重叠关系、平台能力和内存预算。

2. RenderLayer 和 GraphicsLayer:历史模型

早期 WebKit/Chrome 资料常使用下面的概念:

  • RenderLayer:围绕 DOM 子树和层叠关系组织渲染层;
  • GraphicsLayer:可以作为独立绘制/纹理提交的图形层;
  • GraphicsContext:记录该层的绘制操作;
  • 纹理:可以理解为供合成阶段使用的位图数据。

这个模型仍有助于解释“为什么重叠和透明度需要正确的绘制顺序”,但现代 Chromium 的实现还包括布局片段、属性树、绘制块、合成图层、Viz 和 GPU/CPU 栅格化路径。不要把旧名词当成 Chromium 当前所有代码路径的精确类图。

图层树和绘制列表示意

三、哪些情况可能产生合成层

浏览器的合成启发式会持续变化,以下只能作为常见方向,不能当作保证:

  • 正在执行的 transformopacity 动画;
  • 视频、WebGL、部分 canvas 和需要独立更新的滚动内容;
  • 固定/粘性定位、滚动容器、裁剪和遮罩等复杂场景;
  • 某些 filter、混合和 3D 变换;
  • will-change 提前提示浏览器;
  • 为了隔离重绘区域或满足合成顺序而进行的内部提升。

以下说法都过于绝对:

  • 设置 z-index 就一定创建合成层;
  • 设置 opacity 就一定把元素交给 GPU;
  • 使用 translateZ(0) 就一定更快;
  • 每个 DOM 节点都有一个独立图层;
  • 所有 transform 都不需要 Paint。

可以使用 DevTools 的 Layers、Rendering 和 Performance 面板确认某个版本、设备和页面的实际合成原因。

四、绘制列表和图块

渲染主线程会为需要更新的内容记录绘制操作,例如:

绘制背景 -> 边框 -> 文本 -> 阴影 -> 图片 -> 子元素

绘制列表示意

绘制列表通常会被划分为适合处理的图块。图块大小、数量、优先级和栅格化方式由浏览器和设备决定,不应把 256 × 256512 × 512 当成固定规范。

图块栅格化示意

现代浏览器可能使用 GPU 栅格化,也可能使用 CPU 或在不同内容、驱动和设备条件下回退。即使最终合成使用 GPU,生成绘制列表、样式计算和部分栅格化也可能占用主线程或 CPU。

低分辨率占位和首屏

一些浏览器为了尽快显示首屏,可能先处理视口附近或低质量的内容,再替换成完整结果。这是实现优化,不是所有浏览器、资源和页面都遵循的固定步骤。

五、合成为什么可能更快

当动画只改变合成器能够处理的属性时,浏览器可以复用已经绘制和栅格化的位图,只更新变换矩阵、透明度或滚动偏移:

.card {
  transition: transform 240ms ease, opacity 240ms ease;
}

.card.is-moving {
  transform: translate3d(0, 0, 0);
  opacity: 0.8;
}

这可能跳过布局和 Paint,但并不意味着 JavaScript、事件处理或主线程永远不影响动画。长任务、频繁样式变化、内容重绘、内存压力和合成器无法处理的输入事件仍可能造成卡顿。

will-change 的正确用法

will-change 是提示,不是“打开 GPU 开关”:

const panel = document.querySelector('.panel')

function prepareAnimation() {
  panel?.style.setProperty('will-change', 'transform')
}

function finishAnimation() {
  panel?.style.removeProperty('will-change')
}

实际项目中更适合在动画即将开始前设置,并在结束后移除。长期给大量元素设置会提前分配资源、增加内存占用、扩大绘制区域,甚至降低性能。will-change: topwill-change: left 也不会把布局属性变成合成属性;改变它们仍可能触发布局。

六、隐式合成和层爆炸

旧版 Chrome 资料常把“一个低层叠级元素被提升后,上方重叠元素也被提升”的现象称为隐式合成,并用它解释层爆炸。这个现象在某些实现和场景中确实可能出现,但现代浏览器会通过合成原因、重叠测试、图层合并和资源预算做更多优化,不能使用一条旧规则推断所有图层数量。

层爆炸的实际风险包括:

  • 大量独立位图或纹理占用 GPU/系统内存;
  • 图层上传、栅格化和合成调度成本增加;
  • 高 DPR 屏幕上的纹理尺寸被放大;
  • 过度使用 will-change 或 3D 变换导致滚动和动画更差。

排查时应在 Performance 中录制真实交互,结合 Layers/Rendering 查看图层尺寸和合成原因,而不是盲目给每个元素加 z-indextranslateZ(0)

七、常见优化方式

  1. 先减少需要绘制的内容:缩小绘制区域,避免超大阴影、复杂滤镜、巨大透明层和不必要的重叠;
  2. 动画优先尝试 transformopacity:确认实际 trace 中确实跳过了不必要的 Layout/Paint;
  3. 控制合成层数量和尺寸:合成层不是越多越好,尤其要注意移动端和高 DPR;
  4. 批量更新 DOM 和样式:合并 class 变化,避免读写交错造成强制同步布局;
  5. 使用 CSS containment 或 content-visibility 做有边界的隔离:先验证布局、可访问性和滚动占位是否符合需求;
  6. 使用 requestAnimationFrame 组织视觉更新:不要把它误解为强制每次都能产生一帧;
  7. 用工具验证:以长任务、Layout、Paint、Raster、Composite、LCP 和 INP 等真实数据为依据。

八、如何在 DevTools 中观察

Chrome DevTools 的 Performance 录制可以查看:

  • Main 线程的 JavaScript 和长任务;
  • Recalculate StyleLayoutPaint
  • 合成、栅格化和帧时间;
  • Layout Shift、交互延迟和资源加载;
  • 高级 Paint instrumentation 生成的绘制详情。

Rendering 面板可辅助显示 FPS、Paint flashing、Layout Shift regions 和 layer borders。Layers 面板适合查看图层大小、原因和绘制内容,但面板名称、入口和展示细节会随 DevTools 版本变化。

九、结论

Composite 的价值不是“把所有工作交给 GPU”,而是让浏览器在合适的情况下复用已经完成的绘制结果,只更新变换、透明度、滚动或层之间的关系。正确的优化顺序是:

测量 -> 找到 Layout/Paint/Raster/Composite 瓶颈
     -> 减少内容和更新范围
     -> 选择合适的 CSS/DOM 策略
     -> 再次测量验证

不要把历史文章中的固定层规则、translateZ(0) 或“硬件加速万能”当作性能军规。

参考资料

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS