iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
JavaScript

React 觀念架構:從js 基礎到Hook 底層邏輯 系列 第 21 篇

Day 21 Fiber 雙緩衝機制與 WorkLoop:React 如何調度優先級?

  • 分享至 

  • xImage
  •  

今天我們要說明 React 16+ 能實現非阻塞渲染 (Non-blocking Rendering) 與可中斷更新 (Interruptible Render) 的核心底層:Fiber 雙緩衝機制 (Double Buffering) 與 WorkLoop 調度核心。

一、 為什麼需要 Fiber?傳統 Stack Reconciler 的痛點

在 React 15 及更早版本中,協調器 (Reconciler) 採用的是遞迴同步運算的 Stack Reconciler。

  • 痛點:一旦觸發更新,React 會一氣呵成、無法中斷地遞迴比對整棵 Virtual DOM 樹。當組件結構龐大時,CPU 運算時間若超過 16ms,就會導致瀏覽器主線程 (Main Thread) 無法及時處理使用者輸入或動畫格,出現肉眼可見的掉幀與卡頓 (Jank)。

  • 解法:React 16 將 Stack 拆解為以鏈表 (Linked List) 為基礎的 Fiber Node,把一次龐大的更新任務拆分成無數個微小的 Work Unit(工作單元),實現可排程、可中斷、可復原的調度機制。

二、 Fiber 雙緩衝機制 (Double Buffering)

為了確保在背景處理複雜計算時畫面不會閃爍或出現半成品 UI,React 借鏡了圖形學中的 Double Buffering 技術,在記憶體中同時維護兩棵 Fiber 樹:

  1. current 樹:代表當前螢幕上已渲染出來的 UI 畫面。

  2. workInProgress (wip) 樹:代表正在背景進行 Reconcile 計算、準備渲染的下一幀 UI 畫面。

[螢幕顯示 (UI)]
      │
      ▼
 current Fiber 樹 ───(alternate)───► workInProgress Fiber 樹 (背景建構中)
  • alternate 指針:current 節點與 workInProgress 節點透過 alternate 屬性互相引用,實現雙向連接。

  • Commit 階段一秒切換:當 workInProgress 樹在背景計算 completion 後,React 只要將根節點 (HostRoot) 的 current 指針切換指向 workInProgress 樹,就能在極短時間內完成 UI 替換!

三、 WorkLoop 工作迴圈與可中斷調度

React 的調度核心就是 WorkLoop。它會在瀏覽器的空閒時間(透過 Scheduler 模組排程)逐步執行 Fiber 節點的比對:

// 簡化版 React 內部 WorkLoop 邏輯
function workLoopConcurrent() {
  // 只要還有剩餘 Work Unit 且 Scheduler 判定當前 Time Slice 尚未逾期,就繼續執行
  while (workInProgress !== null && !shouldYield()) {
    performUnitOfWork(workInProgress);
  }
}

機制拆解:

  1. shouldYield()(時間片 Time Slicing):每一個 Time Slice 預設約 5ms。當 5ms 耗盡或有高優先級事件(如使用者打字、點擊)進入時,shouldYield() 會回傳 true,主動讓出主線程給瀏覽器回應使用者。

  2. 三向鏈表遍歷:Fiber 節點透過 child(第一個子節點)、sibling(下一個兄弟節點)、return(父節點)三個指針連接,讓 React 可以隨時中斷並記錄「當前處理到哪一個 Fiber 節點」,下次恢復時從該節點繼續。

四、 Priority Scheduling(優先級調度)

React 內部透過 Lane 模型(31 位元的位元遮罩 Bitmask)來標記各個更新任務的優先級:

  • SyncLane / InputContinuousLane:高優先級(如離散點擊 onClick、文字輸入 onChange),必須立刻處理。

  • DefaultLane:中優先級(如 API 資料回傳觸發的更新)。

  • TransitionLane / OffscreenLane:低優先級(如頁面切換動畫、隱藏內容預載入),允許被高優先級任務插隊 (Interruption)。

當高優先級任務插隊時,React 會中斷並放棄當前計算到一半的低優先級 workInProgress 樹;等待高優先級任務 Commit 到畫面後,再重新啟動低優先級任務。


上一篇
Day 20 自訂 Hook (Custom Hooks) 封裝:抽離業務邏輯與邏輯複用
下一篇
Day 22 Render 階段與 Commit 階段:Reconciler 與 Renderer 如何協作?
系列文
React 觀念架構:從js 基礎到Hook 底層邏輯 共 22 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言