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