Fiber 架构详解
1. Fiber 是什么
Fiber 是 React 16 引入的新架构,是对 React 核心算法的重写。Fiber 既是一种数据结构,也是一种架构模式。
1.1 Fiber 作为数据结构
Fiber 是一个 JavaScript 对象,表示一个工作单元,包含组件的类型、状态、副作用等信息。
1.2 Fiber 作为架构
Fiber 架构使得 React 能够:
- 可中断渲染:将渲染工作分成多个小任务,可以暂停和恢复
- 优先级调度:根据优先级决定先执行哪些任务
- 增量更新:可以逐步更新 UI,而不是一次性完成
工作流程
1.调和阶段 1.1 React 会将整个渲染任务拆分成多个小的工作单元(Fiber 节点) 1.2 拆分成 beginWork 和 completeWork 1.2.1 beginwork:挂载更新 各个 hooks(hooks允许在不编写 class 的情况下使用 state 以及 React 的其他特性 包含 state、effect) ,存到memoizedState 1.3 构建新的 Fiber 树(workInProgress)
2. Fiber 树结构
Fiber 节点通过以下字段形成树结构:
Fiber
├── child → 第一个子节点
├── sibling → 下一个兄弟节点
└── return → 父节点遍历顺序(深度优先):
- 访问当前节点
- 访问子节点(child)
- 访问兄弟节点(sibling)
- 回到父节点(return)
3. 双缓冲机制
React 使用双缓冲技术来优化性能:
3.1 Current Tree 和 WorkInProgress Tree
- Current Tree:当前显示在屏幕上的 Fiber 树
- WorkInProgress Tree:正在构建的新 Fiber 树
3.2 alternate 字段
每个 Fiber 节点都有一个 alternate 字段,指向另一个树中对应的节点:
// current.alternate === workInProgress
// workInProgress.alternate === current3.3 工作原理
- 开始更新时,从 current 树克隆节点创建 workInProgress 树
- 在 workInProgress 树上进行更新
- 更新完成后,workInProgress 树成为新的 current 树
- 下次更新时,复用之前的节点,减少内存分配
4. 优先级系统(Lanes)
React 使用 Lanes(车道)系统管理优先级:
任务看成我一辆辆汽车,他们需要在不同的车道上行驶才不会相互影响,但是右边的车道可以向左边超车(优先级高)。这就是为什么我们称之为 车道模型。
4.1 优先级档位(5 档,从高到低)
Lane 在 ReactFiberLane.js 里用 31 位掩码表示;getHighestPriorityLane() 在待处理集合里取最靠右的 bit,对应最紧急的更新。日常所说的「优先级」通常指下面 5 个主档位(与 lanesToEventPriority → Scheduler 五档的映射一致,详见 05-Scheduler调度器):
- SyncLane — 离散交互、
flushSync等,需尽快同步完成 - InputContinuousLane — 连续输入(滚动、拖拽、
mousemove等),可分批处理但不能长期饿死 - DefaultLane — 未单独分级的普通更新(多数
setState、请求返回后的渲染) - TransitionLanes —
startTransition/useDeferredValue(占 14 个 bit,可并存多个 transition) - IdleLanes — 可无限推迟的后台工作
Hydration 还有与上表同档的 *HydrationLane 变体,专用于 SSR 注水。
不算在上述五档里的辅助车道(不要和「5 个优先级」混为一谈):
- RetryLanes(4 bit):Suspense 在 Promise 就绪后的重试
- OffscreenLane:离屏 / 预渲染内容
原先只列 Sync、Transition、Retry、Idle,漏了 InputContinuous 与 Default 两档,且把 Retry 当成了与 Transition 并列的主层级。
5. 副作用标记(Flags)
React 使用 Flags 标记副作用:
5.1 副作用类型
- Placement:需要插入 DOM
- Update:需要更新 DOM
- Deletion:需要删除 DOM
- Passive:useEffect 副作用
- Layout:useLayoutEffect 副作用
6. Fiber 架构的优势
6.1 可中断渲染
- 可以将渲染工作分成多个小任务
- 可以在任务之间让出控制权
- 可以暂停低优先级任务,优先处理高优先级任务
6.2 优先级调度
- Sync / InputContinuous:点击、键盘、滚动等用户感知路径优先
- Default / Transition:普通状态更新 vs 可打断的过渡更新
- Idle:后台任务最后执行
6.3 增量更新
- 可以逐步更新 UI
- 不会阻塞主线程
- 提供更好的用户体验
7. Fiber 架构的设计原则
根据 Fiber Principles:
- 在 beginWork 和 completeWork 中可以修改 Fiber
- 不能在这些阶段之外有全局副作用
- 使用固定的数据结构:Fiber 节点结构固定,不能动态添加字段
- 避免动态分发:减少函数调用开销