news 2026/10/22 7:24:52

渲染流水线

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
渲染流水线

8.3 渲染流水线

渲染流水线是浏览器将 DOM、CSSOM 转化为屏幕可视化像素的完整执行流程,与事件循环深度协同,按固定帧率周期性执行。完整的渲染流水线分为样式计算、布局、绘制、合成四个核心阶段,不同阶段对应不同的性能开销。配合requestAnimationFrame精准控制渲染时机、requestIdleCallback利用空闲时间调度低优先级任务,可以实现渲染性能的精细化管控。


8.3.1 渲染帧的完整流程:样式 → 布局 → 绘制 → 合成

浏览器以固定帧率(通常 60fps,即每 16.67ms 一帧)周期性执行渲染流水线。每一帧都会根据最新的 DOM 与样式状态,完成从样式计算到屏幕合成的全流程,最终更新画面。并非所有场景都会走完所有阶段,根据变更的属性不同,流水线会提前终止,对应不同的性能开销。

一、样式计算(Style / Recalculate Style)
  • 核心工作:根据 CSS 样式表、类名变更、属性修改,重新计算所有受影响元素的最终计算样式(computed style)。
  • 触发场景:任何 CSS 属性、class、id 等影响样式的修改。
  • 开销程度:低,仅做样式匹配与计算,不涉及几何信息。
  • 说明:这是渲染流水线的第一步,所有视觉变更都会先经过样式计算,再决定后续流程。
二、布局(Layout / Reflow)
  • 核心工作:根据元素的样式与内容,计算元素的几何信息(位置、尺寸、排版、层级关系),生成渲染树的布局结构。
  • 触发场景:修改 width、height、margin、top、font-size 等布局属性,DOM 节点增删、内容变化等。
  • 开销程度:极高,需要递归计算元素间的位置影响,是渲染性能的核心瓶颈。
  • 分类:全局布局(影响整个文档)、局部布局(仅影响部分区域,开销更低)。
  • 对应概念:这一步就是常说的「重排(回流)」,重排后必然触发后续的绘制阶段。
三、绘制(Paint / Repaint)
  • 核心工作:根据布局结果与样式,在对应图层上填充像素,包括颜色、背景、边框、阴影、文字、图片等所有视觉像素信息。
  • 触发场景:修改 color、background、box-shadow、visibility 等不影响布局的视觉属性。
  • 开销程度:中等,像素级填充,大面积绘制开销会显著上升。
  • 对应概念:这一步就是「重绘」,仅影响视觉像素,不改变元素位置与尺寸。
  • 图层特性:浏览器会将页面分为多个图层分别绘制,减少全页面重绘的开销。
四、合成(Composite)
  • 核心工作:将所有绘制好的图层,按照正确的层级顺序、透明度、变换关系,由 GPU 混合合成为最终的屏幕画面。
  • 触发场景:修改 transform、opacity 等仅影响图层合成的属性。
  • 开销程度:极低,由 GPU 并行处理,无需 CPU 重新计算布局与像素,是性能最优的渲染阶段。
  • 核心价值:硬件加速动画的本质,就是将动画控制在合成阶段,全程不触发布局与绘制。
各阶段对比总结

阶段

核心操作

触发属性示例

性能开销

跳过条件

样式计算

计算元素最终样式

class、color、width

低

无样式变更时跳过

布局

计算几何位置尺寸

width、margin、top、font-size

极高

无布局属性变更时跳过

绘制

填充视觉像素

color、background、shadow

中等

无视觉属性变更时跳过

合成

图层混合输出

transform、opacity

极低

无图层变更时跳过

渲染优化的核心思路:尽可能让变更停留在更靠后的阶段,优先使用合成属性,避免触发布局与全量重绘。


8.3.2 requestAnimationFrame 与渲染时机

一、核心定位

requestAnimationFrame(简称 rAF)是浏览器专门为动画与渲染优化提供的原生 API,回调函数会在每帧渲染流水线开始前自动执行,与屏幕刷新率严格同步,是 JS 驱动动画的标准最佳实践。

二、执行时机

在事件循环的完整流程中,rAF 的执行节点位于:宏任务执行完毕→微任务队列清空→ requestAnimationFrame回调执行→正式执行渲染流水线

核心特点:rAF 回调恰好发生在渲染之前,此时修改的样式与布局会被当前帧的流水线一次性处理,不会出现样式与渲染不同步的掉帧问题。

三、与定时器动画的核心区别

