到底React Fiber架构是个什么

diff 算法缺陷

diff 算法问题出现在,React 的调度策略 -- Stack Reconfile。这个策略像函数调用栈一样,会深度优先遍历所有的 Virtual DOM 节点,进行Diff。它一定要等整棵 Virtual DOM 计算完成之后,才将任务出栈释放主线程。重点在于,Stack Reconfile始终会一次性地同步处理整个组件树。Stack Reconciler无法暂停,因此如果更新较为深入并且可用CPU时间有限,这种做法并非最优化的。所以,在浏览器主线程被 React更新状态任务占据的时候,用户与浏览器进行任何的交互都不能得到反馈,只有等到任务结束,才能突然得到浏览器的响应。

React Fiber 简介

使用协作式多任务处理任务。将原来的整个 Virtual DOM 的更新任务拆分成一个个小的任务。每次做完一个小任务之后,放弃一下自己的执行(可以暂停),将主线程空闲出来,看看有没有其他的任务。如果有的话,就暂停本次任务,执行其他的任务,如果没有的话,就继续下一个任务。

为什么React 需要 Fiber

这里特指Javascript 引擎是单线程运行的。严格来说,页面绘制由单独的GUI渲染进程负责,只不过GUI渲染线程和Javascript线程是互斥的. 另外底层的异步操作实际上也是多线程的。

  • JavaScript单线程。要是有一个任务长期霸占CPU,浏览器会呈现卡死的状

  • 因为不是所有的state更新都需要立即显示出来,比如屏幕之外的用户看不见的部分的更新

  • react 为了解决这个问题,提出了 Fiber reconciliation 的方案来代替之前的 Stack reconciliation。Fiber 相较于 Stack,采用了异步的方式将之前同步执行的计算过程拆分,这样主线程不会一直处于被占用的状态,可以有时间去处理其他任务,比如 I/O 操作,交互反馈等。

  • diff 算法满足不了暂停任务, React 通过Fiber 架构,让自己的 reconcilation 过程变成可被中断 适当让出CPU执行权

React Fiber思想

Fiber是堆栈的重新实现,专门用于React组件。你可以将单个Fiber视为一个虚拟堆栈帧。

时间切片:

  • 虚拟DOM,是可以进行分片进行

  • react 新API:unstable_deferredUpdates

  • Chorme 新API:requestIdleCallback

  • 时间切片让React 渲染的过程可以被中断。当遇到浏览器行为的时候,可以将控制权交回浏览器,让位给高优先级的任务(键盘鼠标输入行为),浏览器空闲后再介入进行渲染,适当让出CPU执行权还给浏览器

  • 当一个节点处理完成,react仍然会检查当前时间片是否够用。如果够用则处理下一个

  • fiber reconciler优先级策略:通过将reconciliation过程,分解成小的工作单元的方式,可以让页面对于浏览器事件的响应更加及时。但是另外一个问题还是没有解决,就是如果当前在处理的react渲染耗时较长,仍然会阻塞后面的react渲染。

  • Fiber 依次通过 return、child 及 sibling 的顺序对 ReactElement 做处理,将之前简单的树结构,变成了基于单链表的树结构,维护了更多的节点关系。

React Fiber主要阶段

  • render / reconciliation (interruptible) 协调/渲染 协调阶段通常被称为“渲染阶段”
    Reconcile 阶段。此阶段中,依序遍历组件,通过diff 算法,判断组件是否需要更新,给需要更新的组件加上tag。遍历完之后,将所有带有tag的组件加到一个数组中。这个阶段的任务可以被打断。

  • commit (not interruptible) 提交
    根据在 Reconcile 阶段生成的数组,遍历更新DOM,这个阶段需要一次性执行完。如果是在其他的渲染环境 -- Native,硬件,就会更新对应的元素。

requestIdleCallback API

window.requestIdleCallback()方法将在浏览器的空闲时段内调用的函数排队。这使开发人员能够在主事件循环上执行后台和低优先级工作,而不会影响延迟关键事件,如动画和输入响应。函数一般会按先进先调用的顺序执行,然而,如果回调函数指定了执行超时时间timeout,则有可能为了在超时前执行函数而打乱执行顺序。

兼容性:

react 使用 这个api ,根据当前主线程的使用情况去处理这次update,requestIdleCallback可以在这个空闲期(Idle Period)调用空闲期回调(Idle Callback),执行一些任务
目前 requestIdleCallback 目前只有Chrome, Opera支持。所以目前 React 自己实现了一个

页面流畅与 FPS:

  • 页面是一帧一帧绘制出来的,当每秒绘制的帧数(FPS)达到 60 时,页面是流畅的,小于这个值时,用户会感觉到卡顿。

  • 1s 60帧,所以每一帧分到的时间是 1000/60 ≈ 16 ms。所以我们书写代码时力求不让一帧的工作量超过 16ms。

一帧内需要完成如下六个步骤的任务:

  • 处理用户的交互
  • JS 解析执行
  • 帧开始。窗口尺寸变更,页面滚去等的处理
  • requestAnimationFrame(rAF)
  • 布局
  • 绘制

上面六个步骤完成后没超过 16 ms,说明时间有富余,此时就会执行 requestIdleCallback 里注册的任务。

  • 客户端线程执行任务时会以帧的形式划分,大部分设备控制在30-60帧是不会影响用户体验;在两个执行帧之间,主线程通常会有一小段空闲时间,requestIdleCallback可以在这个空闲期(Idle Period)调用空闲期回调(Idle Callback),执行一些任务 。对于不支持这个API的浏览器,react会加上pollyfill。
  • 低优先级任务由requestIdleCallback处理;
  • requestIdleCallback可以在多个空闲期调用空闲期回调,执行任务;
  • requestIdleCallback方法提供deadline,即任务执行限制时间,以切分任务,避免长时间执行,阻塞UI渲染而导致掉帧;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容