React 16采用新的Fiber架构对React进行彻底重写,同时保持向后兼容。react
concurrent rendering 又叫 async rendering,主要包含2个特性:git
time slicing(分片)github
suspensesegmentfault
这两个特性的关键前提是:React的渲染可以被停止(interrupt)、恢复。
这就是为何咱们须要fiber架构了。promise
首先,咱们先解释,为何过去的架构没法支持渲染停止。浏览器
JavaScript原生的执行模型:经过调用栈来管理函数执行状态。网络
其中每一个栈帧表示一个工做单元(a unit of work),存储了函数调用的返回指针、当前函数、调用参数、局部变量等信息。
由于JavaScript的执行栈是由引擎管理的,执行栈一旦开始,就会一直执行,直到执行栈清空。没法按需停止。架构
这与React有什么关系呢?React将视图看作函数调用的结果:dom
View = Component(Data)
Component会递归调用其余的Component。页面复杂的话,这个调用栈会很深,致使UI变卡。
在React Fiber以前,React的渲染就是使用原生执行栈来管理组件树的递归渲染。这意味着,整颗组件树的渲染必须一次性完成,工做没法被分片。
所以,react须要另外一种可控的执行模型,让react来管理工做的调度。async
React Fiber架构就是用JavaScript来实现的执行模型。能够将它比做由react管理的“调用栈”,一个fiber与一个函数栈帧很是相似,它们都表示一个工做单元(a unit of work)。一个组件实例对应一个Fiber。
函数栈帧 | fiber |
---|---|
返回指针 | 父组件 |
当前函数 | 当前组件 |
调用参数 | props |
局部变量 | state |
React Fiber与调用栈的区别:
React Fiber是使用JavaScript实现的,这意味着它的底层依然是JavaScript调用栈。
Fiber实际上是计算机科学中早已存在的概念。Fiber的英文含义就是“纤维”,意指比Thread更细的线,寓意它是比线程(Thread)控制得更精密的执行模型。fiber是协做的(cooperatively)、可控的。一个fiber执行完本身的工做之后,会主动让出控制权,不会主宰(dominate)整个程序的执行。
协程(Coroutines)基本是相同的概念,它们的区别微乎其微。说白了,React Fiber就是用JavaScript从新实现了一个协程模型。
话说回来,generator函数也可以主动让出程序控制权(generator函数本质就是协程),用它也可以作到concurrent rendering。为何react不使用generator函数而是从新实现协程,应该是由于后者可以更加灵活吧,好比generator函数不支持回到以前的yield状态,而fiber支持从任意一个fiber节点从新开始渲染。
与Fiber相反,调用栈模型则不可控、不协做(non-cooperatively)。若是函数不断地递归调用,那么会彻底主宰整个程序,后续的工做(好比浏览器paint)必须等待它执行完成。
在React Fiber中,一次更新过程会分红多个分片完成,因此彻底有可能一个更新任务尚未完成,就被另外一个更高优先级的更新过程打断,这时候,优先级高的更新任务会优先处理完,而低优先级更新任务所作的工做则会 彻底做废,而后等待机会重头再来。
由于一个更新过程可能被打断,因此React Fiber一个更新过程被分为两个阶段(Phase):第一个阶段Reconciliation Phase和第二阶段Commit Phase。
在第一阶段Reconciliation Phase,React Fiber会找出须要更新哪些DOM,这个阶段是能够被打断的;可是到了第二阶段Commit Phase,那就一气呵成把DOM更新完,毫不会被打断。
当一个Fiber的工做执行完,控制权会交还给React Scheduler,后者会检查【渲染一帧的可用时间】是否已经用完:
若是渲染到某个组件时,发现渲染须要暂停(好比须要等待React.lazy
组件的加载,咱们假设组件层级为<App> -> <User> -> <LazyComponent>
),那么在User组件的渲染函数中,会抛出一个Promise。得益于React Fiber架构,调用栈并非React scheduler -> App -> User
,而是:先React scheduler -> App
而后React scheduler -> User
。所以User组件抛出的错误会被React scheduler接住,React scheduler会将渲染“暂停”在User组件。这意味着,App组件的工做不会丢失。等到promise解析到数据之后,从User fiber开始从新渲染就行了(至关于控制权直接交还给User)。
Algebraic Effects,以及它在React中的应用讨论了它背后的理论概念。
Algebraic effects, Fibers, Coroutines...
React Fiber Architecture
Inside Fiber: in-depth overview of the new reconciliation algorithm in React