React Fiber

什么是 React Fiber

宏观

React Fiber是重构React V15之后的一个全新的架构

使用Fiber架构后可以支持许多新的功能

  • Concurrent Mode

狭义

Fiber 其实是一个拥有许多属性的 JavaScript 对象。

export type Fiber = {|
tag: WorkTag,
key: null | string,
elementType: any,
type: any,
stateNode: any,
return: Fiber | null,
child: Fiber | null,
sibling: Fiber | null,
index: number,
ref:
| null
| (((handle: mixed) => void) & { _stringRef: ?string, ... })
| RefObject,
pendingProps: any, // 从`ReactElement`对象传入的 props. 用于和`fiber.memoizedProps`比较可以得出属性是否变动
memoizedProps: any, // 上一次生成子节点时用到的属性, 生成子节点之后保持在内存中
updateQueue: mixed, // 存储state更新的队列, 当前节点的state改动之后, 都会创建一个update对象添加到这个队列中.
memoizedState: any, // 用于输出的state, 最终渲染所使用的state
dependencies: Dependencies | null, // 该fiber节点所依赖的(contexts, events)等
mode: TypeOfMode, // 二进制位Bitfield,继承至父节点,影响本fiber节点及其子树中所有节点. 与react应用的运行模式有关(有ConcurrentMode, BlockingMode, NoMode等选项).
// Effect 副作用相关
flags: Flags, // 标志位
subtreeFlags: Flags, //替代16.x版本中的 firstEffect, nextEffect. 当设置了 enableNewReconciler=true才会启用
deletions: Array<Fiber> | null, // 存储将要被删除的子节点. 当设置了 enableNewReconciler=true才会启用
nextEffect: Fiber | null, // 单向链表, 指向下一个有副作用的fiber节点
firstEffect: Fiber | null, // 指向副作用链表中的第一个fiber节点
lastEffect: Fiber | null, // 指向副作用链表中的最后一个fiber节点
// 优先级相关
lanes: Lanes, // 本fiber节点的优先级
childLanes: Lanes, // 子节点的优先级
alternate: Fiber | null, // 指向内存中的另一个fiber, 每个被更新过fiber节点在内存中都是成对出现(current和workInProgress)
// 性能统计相关(开启enableProfilerTimer后才会统计)
// react-dev-tool会根据这些时间统计来评估性能
actualDuration?: number, // 本次更新过程, 本节点以及子树所消耗的总时间
actualStartTime?: number, // 标记本fiber节点开始构建的时间
selfBaseDuration?: number, // 用于最近一次生成本fiber节点所消耗的时间
treeBaseDuration?: number, // 生成子树所消耗的时间的总和
|};

为什么要使用 React Fiber 架构

现代浏览器中最想避免的无非是两种糟糕的使用者体验

  • 页面卡顿
  • 没有内容的白屏渲染

React Fiber的出现就是为了解决这个问题,

Before Fiber

React就像一个快节奏的公司,但是不使用git。

想象一下这种场景,当我们在做一个大的功能的时候,老板过来说要做一个 Hotfix。但是你不能停止你现在的工作,因为所有的改动都是一个文件中,你必须先完成这项工作。

如果我们使用git,我们就可以将我们的工作提交到一个分支,并切换到一个新的分支来做 Hotfix.

使用 Fiber, React可以随意的暂停和恢复工作,以尽快开始重要的工作。

React源码中包的简介

  • react

    • react的基础包,只提供定义 react 组件(ReactElement)的必要函数。我们开发中大部分都是调用此包中的API
  • react-dom

    • react渲染器之一,是 react 与 web 平台连接的桥梁
    • reconciler 中运行结果输出到 web 界面上。
    • 在编写 react 应用时,大多数场景,就是用到此包的一个入口函数
      • React.render(<App>, container)
  • react-reconciler

    • react得以运行的核心包(综合协调 react-dom、react、scheduler各包之间的调用与配合)。管理 React 应用状态的输入和结果的输出。将输入信号最终转换成输出信号传递给渲染器。

  • scheduler

    • 调度机制的核心实现,控制由 react-reconciler 送入的回调函数的执行时机

    • concurrent模式下可以实现任务分片。

      • 核心任务就是执行回调(回调函数由 react-reconciler提供)
      • 通过控制回调函数的执行时机, 来达到任务分片的目的, 实现可中断渲染(concurrent模式下才有此特性)