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”答完整
可以按这条链路回答:
- 旧 Reconciler 是同步递归,长任务会阻塞主线程。
- React 需要支持更复杂的交互优先级和可中断更新。
- Fiber 把节点变成工作单元,让协调过程能暂停、恢复、插队。
- 所以 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,而是会调度更新。