React Stack 架构
解释 React 16 之前的 Stack Reconciler 架构及其局限性。
#tech / dev / frontend
#type / concept
#status / growing
#resource / javascript
#package / react
[!info] related notes
- 所属 MOC: React MOC, Fiber MOC
- 并列概念: Fiber 架构
- 关系笔记: Stack vs Fiber
React Stack 架构
这篇笔记回答一个问题:React 16 之前的 Stack Reconciler 是怎么工作的,以及为什么需要被 Fiber 替代。
一句话定义
Stack Reconciler 是 React 16 之前的协调器实现,采用递归方式一次性完成整棵组件树的 diff 和更新,过程不可中断。
核心机制
递归 diff
Stack 架构用递归遍历组件树,对比新旧 Virtual DOM 生成更新。
render()
-> Child1.render()
-> GrandChild.render()
-> Child2.render()
一旦开始,就会一直递归到底,直到整棵树处理完才释放主线程。
调用栈驱动
更新过程依赖 JavaScript 调用栈。组件树的层级直接映射为调用栈的深度。
局限性
1. 不可中断
递归一旦开始就无法暂停。如果组件树很大,会长时间占用主线程,导致页面卡顿、掉帧。
2. 无法按优先级调度
所有更新同等对待,无法区分”用户输入”和”后台数据加载”的优先级差异。
3. 长任务阻塞
16ms 内浏览器需要完成一帧渲染。Stack 架构下如果 diff 耗时超过 16ms,就会出现掉帧。
为什么需要 Fiber
Fiber 的核心改进是把递归改为循环,把一次性任务拆成可中断的工作单元(work unit),让 React 可以:
- 暂停更新,让出主线程处理用户输入
- 恢复之前未完成的工作
- 按优先级决定先处理哪些更新
- 复用已经计算过的结果
最小对比
| 维度 | Stack Reconciler | Fiber |
|---|---|---|
| 遍历方式 | 递归 | 循环 + 链表 |
| 可中断性 | 不可中断 | 可暂停、恢复 |
| 优先级 | 无 | 支持优先级调度 |
| 主线程占用 | 可能长时间阻塞 | 分片执行,让出主线程 |
常见误解
- “Stack 架构很慢” -> 不是慢,而是不可中断。小组件树完全没问题
- “Fiber 比 Stack 计算量更少” -> 不一定,Fiber 的关键是可调度,不是计算量
- “Stack 架构已经被完全移除” -> 理解其思想仍然有助于理解 Fiber 的改进动机