1. React Fiber 的核心目標?
-
?增量渲染?:將大型更新拆解為可中斷的小任務(時間切片),避免阻塞
-
主線程?優先級調度?:動態管理任務執行順序(如用戶交互 > 動畫 > 數據加載)。
-
與瀏覽器協作?:利用瀏覽器渲染周期(rAF)和空閑時間(rIC理念)優化性能。
一句話定義:
React Fiber是React 16+的核心重寫算法,通過增量渲染和任務分片實現高性能異步更新。旨在解決傳統同步渲染阻塞主線程導致的卡頓問題。
2. React Fiber 的核心原理
之前的版本中,React使用遞歸
的方式處理組件樹的更新,這個過程是同步
的,一旦開始就不能中斷,可能導致長時間占用主線程,造成界面卡頓,尤其是在處理復雜組件時。
Fiber是將組件樹
拆解為?鏈表結構?
的 Fiber 節點
(每個節點對應一個可中斷/恢復
的“工作單元”),通過?優先級調度?
(如用戶交互任務優先)和?時間切片?
(利用瀏覽器空閑時間分批次處理任務),實現異步可中斷
的渲染流程。
Fiber 在協調階段
(Render Phase)增量構建虛擬樹
并標記副作用(如 DOM 更新),在提交階段
(Commit Phase)同步
執行所有變更,同時通過?雙緩沖機制?
(交替使用 current 和 workInProgress 樹)和?副作用鏈表?優化性能,從而支持并發模式(Concurrent Mode),顯著提升復雜應用的響應速度與流暢度。
在 React 的 Fiber 架構中,requestAnimationFrame
、?鏈表?
和 ?調度器?
三者緊密結合,主要體現在 ?任務調度策略?
和 ?執行效率優化?
上
2.1. Filber中的鏈表(任務存儲與遍歷?)
Fiber 樹本身的鏈表結構?和?副作用鏈表(effect list)?是?兩個不同的鏈表
2.1.1. Fiber 樹鏈表(主鏈表)?
作用?:
表示
組件樹
的完整結構
,用于協調階段(reconciliation)
的遍歷
和任務分片
。
數據結構?:
每個 Fiber 節點通過
child、sibling、return
三個指針構成?樹形鏈表?(深度優先遍歷的線性化結構)。
class FiberNode {child: Fiber | null; // 第一個子節點sibling: Fiber | null; // 下一個兄弟節點return: Fiber | null; // 父節點// ... 其他屬性(type, stateNode 等)
}
特點?:
用于
遞歸的?可中斷恢復?
(通過保存當前處理的 Fiber 節點指針)。
是 React處理組件更新
的?核心數據結構?。
?與調度器的關系?
:
每個鏈表節點(FiberNode)包含任務信息
、優先級標記
和指針
(child/sibling/return)
調度器通過鏈表實現?可中斷恢復?
:保存當前節點指針,下次從中斷處繼續
2.1.2. 副作用鏈表(effect list)?
作用?:
收集所有需要執行副作用的 Fiber 節點(如 DOM 操作、生命周期調用),在提交階段(commit phase)批量處理。
?數據結構?:
通過 firstEffect、lastEffect、nextEffect 指針構成的?單向鏈表?。
class FiberNode {firstEffect: Fiber | null; // 鏈表頭lastEffect: Fiber | null; // 鏈表尾nextEffect: Fiber | null; // 下一個副作用節點effectTag: Placement | Update | Deletion; // 副作用類型
}
?特點?:
是
Fiber 樹的?子集?
,僅包含需要處理
的節點。
在協調階段
動態構建,提交階段直接遍歷此鏈表執行 DOM 操作
副作用鏈表(effect list)的工作流程?
每個Fiber節點在完成工作后,如果有副作用,會被添加到鏈表中。firstEffect和lastEffect用來指向鏈表的頭和尾,nextEffect
是每個節點的指針。在提交階段,React遍歷這個鏈表,依次處理每個副作用
,如DOM更新
、生命周期方法
的調用等。這種結構使得React能夠高效地批量處理副作用
,而不必在協調階段頻繁操作DOM,從而提高性能。
React Fiber 架構中任務調度與副作用處理的優先級機制:
于優先級,副作用鏈表可能并不直接管理優先級
,而是由調度器決定哪些Fiber節點需要先處理
。高優先級的更新會導致重新構建副作用鏈表,確保緊急的副作用先執行。例如,用戶輸入觸發的更新可能打斷正在進行的渲染,優先處理相關副作用,然后再處理低優先級的任務。
- ?中斷與恢復?:高優先級任務可中斷當前協調過程,保留未完成的副作用鏈表,后續恢復時繼續構建。
- 多優先級鏈表?:React 內部維護多個鏈表(如 pendingPassiveEffects),區分同步與異步(如 useEffect)副作用。
-
?同步副作用?:useLayoutEffect 在提交階段同步執行。
-
?異步副作用?:useEffect 被推入異步隊列,在瀏覽器空閑時處理。
-
在構建鏈表時,React可能采用深度優先的后序遍歷方式
,確保子節點的副作用在父節點之前處理
,這樣在DOM操作時可以正確應用變更。例如,當子節點需要被刪除時,先處理子節點的刪除,再處理父節點的更新,避免父節點更新后子節點不存在導致的錯誤。
最后,需要理解副作用鏈表在React整個渲染流程中的位置。協調階段(render phase
)負責找出所有需要變更的節點
并構建
副作用鏈表,提交階段(commit phase)
則遍歷鏈表執行變更
。這種分離使得React可以異步處理渲染,提高響應能力。
2.1.3. 為什么分開設計??
1?.關注點分離?:
Fiber 樹負責?任務調度和中斷恢復?(協調階段)。
副作用鏈表負責?高效執行 DOM 操作?(提交階段)。
?2.性能優化?:
提交階段只需遍歷少量副作用節點,避免全樹遍歷。
批量處理 DOM 更新,減少瀏覽器重排/重繪。
?總結?
:
?不是同一個鏈表?,但副作用鏈表是 Fiber 樹的衍生結構
。
Fiber 樹是?全局任務管理?
的骨架,副作用鏈表是?局部優化?
的結果。
兩者協作實現 React 的?可中斷渲染?和?高效更新?
。
2.2?. requestAnimationFrame(rAF)?:調度時機控制?
?requestAnimationFrame(rAF)? 是瀏覽器提供的原生 API,用于在下一次屏幕刷新
(通常是每秒 60 次,即 16.6ms/幀)前執行回調函數。
?作用?
在每一幀
渲染前
執行高優先級任務
(如動畫、UI 更新)
?與調度器的關系?:
React 調度器
用 rAF 作為?高優先級任務
的觸發時機?
,確保視覺更新及時
避免 setTimeout 因時間不精確導致的丟幀問題
核心目標:
- 動畫與視覺更新?:
rAF 確保回調函數在瀏覽器?下一幀渲染前執行?,與屏幕刷新率(60Hz)同步,避免丟幀。
- React 中的應用?:
高優先級任務對齊?:React 將動畫、布局更新等高優先級任務標記為與 rAF 同步執行。
?避免布局抖動?:在 rAF 回調中批量處理 DOM 讀寫,減少強制布局計算(如 offsetWidth)。
特性 | requestAnimationFrame | requestIdleCallback |
---|---|---|
?觸發時機? | 每幀開始前(16.7ms/60FPS) | 瀏覽器空閑時(無高優先級任務) |
?用途? | 動畫、視覺更新 | 后臺任務(日志、預加載) |
?優先級? | 高(與渲染強相關) | 低(可被高優先級任務打斷) |
?React調度參考? | 影響高優先級任務分片 | 啟發低優先級任務分片(如并發渲染) |
?執行耗時限制? | 需控制在3-4ms以內 | 默認50ms(通過timeout 參數可調) |
?兼容性? | IE10+ | 需polyfill(如React的scheduler ) |
2.3. React 自研調度器(Scheduler)
是其并發模式(Concurrent Mode)的核心底層機制,相比傳統更新調度方式具有以下顯著優勢:
2.3.1.優先級調度?
? 更精細的任務優先級控制?
- 5級優先級劃分?:
Immediate(同步) > UserBlocking(用戶交互) > Normal(默認) > Low(數據加載) > Idle(空閑任務)
協作流程示例?
- ?用戶點擊按鈕?(Immediate 優先級):
同步執行回調,更新狀態,標記相關 Fiber 節點。- ?觸發動畫?or搜索建議(UserBlocking 優先級):
將更新任務放入 rAF 隊列,確保下一幀渲染前完成。- ?數據加載?(Low 優先級):
拆分任務為 5ms 的塊,在調度器檢測到空閑時逐步執行。
- 動態調整?:高優先級任務可中斷低優先級任務(如渲染中途響應用戶點擊)。
2.3.2.避免瀏覽器主線程阻塞
1.時間切片(Time Slicing)的概念
時間切片邏輯?:將任務
拆分
為5ms
的塊,動態檢查剩余時間
,通過shouldYield()判斷是否讓出主線程,保證UI響應。優先處理用戶輸入
等高優先級
事件。
用于將渲染任務
分解成更小的單元,這樣可以在瀏覽器的空閑時段
執行這些任務,避免阻塞用戶交互。這聽起來類似于瀏覽器的requestIdleCallback API
,允許在空閑時間執行任務,但React可能自己實現了更精細的控制。
requestIdleCallback(rIC)的理念?
空閑時段處理
低優先級
任務?:rIC 在瀏覽器空閑時執行非緊急任務
(如日志、預加載),避免干擾關鍵渲染和交互。
2.?基于MessageChannel的調度?:
React 自研調度器,通過
MessageChannel
或setTimeout ?模擬空閑檢測?
。
MessageChannel相比setTimeout,利用事件循環的宏任務機制更精準控制執行時機,避免任務堆積導致卡頓。
React Fiber 未直接使用 rIC?:這是因為rIC的瀏覽器兼容性
和觸發頻率
不夠理想。React的調度器會將任務分成小的時間片,并在每個時間片結束時檢查是否有更高優先級的任務需要處理,從而避免長時間阻塞主線程。
2.3.3. 更智能的后臺任務處理?
?空閑期
利用?:
通過requestIdleCallback
的polyfill(兼容方案),在瀏覽器空閑時執行低優先級任務(如日志上報、預渲染)。
?任務饑餓保護?:
防止低優先級任務因長期無法執行被“餓死”(超過超時時間會強制提升優先級)。
2.3.4. 與React深度集成?
? 協調器(Reconciler)聯動?:
調度器知曉Fiber節點結構,可精準暫停/恢復渲染任務,實現可中斷渲染。
?并發特性基礎?:
支持startTransition、useDeferredValue等API的底層依賴。
對比傳統調度方案?
能力 | 傳統setState更新 | React調度器 |
---|---|---|
任務中斷 | ? 不可中斷 | ? 高優任務可中斷低優任務 |
瀏覽器阻塞 | 可能阻塞主線程 | 通過時間切片避免阻塞 |
優先級控制 | 無差別處理 | 5級動態優先級 |
后臺任務利用 | 依賴手動實現 | 內置空閑期調度 |
2.4 雙緩沖機制
2.4.1. 雙緩沖的定義
Fiber 架構的核心機制?,用于在 ?協調階段(Reconciliation)? 和 ?提交階段(Commit)? 之間高效
管理組件狀態更新
,確保 React 的 ?可中斷渲染?
和 ?一致性更新?
。
雙緩沖是計算機圖形學中的經典技術,指 ?同時維護兩套數據結構?:
- 當前緩沖(Current)?:正在渲染或已渲染的 UI 狀態(對應屏幕上顯示的內容)。
- 工作緩沖(WorkInProgress,WIP)?:正在計算的新狀態(尚未提交到屏幕)。
React 借用這一概念,在 Fiber 架構中維護 ?兩棵 Fiber 樹?:
- ?
current
樹?:當前已渲染的 Fiber 樹(對應真實 DOM
)。 - ?
workInProgress
樹?:正在構建的新 Fiber 樹
(用于計算更新)。
2.4.2. 雙緩沖的核心流程?
?(1) 協調階段(Reconciliation)?
- React 從 current 樹
克隆出
workInProgress 樹(通過 alternate 指針關聯)。 - 在
workInProgress
樹上進行 ?Diff 計算?
,標記需要更新的節點
(effectTag)。 - 如果任務被中斷(如高優先級任務插入),可以
丟棄 workInProgress 樹并重新開始
,而不會影響 current 樹(已渲染的 UI)。
?(2) 提交階段(Commit)?
當 workInProgress 樹構建完成,React 執行 ?原子性切換?:
root.current = finishedWork; // 切換 current 和 workInProgress
此時:
- 新的 workInProgress 樹變為 current 樹(對應最新 UI)。
- 舊的 current 樹變為新的 workInProgress 樹(供下次更新使用)。
通過維護兩棵 Fiber 樹(current
和 workInProgress
),實現:
- 計算與渲染分離。
- 高優先級任務搶占。
- 無閃爍的 UI 更新。
最終提升復雜應用的流暢度和響應速度。