资讯专栏INFORMATION COLUMN

React 重要的一次重构:认识异步渲染架构 Fiber

cppowboy / 3483人阅读

摘要:在之前的叫,是新的,这次更新到架构是一次重量级的核心架构的替换,为了完成这次替换已经准备了两三年的时间了。因此团队引入了异步渲染这个概念,而采用架构可以实现这种异步渲染的方式。官方目前已经把和标记为,并使用新的生命周期函数和进行替换。

Diff 算法

熟悉 react 的朋友都知道,在 react 中有个核心的算法,叫 diff 算法。web 界面由 dom 树组成,不同的 dom 树会渲染出不同的界面。react 使用 virtual dom 来表示 dom 树,而 diff 算法就是用于比较 virtual dom 树的区别,并更新界面需要更新的部分。diff 算法和 virtual dom 的完美结合的过程被称为 reconciler,这可是 react 攻城拔寨的绝对利器。有了 reconciler,开发者可以脱身操作真实的 dom 树,只需要向 react 描述界面的状态,而 react 会帮助你高效的完成真正 dom 操作。

在 react16 之前的 reconciler 叫 stack reconciler,fiber 是 react 新的 reconciler,这次更新到 fiber 架构是一次重量级的核心架构的替换,react 为了完成这次替换已经准备了两三年的时间了。

那么 fiber 究竟有什么好的呢?

Fiber 为何出现

不知道大家有没有遇到过这样的情况,点击一个页面的按钮时感觉到页面没有任何的反应,让你怀疑电脑是不是死机了,然后你快速切出浏览器,发现电脑并没有死机,于是再切回浏览器,这时候才发现页面终于更新了。为什么会出现这种情况?在多数情况下,可能是因为浏览器忙着执行相关的 js 代码,导致浏览器主线程没有及时响应用户的操作或者没有及时更新界面。下面这张图就表示了这种现象,你的公司只有一个程序员 (main thread),当这个程序员在执行你的任务 (your code) 时,处于沉浸式编程的状态,无法响应外部的其他事件,什么下班吃饭,都是不存在的。这就像浏览器忙着执行 js 代码的时候,不会去执行页面更新等操作。

本着顾客是上帝的原则,作为一名优秀的开发者,怎么能够允许出现这种情况降低用户的体验呢。因此 react 团队引入了异步渲染这个概念,而采用 fiber 架构可以实现这种异步渲染的方式。

原先的 stack reconciler 像是一个递归执行的函数,从父组件调用子组件的 reconciler 过程就是一个递归执行的过程,这也是为什么被称为 stack reconciler 的原因。当我们调用 setState 的时候,react 从根节点开始遍历,找出所有的不同,而对于特别庞大的 dom 树来说,这个递归遍历的过程会消耗特别长的时间。在这个期间,任何交互和渲染都会被阻塞,这样就给用户一种“死机”的感觉。

fiber 的出现解决了这个问题,它把 reconciler 的过程拆分成了一个个的小任务,并在完成了小任务之后暂停执行 js 代码,然后检查是否有需要更新的内容和需要响应的事件,做出相应的处理后再继续执行 js 代码。这样就给了用户一种应用一直在运行的感觉,提高了用户的体验。

Fiber 如何做到异步渲染

在做显示方面的工作时,经常会听到一个目标叫 60 帧,这表示的是画面的更新频率,也就是画面每秒钟更新 60 次。这是因为在 60 帧的更新频率下,页面在人眼中显得流畅,无明显卡顿。每秒钟更新 60 次也就是每 16ms 需要更新一次页面,如果更新页面消耗的时间不到 16ms,那么在下一次更新时机来到之前会剩下一点时间执行其他的任务,只要保证及时在 16ms 的间隔下更新界面就完全不会影响到页面的流畅程度。fiber 的核心正是利用了 60 帧原则,实现了一个基于优先级和 requestIdleCallback 的循环任务调度算法。

requestIdleCallback 是浏览器提供的一个 api,可以让浏览器在空闲的时候执行回调,在回调参数中可以获取到当前帧剩余的时间,fiber 利用了这个参数,判断当前剩下的时间是否足够继续执行任务,如果足够则继续执行,否则暂停任务,并调用 requestIdleCallback 通知浏览器空闲的时候继续执行当前的任务。

function fiber(剩余时间) {
 if (剩余时间 > 任务所需时间) {
 做任务;
 } else {
 requestIdleCallback(fiber);
 }
}

fiber 还会为不同的任务设置不同的优先级,高优先级任务是需要马上展示到页面上的,比如你正在输入框中输入文字,你肯定希望你的手指在键盘上敲下每一个按键时,输入框能立马做出反馈,这样你才能知道你的输入是否正确,是否有效。低优先级的任务则是像从服务器传来了一些数据,这个时候需要更新页面,比如这篇文章喜欢的人数+1 或是评论+1,这并不是那么紧急的更新,延迟 100-200ms 并不会有多大差别,完全可以在后面进行处理。fiber 会根据任务优先级来动态调整任务调度,优先完成高优先级的任务。

