banner
HJ

HJ

github

Fiber 架构

在最新的 React.js 18 中, React 添加了期待已久的并发渲染器,并且支持开启并发更新功能(不会有并发更新模式),并发更新的体系结构如下图所示。本文将会从 Fiber 架构出发,一步步深挖 React 并发原理。

卡颂 — 《React 设计原理》

Fiber === React DOM#

Fiber 架构其实是 React 中 VDOM 的实现,它是 16 版本后 React 对核心算法的一次重新实现。

它的主要目标是提高动画、布局、手势等操作的响应速度。 Fiber 有能力将渲染工作分割成多块,并将它们分散到多个帧中去渲染。其他关键功能包括有能力暂停、渲染,有新的更新时可以重复使用;有能力对不同的更新增加优先级;新的并发模式。

React 16 以前#

当调用 ReactDOM 的 render 方法或者触发更新( setState )时,都会触发 React 的两个阶段,分别是 reconciler 和 renderer ,中文的解释是协调器和渲染器。从功能的实现上看, 这两个阶段分别对应 Diff 和 渲染过程,如下图:

image

  • 协调阶段(Reconciler):官方解释。 React 会自顶向下通过递归,遍历新数据生成新的 Virtual DOM ,然后通过 Diff 算法,找到需要变更的元素 (Patch),放到更新队列里面去。
  • 渲染阶段(Renderer):遍历更新队列,通过调用宿主环境的 API,实际更新渲染对应元素。宿主环境,比如 DOM、 Native、 WebGL 等。

在协调阶段阶段,由于是采用的递归的遍历方式,这种也被成为 Stack Reconciler ,主要是为了区别 Fiber Reconciler 取的一个名字。这种方式有一个特点:一旦任务开始进行,就无法中断,那么 JavaScript 将一直占用主线程, 一直要等到整棵 Virtual DOM 树计算完成之后,才能把执行权交给渲染引擎,那么这就会导致一些用户交互、动画等任务无法立即得到处理,就会有卡顿,非常的影响用户体验。

image

想要解决这个问题, React 现在的做法是引入 并发功能,通过一套优先级算法实现任务中断 / 恢复。原有的 Stack Reconciler 架构无法做到任务中断 / 恢复,不支持异步更新,因此 16 版本进行了重构,引进了 Fiber 架构。

什么是 Fiber#

在上面的介绍中,我们已经确定 Fiber 的主要目标是让 React 能够使用并发调度。具体来说,需要实现以下目标:

  1. 任务中断与恢复
  2. 为不同类型的任务分配优先级

为了做到这一点,我们需要设计一种方法将这些 “任务(Task)” 分解为单元,用于保存当前的更新中的一些信息,同时还需要保存一些静态数据(如当前 Task 对应的 节点信息),这就是一个 Fiber 节点(FiberNode), Fiber 架构就是由多个 FiberNode 组成的树状结构。不同 FiberNode 间由 child、return、sibling 等属性连接。

image

总的来说, Fiber 包含三层含义:

  1. 作为架构,Fiber 是由 FiberNode 组成的树状结构,区别于 16 版本前的 Stack Reconciler,16 版本的 Reconciler 基于 Fiber 实现。
  2. 作为数据结构,每一个 FiberNode 对应一个 ReactElement,保存了该组件的类型、DOM 结构等信息。
  3. 作为工作单元,每一个 FiberNode 保存了本次更新中该组件需要改变的状态,需要执行的工作。

Fiber 架构的组成#

总的来说,Fiber 架构由三部分组成:

  • FiberRootNode:保存挂载的根节点等信息,也是执行更新开始的节点。
    • 负责 Current Fiber Tree 与 Wip Fiber Tree 的转换
    • 保存任务的调度信息
  • HostRoot:应用在宿主环境上挂载的根节点,连接整颗 Fiber Tree

image

Fiber 工作原理#

Fiber 架构中会存在两条 Fiber Tree,一颗是真实 UI 对应的 Fiber Tree,另外一颗是正在内存中构建的 Fiber Tree,分别被称为 “current” 和 “workInProgress”, 这两颗 Fiber Tree 通过 alternate 属性相互连接。

这是一种被称为 Multiple buffering - Wikipedia --- 多重缓冲 - 维基百科 (双缓存)的工作机制。试想一下,在 Fiber 需要更新时,我们不需要直接使用 current Fiber Tree 进行更新,而是基于 current Fiber Tree 复制一份 workInProgress Fiber Tree 进行更新。在更新完成后,只需要将两颗 Fiber Tree 互换就完成了 Fiber Tree 的更新。

image

总结#

本文简单介绍了 React 16 及以后版本引入的并发模型,介绍 Fiber 结构的组成及其工作原理。在接下来的章节中,将会介绍 React 中的三大核心流程及其交互,进一步分析 React 并发原理。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。