对比维度

setInterval / setTimeout 动画

requestAnimationFrame 动画

执行时机

作为宏任务调度,与渲染时机不同步

渲染前固定执行,与帧率严格同步

帧率稳定性

容易掉帧、卡顿,回调可能落在两帧之间

自动匹配屏幕刷新率,流畅稳定

页面可见性

页面隐藏后依然执行,浪费性能

页面隐藏后自动暂停,切回后恢复

时间精度

受事件循环排队影响,时间偏差大

传入高精度时间戳,进度计算精准

四、基础用法
function animate(timestamp) { // timestamp 为高精度时间戳,单位毫秒 // 更新动画状态 element.style.transform = `translateX(${timestamp / 10}px)`; // 递归调用,持续下一帧 requestAnimationFrame(animate); } // 启动动画 requestAnimationFrame(animate);
五、典型应用场景
  • JS 驱动的逐帧动画、Canvas 动画、游戏渲染
  • 精确控制 DOM 动画的渲染时机,避免掉帧
  • 批量 DOM 修改统一在渲染前执行,减少重排重绘次数

8.3.3 空闲调度:requestIdleCallback

一、核心定位

requestIdleCallback(简称 rIC)是浏览器的空闲时间调度 API,回调会在每帧渲染完成后、页面处于空闲状态时执行。如果当前帧还有剩余时间(距离下一帧开始还有空闲),就执行空闲任务;如果帧时间已用完,则推迟到下一帧空闲时再执行,完全不影响关键渲染与交互。

二、执行时机

完整的帧周期执行顺序:宏任务→微任务→ requestAnimationFrame →渲染流水线→ requestIdleCallback(空闲时)

核心特点:优先级最低,仅利用帧的剩余时间执行,不会阻塞主线程、不会影响页面渲染与交互响应。

三、核心特性

空闲时间参数:回调接收deadline对象,包含:

  1. deadline.timeRemaining():返回当前剩余空闲时间(毫秒),任务执行前判断,避免超时。
  2. deadline.didTimeout:是否因为超时强制执行。

超时参数timeout:第二个参数可设置超时时间,超过该时间即使没有空闲也会强制执行,避免任务无限推迟。

requestIdleCallback(doIdleWork, { timeout: 2000 });

四、基础示例
function doIdleWork(deadline) { // 还有剩余时间,且有任务待处理 while (deadline.timeRemaining() > 0 && tasks.length > 0) { processTask(tasks.shift()); } // 还有任务,继续申请下一次空闲 if (tasks.length > 0) { requestIdleCallback(doIdleWork); } } requestIdleCallback(doIdleWork, { timeout: 3000 });
五、典型应用场景
  • 非紧急的后台任务:埋点数据上报、日志上报
  • 预加载与预计算:提前加载后续页面资源、大数据预计算
  • 低优先级计算:大批量数据处理、索引构建,拆分到多个空闲帧执行
  • 非关键 DOM 操作:次要元素的延迟渲染、非核心内容的更新
六、注意事项
  • 不保证执行时机,不要用于关键业务逻辑与动画。
  • 单次任务不要占用过长时间,建议拆分小任务分批执行,避免占用空闲时间过长。
  • 低版本浏览器需要 polyfill 兼容。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 7:23:56

SUAPP AI 云端建模成果:导出 skp/glb 之后要检查的三件事

下载之后,建议先检查结构能否按需修改、几何是否符合设计输入、材质显示是否适合交付用途,再决定模型进入哪一步。本文围绕模型导出、可编辑模型与成果校核展开,供使用AI建模软件的设计人员安排人工检查;三件事属于项目方法建议&a…

作者头像 李华
网站建设 2026/10/22 7:23:25

为什么 LLM 会产生幻觉?——token 级别的解释

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 7:20:01

遇到上头的买家怎么接?情绪降温三步与补偿的边界

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/22 7:18:09

On Explaining (Large) Language Models For Code Using Global Code-Based Explanations

文章主要内容总结 本文提出了一种名为CodeQ的可解释性方法,旨在通过全局代码解释来分析大型语言模型(LM4Code)的代码生成决策过程。CodeQ通过三个核心步骤实现: Rationalization:提取影响代码预测的关键输入令牌子集(rationale),通过贪心算法逐步选择对目标令牌概率贡…

作者头像 李华
网站建设 2026/10/22 7:17:09

2026免费低代码平台TOP5,中小企业数字化工具盘点

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华