{ 
 Synchronous: 1, // 同步任务,优先级最高
 Task: 2, // 当前调度正执行的任务
 Animation 3, // 动画
 High: 4, // 高优先级
 Low: 5, // 低优先级
 Offscreen: 6, // 当前屏幕外的更新,优先级最低
}

在 fiber 架构中,有一种数据结构,它的名字就叫做 fiber,这也是为什么新的 reconciler 叫做 fiber 的原因。fiber 其实就是一个 js 对象,这个对象的属性中比较重要的有 stateNodetagreturnchildsiblingalternate

Fiber = {
 tag // 标记任务的进度
 return // 父节点
 child // 子节点
 sibling // 兄弟节点
 alternate // 变化记录
 .....
};

我们可以看出 fiber 基于链表结构,拥有一个个指针,指向它的父节点子节点和兄弟节点,在 diff 的过程中,依照节点连接的关系进行遍历。

fiber 可能存在的问题

在 fiber 中,更新是分阶段的,具体分为两个阶段,首先是 reconciliation 的阶段,这个阶段在计算前后 dom 树的差异,然后是 commit 的阶段,这个阶段将把更新渲染到页面上。第一个阶段是可以打断的,因为这个阶段耗时可能会很长,因此需要暂停下来去执行其他更高优先级的任务,第二个阶段则不会被打断,会一口气把更新渲染到页面上。

由于 reconciliation 的阶段会被打断,可能会导致 commit 前的这些生命周期函数多次执行。react 官方目前已经把 componentWillMountcomponentWillReceivePropscomponetWillUpdate 标记为 unsafe,并使用新的生命周期函数 getDerivedStateFromPropsgetSnapshotBeforeUpdate 进行替换。

还有一个问题是饥饿问题,意思是如果高优先级的任务一直插入,导致低优先级的任务无法得到机会执行,这被称为饥饿问题。对于这个问题官方提出的解决方案是尽量复用已经完成的操作来缓解。相信官方也正在努力提出更好的方法去解决这个问题。

文 / Xss

编 / 荧声

本文已由作者授权发布,版权属于创宇前端。欢迎注明出处转载本文。本文链接:https://knownsec-fed.com/2018...

想要订阅更多来自知道创宇开发一线的分享,请搜索关注我们的微信公众号:创宇前端(KnownsecFED)。欢迎留言讨论,我们会尽可能回复。

感谢您的阅读。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108585.html

相关文章

  • 浅谈React Fiber

    摘要:因为版本将真正废弃这三生命周期到目前为止,的渲染机制遵循同步渲染首次渲染,更新时更新时卸载时期间每个周期函数各司其职,输入输出都是可预测,一路下来很顺畅。通过进一步观察可以发现,预废弃的三个生命周期函数都发生在虚拟的构建期间,也就是之前。 showImg(https://segmentfault.com/img/bVbweoj?w=559&h=300); 背景 前段时间准备前端招聘事项...

    izhuhaodev 评论0 收藏0
  • React 16」为 Luy 实现 React Fiber 架构

    摘要:开始写代码构造函数讲了那么多的理论,大家一定是晕了,但是没办法,架构已经比之前的简单要复杂太多了,因此不可能指望一次性把的内容全部理解,需要反复多看。 前言 Facebook 的研发能力真是惊人, Fiber 架构给 React 带来了新视野的同时,将调度一词介绍给了前端,然而这个架构实在不好懂,比起以前的 Vdom 树,新的 Fiber 树就麻烦太多。 可以说,React 16 和 ...

    DevWiki 评论0 收藏0
  • React Fiber 架构理解

    摘要:架构理解引用原文是核心算法正在进行的重新实现。构建的过程就是的过程,通过来调度执行一组任务,每完成一个任务后回来看看有没有插队的更紧急的,把时间控制权交还给主线程,直到下一次回调再继续构建。 React Fiber 架构理解 引用原文:React Fiber ArchitectureReact Fiber is an ongoing reimplementation of Reacts...

    Berwin 评论0 收藏0
  • Deep In React之浅谈 React Fiber 架构(一)

    摘要:在上面我们已经知道浏览器是一帧一帧执行的,在两个执行帧之间,主线程通常会有一小段空闲时间,可以在这个空闲期调用空闲期回调,执行一些任务。另外由于这些堆栈是可以自己控制的,所以可以加入并发或者错误边界等功能。 文章首发于个人博客 前言 2016 年都已经透露出来的概念,这都 9102 年了,我才开始写 Fiber 的文章,表示惭愧呀。不过现在好的是关于 Fiber 的资料已经很丰富了,...

    Jiavan 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<