banner
HJ

HJ

github

Fiber 架構

在最新的 React.js 18 中, React 添加了期待已久的並發渲染器,並且支持開啟並發更新功能(不會有並發更新模式),並發更新的體系結構如下圖所示。本文將會從 Fiber 架構出發,一步步深挖 React 並發原理。

卡頌 — 《React 設計原理》

Fiber === React DOM#

Fiber 架構其實是 React 中 VDOM 的實現,它是 16 版本後 React 對核心算法的一次重新實現。

它的主要目標是提高動畫、布局、手勢等操作的響應速度。 Fiber 有能力將渲染工作分割成多塊,並將它們分散到多個幀中去渲染。其他關鍵功能包括有能力暫停、渲染,有新的更新時可以重複使用;有能力對不同的更新增加優先級;新的並發模式。

React 16 以前#

當調用 ReactDOM 的 render 方法或者觸發更新( setState )時,都會觸發 React 的兩個階段,分別是 reconciler 和 renderer ,中文的解釋是協調器和渲染器。從功能的實現上看, 這兩個階段分別對應 Diff 和 渲染過程,如下圖:

image

  • 協調階段(Reconciler):官方解釋。 React 會自頂向下通過遞歸,遍歷新數據生成新的 Virtual DOM ,然後通過 Diff 算法,找到需要變更的元素 (Patch),放到更新隊列裡面去。
  • 渲染階段(Renderer):遍歷更新隊列,通過調用宿主環境的 API,實際更新渲染對應元素。宿主環境,比如 DOM、 Native、 WebGL 等。

在協調階段階段,由於是採用的遞歸的遍歷方式,這種也被成為 Stack Reconciler ,主要是為了區別 Fiber Reconciler 取的一個名字。這種方式有一個特點:一旦任務開始進行,就無法中斷,那麼 JavaScript 將一直佔用主線程, 一直要等到整棵 Virtual DOM 樹計算完成之後,才能把執行權交給渲染引擎,那麼這就會導致一些用戶交互、動畫等任務無法立即得到處理,就會有卡頓,非常的影響用戶體驗。

image

想要解決這個問題, React 現在的做法是引入 並發功能,通過一套優先級算法實現任務中斷 / 恢復。原有的 Stack Reconciler 架構無法做到任務中斷 / 恢復,不支持異步更新,因此 16 版本進行了重構,引進了 Fiber 架構。

什麼是 Fiber#

在上面的介紹中,我們已經確定 Fiber 的主要目標是讓 React 能夠使用並發調度。具體來說,需要實現以下目標:

  1. 任務中斷與恢復
  2. 為不同類型的任務分配優先級

為了做到這一點,我們需要設計一種方法將這些 “任務(Task)” 分解為單元,用於保存當前的更新中的一些信息,同時還需要保存一些靜態數據(如當前 Task 對應的 节點信息),這就是一個 Fiber 节點(FiberNode), Fiber 架構就是由多個 FiberNode 組成的樹狀結構。不同 FiberNode 間由 child、return、sibling 等屬性連接。

image

總的來說, Fiber 包含三層含義:

  1. 作為架構,Fiber 是由 FiberNode 組成的樹狀結構,區別於 16 版本前的 Stack Reconciler,16 版本的 Reconciler 基於 Fiber 實現。
  2. 作為數據結構,每一個 FiberNode 對應一個 ReactElement,保存了該組件的類型、DOM 結構等信息。
  3. 作為工作單元,每一個 FiberNode 保存了本次更新中該組件需要改變的狀態,需要執行的工作。

Fiber 架構的組成#

總的來說,Fiber 架構由三部分組成:

  • FiberRootNode:保存掛載的根節點等信息,也是執行更新開始的節點。
    • 負責 Current Fiber Tree 與 Wip Fiber Tree 的轉換
    • 保存任務的調度信息
  • HostRoot:應用在宿主環境上掛載的根節點,連接整顆 Fiber Tree

image

Fiber 工作原理#

Fiber 架構中會存在兩條 Fiber Tree,一顆是真實 UI 對應的 Fiber Tree,另外一顆是正在內存中構建的 Fiber Tree,分別被稱為 “current” 和 “workInProgress”, 這兩顆 Fiber Tree 通過 alternate 屬性相互連接。

這是一種被稱為 Multiple buffering - Wikipedia --- 多重緩衝 - 維基百科 (雙緩衝)的工作機制。試想一下,在 Fiber 需要更新時,我們不需要直接使用 current Fiber Tree 進行更新,而是基於 current Fiber Tree 複製一份 workInProgress Fiber Tree 進行更新。在更新完成後,只需要將兩顆 Fiber Tree 互換就完成了 Fiber Tree 的更新。

image

總結#

本文簡單介紹了 React 16 及以後版本引入的並發模型,介紹 Fiber 結構的組成及其工作原理。在接下來的章節中,將會介紹 React 中的三大核心流程及其交互,進一步分析 React 並發原理。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。