React Fiber 架构的前世今生

53 阅读5分钟

一、背景:为什么需要 Fiber?

1. React 15 时代的问题

在 React 15 及更早版本中,渲染是同步、不可中断的。当 setState 触发更新时,React 会递归整棵虚拟 DOM 树,计算出差异(diff),并一次性更新真实 DOM。

这种方式在小应用中没问题,但在复杂 UI 场景下会出现严重性能问题:

  • 更新过程是 单线程、不可中断的
  • JavaScript 主线程被 React 占用时,用户交互、动画、滚动都会卡顿
  • React 无法根据任务的重要程度灵活调度(比如动画比日志输出更重要)。

📉 问题总结:

旧版 React 的渲染是「递归 + 同步」的。递归函数一旦开始执行,直到整棵树遍历完之前无法打断。这会导致主线程长时间被阻塞。


二、Fiber 的核心目标

1. 可中断的渲染

React Fiber 将同步的递归渲染改写为 可中断、可恢复的循环任务。这意味着:

  • React 渲染工作可以被切成更小的片段(fiber),
  • 每个片段在空闲时间内执行,
  • 若有更高优先级任务(如用户输入),可以中断当前渲染

🧠 目的: 不再让 React “霸占主线程”,而是让渲染像多任务调度一样可控。

2. 更精细的调度控制

Fiber 引入 优先级 (Priority) 概念,让不同类型的更新拥有不同的紧急程度。

更新类型示例优先级
用户交互输入框打字
动画组件过渡动画
网络请求结果更新异步数据渲染

这样 React 就能合理分配时间,先响应用户、后处理耗时任务

3. 持久的执行上下文

Fiber 将每个组件更新的执行信息(包括 props、state、children 等)封装为一个对象,这个对象就是 FiberNode。它可以在中断后继续恢复,不会丢失执行状态。

🌿 Fiber 的名字就来源于「纤维」:一种比线程(Thread)更轻量的执行单元。


三、Fiber 架构的核心思想

1. 从「递归」到「循环」

传统的递归渲染:

function render(element) {
  reconcile(element);
  render(element.children);
}

在 Fiber 架构中变成了手动管理的循环:

while (nextUnitOfWork) {
  nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
}

🌀 核心区别: React 不再让调用栈来管理执行顺序,而是自己保存「下一个任务指针」,从而实现可中断、可恢复的渲染调度。


2. Fiber Node(工作单元)

每个组件对应一个 FiberNode,它包含:

属性说明
type对应的组件类型(函数 / class / 原生标签)
child第一个子节点的引用
sibling下一个兄弟节点
return父节点(用于回溯)
pendingProps本次渲染的新 props
stateNode对应的 DOM 或组件实例

通过这些指针,React 可以实现「链式遍历」而不是「递归遍历」。

📘 比喻:

以前 React 是“从树顶一路递归下去”,现在是“从树顶拿着线条顺着走下去”。


3. 双缓存机制(Double Buffering)

Fiber 使用“双缓存”技术保证 UI 更新的原子性:

  • 当前显示的 UI 树称为 current fiber tree
  • 正在构建的新树称为 workInProgress fiber tree
  • 当新树构建完成后,React 会一次性将其切换为 current。

这意味着:

UI 更新是“可中断的”,但“提交到屏幕”的过程依然是“原子的”。

🧩 好处: 不会出现“渲染一半”的画面,保证 UI 一致性。


四、Fiber 渲染流程(简化版)

image.png

🪄 阶段拆分:

  1. Render Phase(可中断) :构建 Fiber 树,计算变更。
  2. Commit Phase(不可中断) :将变更一次性应用到 DOM。

五、Fiber 架构解决了什么问题?

问题Fiber 解决方式
渲染阻塞主线程将任务拆分为可中断单元
无法区分任务优先级引入 lanes / expirationTime 优先级机制
状态更新无法暂停恢复FiberNode 保存上下文,实现可恢复渲染
UI 更新不一致双缓存保证渲染原子性

六、仍然存在的问题与挑战

  1. 调度粒度有限:即使拆成 Fiber 单元,某些更新仍然较重。
  2. 协调过程仍然昂贵:深层组件频繁更新仍可能导致重建成本高。
  3. 过多优先级切换可能造成抖动

这些问题促使 React 继续演化出:

  • 🧭 Concurrent Rendering(并发渲染) :通过 Scheduler 更智能地调度任务;
  • ⚙️ Suspense / Transition APIs:控制更新优先级;
  • 🚀 React Compiler(未来) :提前编译 Fiber 调度结构,减少运行时负担。

七、总结:Fiber 的设计哲学

维度旧 React新 Fiber 架构
执行模式递归、同步循环、可中断
渲染阶段单阶段Render + Commit 两阶段
任务管理Scheduler 管理优先级
状态保存Fiber Node 链表
响应性能可能卡顿可让出主线程

🎯 一句话总结:

Fiber 是 React 从「函数式 UI」迈向「可调度、响应式 UI」的根本转折点。它不是为了更快地渲染,而是为了更聪明地渲染。


八、未来优化方向

  1. 减少无意义的 Fiber 构建 → 静态分析 + React Compiler。
  2. 提高 Scheduler 智能化程度 → 引入多队列调度。
  3. 支持 Web Worker 渲染 → 让 Fiber 工作线程脱离主线程。
  4. Server Components → 将部分渲染前移到服务端,减少前端 Fiber 压力。

🧭 牢记

  • 理解 Fiber 的关键不是记代码,而是理解:

    • 为什么要“可中断”?
    • 为什么要“优先级”?
    • 为什么要“双缓存”?
  • 多画图、多比喻,体会 React 在“人机交互性能”层面的设计哲学。

Fiber 是 React 从「虚拟DOM」到「调度系统」的里程碑。它的核心不是 Diff,而是时间。