菜单

Fiber 架构

相关源文件

Fiber 是 React 的协调算法,在 React 16 中引入以取代之前的堆栈协调器。本文档解释了 Fiber 的架构、其内部工作原理以及它如何支持并发渲染和增量更新等特性。有关 Fiber 如何与特定渲染器交互的信息,请参阅 React DOM

什么是 Fiber?

Fiber 既是一种数据结构,也是一种架构,它允许 React 实现以下功能:

  1. 暂停、中止和恢复工作
  2. 为不同类型的更新分配优先级
  3. 复用之前已完成的工作
  4. 取消不再需要的工作

Fiber 的核心设计原则是使渲染可中断,从而使 React 能够并发处理多个任务,并提供更好的用户体验,尤其是在复杂应用中。

来源

Fiber 数据结构

从核心来看,Fiber 是一个 JavaScript 对象,代表一个组件、其输入和输出。它充当一个工作单元,并捕获组件的状态和 DOM。

Fiber 结构的关键点

  • Tag (标签): 标识 Fiber 的类型(例如,FunctionComponent (函数组件)、ClassComponent (类组件)、HostComponent (宿主组件))
  • Key (键): 用于协调以识别哪些子节点已更改
  • Type (类型): 与此 Fiber 关联的函数或类
  • StateNode (状态节点): 为此 Fiber 创建的实例(例如,DOM 节点、组件实例)
  • Child (子), Sibling (兄弟), Return (返回): 构成 Fiber 树结构
  • PendingProps/MemoizedProps (待处理属性/记忆化属性): 组件的输入/输出
  • UpdateQueue (更新队列): 状态更新、回调和 DOM 更新的队列
  • MemoizedState (记忆化状态): 用于创建输出的状态
  • Flags (标志): 用于标记需要完成的工作类型
  • Lanes (车道): 表示更新的优先级级别

来源

工作循环和执行上下文

React Fiber 引入了一个“工作循环”,用于控制 Fiber 树的遍历并执行工作。该循环可以被中断,从而允许浏览器处理高优先级事件。

此实现的核心部分在 ReactFiberWorkLoop.js 中,它定义了几个关键的执行上下文

在处理过程中,React 会跟踪当前执行上下文,以了解其所处的阶段,这对于在可中断渲染期间保持正确行为至关重要。

来源

使用 Current 和 Work-In-Progress 树进行双缓冲

Fiber 使用双缓冲技术来构建新的树(workInProgress),同时保持当前已渲染的树不变。这种方法允许 React 在不影响用户界面的情况下在后台准备新工作。

currentworkInProgress Fiber 通过 alternate 属性连接,形成对,从而促进了这种双缓冲方法

此方法在以下文件中实现:

来源

协调阶段

React 的 Fiber 架构将工作分为两个主要阶段:

1. 渲染/协调阶段

在此阶段,React 会进行以下操作:

  • 遍历 Fiber 树
  • 调用组件函数和类渲染方法
  • 计算变更
  • 此阶段可中断、暂停和恢复

重要提示:此阶段不产生任何可见更改——它仅构建“进行中”的树并计算需要更改的内容。

2. 提交阶段

提交阶段具有以下特点:

  • 是同步且不可中断的
  • 将所有更改应用于 DOM
  • 运行生命周期方法和副作用

提交阶段进一步分为子阶段:

  • 变动前阶段
  • 变动阶段
  • 布局阶段

来源

工作处理

在构建或更新 Fiber 树时,React 遵循两阶段过程:

  1. 开始阶段(自上而下):

    • 从根节点开始向下工作
    • 对于每个 Fiber,调用 beginWork,它返回下一个要处理的子节点
    • 按需创建新的 Fiber
  2. 完成阶段(自下而上):

    • 当一个 Fiber 没有子节点(或子节点已处理)时,完成该 Fiber 的处理
    • 调用 completeWork 以完成 Fiber 的最终化
    • 然后处理兄弟节点,再回到父节点

在处理 Fiber 时,React 可能会发现:

  • 它需要更新(props 已更改)
  • 它需要重新创建(类型已更改)
  • 它需要被删除
  • 子节点需要协调

