浅入 React Fiber 及相关资料整理

发布于 2022-10-17 12:55:11 字数 4326 浏览 115 评论 0

fiber 作为一种数据结构,用于代表某些 worker,换句话说,就是一个 work 单元,通过 Fiber 的架构,提供了一种跟踪,调度,暂停和中止工作的便捷方式。

react fiber 及未来

异步渲染 Dan 提出的异步渲染的概念,异步渲染即在以异步的方式加载的同时给人以同步流程的体验,在老设备上,通过牺牲一些加载时间来获得一种流畅的体验。其实在 React@16 版本中,异步渲染默认是关闭的。

生命周期变更 在 react@16 版本中,虽然依旧支持之前的生命周期函数,但是官方已经说明在下个版本中会将废弃其中的部分,这么做的原因,主要是 reconciliation 的重写导致。在 render/reconciliation 的过程中,因为存在优先级和时间片的概念,一个任务很可能执行到一半就被其他优先级更高的任务所替代,或者因为时间原因而被终止。当再次执行这个任务时,是从头开始执行一遍,就会导致组件的某些 xxxwill 生命周期可能被多次调用而影响性能。

react@16 与其说是一个分水岭,不如说是一个过渡,react@17 才会是掀起风浪的那一个。


Stack reconciler 自顶向下的递归 diff,这个过程无法中断(持续占用主线程),那么主线程上的 layout、动画等周期性任务以及交互响应就无法立即得到处理。

Fiber reconciler 的思路是把渲染/更新过程(递归diff)按照时间分片拆分成一系列小任务,通过任务调度每次检查 fiber tree 上的一小部分,如有空闲时间则继续下一个任务,否则将暂停或终止执行任务,待主线程完成更高优先级任务后再继续。

fiber tree 即 Fiber 上下文的 vDOM tree,更新过程就是根据输入数据以及现有的 fiber tree 构造出新的fiber tree(workInProgress tree)。一些细致一点的概念如下:

DOM
    真实DOM节点
-------
effect
    每个workInProgress tree节点上都有一个effect list
    用来存放diff结果
    当前节点更新完毕会向上merge effect list(queue收集diff结果)
- - - -
workInProgress
    workInProgress tree是reconcile过程中从fiber tree建立的当前进度快照,用于断点恢复
- - - -
fiber
    fiber tree与vDOM tree类似,用来描述增量更新所需的上下文信息
-------
Elements
    描述UI长什么样子(type, props)

Fiber reconciler

1. render/reconciliation

初次渲染的时候构建 fiber tree,后续state或props有变更,则以此为蓝本,以 fiber node 为工作单元,自顶向下逐节点构造 workInProgress tree(构建中的新fiber tree)

具体过程如下:

  • 如果当前节点不需要更新,直接把子节点 clone 过来,跳到5,要更新的话打个 tag
  • 更新当前节点状态(props, state, context等)
  • 调用 shouldComponentUpdate,如若返回 false 则跳到5
  • 调用 render() 获得新的子节点,并为子节点创建 fiber(创建过程会尽量复用现有 fiber,子节点增删也发生在这里)
  • [标识位5] 如果没有 child fiber,该工作单元结束,把 effect list 归并 return,并把当前节点的 sibling 作为下一个工作单元,否则把 child 作为下一个工作单元
  • 在工作单元工作结束,则看看任务调度有无更高优先级任务,否则继续
  • 如果没有下一个工作单元了,则回到了 workInProgress tree 的根节点,第1阶段结束,进入pendingCommit状态

workloop 结束时,workInProgress tree 的根节点身上的 effect list 就是收集到的所有 side effect(因为每做完一个都向上归并),所以,构建 workInProgress tree 的过程就是 diff 的过程。

workInProgress tree 构造完毕,得到的就是新的 fiber tree,然后把 current 指针指向 workInProgress tree,丢掉旧的 fiber tree。这样做的好处:能够复用内部对象(fiber),节省内存分配、GC 的时间开销。

2. commit(该阶段不能打断)

  • 处理 effect list,包括 3 种处理:更新DOM树、调用组件生命周期函数以及更新ref等内部状态
  • 把所有的 DOM changes 的 patches 都 commit 到 DOM 树上

任务调度

diff 的粒度控制为一个fiber node,实际上就是按虚拟 DOM 节点拆,因为 fiber tree 是根据 v-DOM tree 构造出来的,树结构一模一样,只是节点数据信息有差异。

任务调度分两部分:工作循环 & 优先级机制。

工作循环是基本的任务调度机制,工作循环中每次处理一个任务(工作单元),处理完毕有一次喘息的机会,基本规则是:每个工作单元结束检查是否还有时间做下一个,没时间了就先“挂起”

优先级机制用来处理突发事件与优化次序。

中断/断点恢复

  • 中断:检查当前正在处理的工作单元,保存当前成果(firstEffect, lastEffect),修改 tag 标记一下,迅速收尾并再开一个requestIdleCallback,下次有机会再做
  • 断点恢复:下次再处理到该工作单元时,看tag是被打断的任务,接着做未完成的部分或者重做

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

滿滿的愛

暂无简介

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文