一、React Fiber 架构
React Fiber 是 React 16+ 引入的协调引擎,代替了旧的栈调和( stack reconciler )。其核心目标是将不可中断的长任务拆分为可中断的增量任务,提升应用响应速度。
Fiber 架构的核心结构: Fiber 节点
每个元素对应一个 Fiber 节点,储存组件的类型 、 状态( state/props ) 、 副作用(如 DOM 更新) 、 子节点/兄弟节点等信息。Fiber 树(工作进度树)通过链表结构连接所有的 Fiber 节点,支持增量遍历。
与旧的树形递归结构不同, Fiber 将组件树构建成一个链表。每个 Fiber 通过 return (执行父节点) 、 child (指向第一个子节点) 、 sibling(执行下一个兄弟节点)指针连接起来。这种结构使得 React 可以 增量地遍历树,而不是一次性递归到底。
Fiver 架构图关键流程:
- 协调阶段
- 提交阶段
- 调度器
1. 协调阶段( Reconciliation ,可中断)
这个阶段的主要任务是构建新的 workInProgress 树,并与 current 树进行比较( Diff ) Props/state ,计算出需要更新的节点(标记为增、删、改等副作用)。
使用 requestIdleCallback 或 requestAnimationFrame 拆分任务,每完成一个 Fiber 节点检测是否有更高优先级任务(如用户输入),若有则打断当前任务,保留进度后继续。
- 特点 :此阶段是纯计算,不涉及任何真实 DOM 操作,因此可以被中断、暂停或丢弃
- 过程 : React 会遍历 Fiber 链表,逐个处理工作单元。如果发现有更高优先级的任务(如用户输入),它会暂停当前的渲染工作,优先处理紧急任务,处理完再回来继续
2. 提交阶段( Commit ,不可中断)
当协调阶段完成后,所有需要进行的 DOM 变更都已经计算完毕。提交阶段的任务就是将这一些变更一次性、原子化应用到真实 DOM 上。
- 特点 :此阶段不可中断
- 原因 :为了保证 UI 的一致性。如果提交过程被中断,用户可能看到新旧数据混合的、不一致的画面
- 过程 :主要包括
getSnapshotBeforeUpdate生命周期、进行真实 DOM 操作(插入、更新、删除)、执行useLayoutEffect和componentDidMount/Update等
3. 调度器
- 管理任务列表,根据优先级决定执行顺序
- 使用
requestIdleCallback或MessageChannel实现任务分片
二、Fiber 解决的核心问题
1. 可中断更新( Incremental Rendering)
旧版栈调和(Stack Reconciler)使用递归遍历组件树,一旦开始无法中断。若组件庞大,长任务会阻塞主线程,导致页面卡顿(如输入延迟 、 动画掉帧)。
Fiber 通过将任务拆分为微任务单元(每个 Fiber 节点为一个单元),利用浏览器的空余时间(requestIdleCallback)或时间切片(requestAnimationFrame)执行。每完成一个单元,检测是否有更高级优先级的任务(如用户交互),若有则暂停当前任务并保存进度(通过 Fiber 节点的链表结构记录当前处理位置),后续恢复时执行。
2.优先级调度( Priority Scheduling )
Fiber 为不同类型的更新分配了优先级(如用户输入事件 > 数据加载 > 列表渲染)。高优先级任务可中断第优先级的任务,确保关键操作(如按钮点击)快速响应。
- Immediate:用户输入 、 错误处理,立即执行
- UserBlocking:动画 、 点击状态变化,尽快执行
- Normal:数据请求后的列表渲染,可中断
- Low/Idle:非关键日志 、 延迟加载,低优先级执行
三、双缓存树( Double Buffering )
Fiber 使用双缓存技术管理 Fiber 树,解决“如何高效生成下一帧 UI ”的问题。
1. 双缓存树的定义
- 当前树(
Current Tree):对应当前屏幕显示的 UI ,已完成提交状态 - 工作进度树(
WorkInProgress Tree):正在协调阶段构建的下一帧 UI 树
2. 工作流程
- 初始时,
current tree指向当前树 - 当需要更新时,基于
current tree的 Fiber 节点克隆生成workInProgress tree(浅拷贝,复用大部分节点) - 协调阶段修改
workInProgress tree的属性(如更新state),标记副作用 - 提交阶段完成后,
workInprogress tree变成新的current tree(通过指针交换),旧current tree变成为下一次的workInProgress tree(节点被复用)
3. 优势
- 减少内存开销:复用 Fiber 节点,避免频繁创建/销毁对象
- 可中断:如果构建过程被打断,可以安全地丢弃
WorkInprogress Tree - 高效切换:通过指针交换快速完成切换,无需重新构建整棵树
四、为什么需要 Fiber
根本原因是前端应用的复杂度提升,旧版栈调和无法满足性能条件:
- 长时间阻塞主线程:栈调和的递归特性导致无法中断,复杂组件树可能会导致页面的卡断(如滚动时延迟输入)
- 缺乏优先级控制:所有的更新按顺序执行,低优先级任务(如列表渲染)可能阻塞高优先级任务(如用户点击)
- 无法感知任务耗时:无法统计单个组件的渲染时间,难以针对性优化
Fiber 通过以下方式解决:
- 可中断的增量渲染:将长任务拆分为微任务,避免阻塞主线程
- 优先级调度:确保关键任务优先执行,提升用户体验
- 双缓存树:高效生成下一帧 UI,减少内存和计算开销
且 Fiber 支持
- 并发特性 :为
Suspense、Time Slicing等特性提供底层支持,例如异步加载组件时保持洁面响应 - 错误边界和调试 :
- 每个 Fiber 节点可捕获子树错误,避免整个应用奔溃
- 支持时间旅行,优化开发者工具体验