每种情况都以不同方式处理,并在 Fiber 上设置相应的标志。

来源

优先级和调度

Fiber 引入了一种复杂的更新优先级系统,使用“车道”(lanes)(它取代了早期的“过期时间”模型)。车道在一个位字段中表示优先级和批处理。

更新会安排在特定的车道中,React 按照优先级顺序处理它们。多个更新可以在同一个车道中进行批处理。

调度系统支持以下功能:

  • 优先处理高优先级更新(例如,用户交互)
  • 批处理低优先级更新(例如,数据获取)
  • 时间切片工作以保持 UI 响应性
  • 在必要时暂停工作

来源

副作用管理

Fiber 使用标志和列表的组合来跟踪副作用(例如,DOM 更新、生命周期方法、ref)。副作用在渲染阶段收集,并在提交阶段执行。

在提交阶段,副作用以特定顺序应用,以确保正确行为:

  1. DOM 变动(放置、更新、删除)
  2. Ref 更新
  3. 布局副作用(componentDidMount/Update, useLayoutEffect)
  4. 被动副作用(useEffect)——异步运行

来源

Hooks 实现

React Hooks 是在 Fiber 架构之上实现的。每个 Fiber 都有一个 memoizedState 字段,对于函数组件而言,它存储了一个 Hook 的链表。

每个 Hook 使用此链表结构在渲染之间维护其状态。当函数组件渲染时:

  1. 当前 Hook 指针被重置
  2. 当组件体中调用每个 Hook 时:
    • 首次渲染:创建并初始化 Hook
    • 更新时:从列表中获取现有 Hook
  3. Hook 返回当前值和更新函数

Hook 调用在渲染之间严格顺序的强制执行依赖于此链表结构。

来源

暂停和恢复能力

Fiber 的强大功能之一是能够暂停渲染,并在之后从中断处恢复。这支持了以下特性,例如:

  • React Suspense 用于数据获取和代码分割
  • 并发模式渲染
  • 时间切片以提高响应性

当一个组件暂停(抛出一个 Promise)时:

  1. React 捕获该 Promise
  2. 回溯当前进行中的工作
  3. 显示一个回退 UI
  4. 当 Promise 解决时,React 重试渲染

来源

错误处理

Fiber 包含强大的错误处理机制,用于捕获和通过组件树传播错误

  1. 当渲染过程中发生错误时,React 会进行以下操作:

    • 回溯堆栈
    • 查找最近的错误边界
    • 在边界上创建错误更新
  2. 在提交阶段:

    • 错误边界的状态被更新
    • 显示回退 UI

此机制确保应用程序某一部分的错误不会破坏整个 UI。

来源

Fiber 协调算法

核心协调算法决定了哪些内容已更改并需要更新

对于子节点协调,React 使用键匹配和启发式算法来确定哪些元素与前一次渲染中的哪些 Fiber 对应。

来源

性能追踪

Fiber 内置了用于性能分析和调试的性能追踪功能

  1. Profiler 组件: 测量树中特定部分的渲染时间
  2. DevTools 集成: 为 React DevTools 提供详细的时间信息
  3. 追踪标记: 追踪特定操作和转换

该架构在协调和渲染的各个阶段提供了 Hook,用于收集性能数据,使 React DevTools 等工具能够提供详细的可视化。

来源

总结

Fiber 架构代表了 React 内部算法的彻底重构,旨在实现并发、增量更新和优先级管理。它建立在以下核心原则之上:

  1. 增量渲染: 工作可以被分割成块,并分布到多个帧上
  2. 优先级管理: 可以根据来源和上下文对不同的更新进行优先级排序
  3. 暂停和恢复: 工作可以被暂停、放弃,并在之后恢复
  4. 工作复用: 在某些情况下,之前完成的工作可以被复用

这种架构为 React 的许多高级特性提供了动力,包括并发模式、Suspense 和 Hooks API。它使 React 即使对于频繁更新的复杂应用程序也能提供响应式的用户体验。