跳到主要内容

React Reconciler为何要采用Fiber架构

面试速答(30 秒版 TL;DR)

  • 先说结论:旧版 Reconciler 的主要问题不是“不会 diff”,而是“更新过程太同步、太一口气”
  • 在旧的 Stack Reconciler 里,组件树一旦开始递归更新,就很难中断,复杂页面容易把主线程占满。
  • Fiber 的价值在于把协调过程改造成 可拆分、可恢复、可按优先级调度 的工作流。
  • 所以 Reconciler 采用 Fiber,不只是为了比较新旧树,更是为了支持:
    • 时间切片
    • 更新优先级
    • 任务中断与重试
    • Suspense / Transition / 并发渲染
  • 一句话总结:React 需要的不只是“算差异”,还要“安排何时算、先算谁、算到一半能不能停”。

一、先分清:Reconciler 到底负责什么

React 内部常被粗分成两层:

  • Reconciler:负责协调更新,决定哪些节点复用、哪些节点删除、哪些节点需要副作用
  • Renderer:负责把结果提交到具体平台,比如 DOM、Native

所以 Reconciler 不是“只做 diff 的小模块”,它承担的是一整套更新协调职责:

  • 处理状态更新
  • 重新执行组件
  • 生成新子树
  • 复用旧节点
  • 收集副作用
  • 决定这次更新如何调度

当应用变大后,真正卡住 React 的,往往不是“能不能比较”,而是“这整个协调过程会不会霸占主线程太久”。

二、旧 Stack Reconciler 的核心问题

Fiber 之前,React 的更新模型更接近“函数调用栈递归”。

它的特点是:

  • 从根节点往下同步递归
  • 一旦开始,本次调用栈要尽量走完
  • 中途很难把部分工作保存下来,稍后继续

这在小应用里问题不大,但在大页面里会暴露明显短板。

1. 不可中断

如果一次更新涉及节点很多,React 会长时间占用主线程。

浏览器主线程被占住后,用户最直接的感受就是:

  • 输入延迟
  • 动画掉帧
  • 滚动不跟手

2. 没有细粒度优先级

旧模型很难优雅表达:

  • 文本输入要优先
  • 大列表重算可以稍后
  • 某些低优先级更新可以让路

这意味着所有更新更像“谁先来谁先整棵处理”,调度能力很弱。

3. 很难恢复部分完成的工作

假设整棵树算到一半,浏览器突然有更重要的事情要处理,旧模型没有足够好的“中间态保存”结构。

React 要么硬着头皮继续,要么下次几乎从头再来。

4. 不适合更高级的异步 UI 模型

后来的 React 想支持:

  • Transition
  • Suspense
  • 更细粒度的优先级
  • 可中断渲染

这些都要求 Reconciler 不只是“递归跑到底”,而要像调度器一样管理工作。

三、Fiber 为什么正好解决这些问题

Fiber 的核心思想是:

  • 把每个组件节点变成一个 Fiber
  • 把一次整树更新拆成很多小的工作单元
  • 每个工作单元都能被记录、暂停、恢复

这样 Reconciler 就从“递归算法”升级成“任务系统”。

1. Fiber 节点保存了足够多的中间状态

Fiber 节点上会保存:

  • 当前组件状态
  • 父子兄弟关系
  • 待处理更新
  • 副作用标记
  • 与旧树的 alternate 关系

这意味着 React 可以算到一半暂停,稍后从上次进度继续。

2. 工作单元可以被切片执行

只要每个 Fiber 节点都能作为一个独立工作单元,React 就能在合适时机:

  • 做一点
  • 暂停
  • 让浏览器先响应事件或绘制
  • 再继续做下一点

这就是“时间切片”背后的前提。

3. 优先级终于有了承载结构

Fiber 让 Reconciler 可以把“更新是什么”和“更新优先级是什么”一起管理。

于是就能实现:

  • 紧急更新先跑
  • 低优先级更新延后
  • 同优先级更新合并

4. 更适合失败、重试和回退

像 Suspense 这种能力,本质上就要求 React:

  • 某部分先挂起
  • 先显示 fallback
  • 数据好了再重试这部分树

没有 Fiber 这种可中断、可恢复的结构,Reconciler 很难优雅做到这一点。

四、为什么说“不是为了更快 diff,而是为了更强调度”

这是这题最关键的一句。

很多人一听 Fiber 就开始答:

  • diff 更快
  • 更新更快

这不准确。

更稳的表达应该是:

Fiber 的核心目标不是单纯减少比较次数,而是让 React 能把更新过程拆开管理,兼顾响应性和可扩展的并发能力。

也就是说,Fiber 带来的最大升级是:

  • 从“算不算得出来”
  • 升级到“能不能在用户交互下稳定、平滑、按优先级地算出来”

五、面试中怎么把“采用 Fiber”答完整

可以按这条链路回答:

  1. 旧 Reconciler 是同步递归,长任务会阻塞主线程。
  2. React 需要支持更复杂的交互优先级和可中断更新。
  3. Fiber 把节点变成工作单元,让协调过程能暂停、恢复、插队。
  4. 所以 Reconciler 采用 Fiber,本质是从“递归遍历器”升级成“可调度协调器”。

标准答法

React Reconciler 采用 Fiber 架构,核心原因不是旧版不会做 diff,而是旧版协调过程太同步,整棵树一旦开始递归更新就难以中断,复杂页面容易造成主线程长任务。Fiber 把每个组件节点抽象成可独立推进的工作单元,允许 React 在 render 阶段按优先级拆分、暂停、恢复和重试更新,从而支持时间切片、Transition、Suspense 这些能力。换句话说,Fiber 让 Reconciler 从“同步递归比较树”升级成了“可调度的更新系统”。

六、常见追问

1. Stack Reconciler 和 Fiber Reconciler 最大区别是什么?

前者更像同步递归调用栈,后者更像显式维护的工作链表/树结构,可以保存进度、恢复工作。

2. Fiber 之后 commit 还能中断吗?

不能。Fiber 主要让 render 阶段可中断,commit 仍然要一次完成。

3. Fiber 是不是等于 Concurrent Mode?

不是。Fiber 是底层架构,Concurrent Rendering 是建立在它之上的能力。

七、易错点 / 坑

  • 把“采用 Fiber”答成“因为 Fiber 的 diff 更快”。
  • 只讲 DOM 更新,不讲主线程调度问题。
  • 不区分 Reconciler 和 Renderer。
  • 把可中断渲染误解成 commit 也能做到半提交。

速记要点(可背诵)

  • 旧问题:同步递归、不可中断、优先级弱。
  • Fiber 方案:节点工作单元化、可暂停、可恢复、可插队。
  • 真正收益:不是只会 diff,而是会调度更新。