⚛️ React Boundary
内部理解 — アーキテクチャ

Fiberとは何か?

React 16で導入されたFiberアーキテクチャ。なぜ旧アーキテクチャではダメだったのか、Fiberは何を可能にしたのかを解説します。

🎯 結論から言う

Fiberとは「中断可能な作業単位」のデータ構造です。

React 16以降、すべてのコンポーネントは「Fiber」という内部オブジェクトとして管理されます。

📜 なぜStack Reconcilerではダメだったのか?

React 15以前はStack Reconcilerというアーキテクチャを使っていました。 これはJavaScriptのコールスタックを使ってコンポーネントを再帰的に処理するものでした。

Stack Reconcilerの問題

// Stack Reconcilerのイメージ(再帰で全部処理)
function reconcile(component) {
  // 1つ処理したら...
  const children = component.render();
  
  for (const child of children) {
    reconcile(child); // 再帰!中断できない
  }
}
  • 再帰なので途中で中断できない
  • コンポーネントが深いと処理に数十msかかる場合がある
  • その間はメインスレッドがブロックされ、ユーザー入力が無視される
  • 60fps(16ms/frame)を維持できない → UIがカクつく

具体的な問題例

1000件のリストを再レンダリング中にユーザーがボタンをクリックした場合、 Stack Reconcilerはリスト処理を終えるまでクリックを処理できません。 処理が50ms かかれば、ユーザーは50msの「フリーズ」を体験します。

🧵 Fiberが解決したこと

Fiberは再帰をループに変えることで、処理を任意の時点で中断・再開できるようにしました。 各コンポーネントに対応するFiberオブジェクトを連結リスト(リンクトリスト)として管理します。

Fiberオブジェクトの構造(簡略版)
interface Fiber {
  // コンポーネントの種類
  type: string | Function;
  
  // propsとstate
  pendingProps: Props;
  memoizedState: State;
  
  // ツリー構造(連結リスト)
  child: Fiber | null;      // 最初の子
  sibling: Fiber | null;    // 次の兄弟
  return: Fiber | null;     // 親
  
  // 変更フラグ
  flags: Flags;             // 更新・挿入・削除
  
  // ダブルバッファリング
  alternate: Fiber | null;  // 前回のFiber
}
// Fiberのイメージ(ループで処理 → 中断可能)
function workLoop(deadline) {
  while (nextUnitOfWork && deadline.timeRemaining() > 0) {
    // 1つのFiberを処理
    nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
  }
  
  if (nextUnitOfWork) {
    // 時間切れ → ブラウザに制御を返す(次フレームに再開)
    requestIdleCallback(workLoop);
  } else {
    // 全Fiber処理完了 → commit phase
    commitRoot();
  }
}

requestIdleCallback(実際はReact独自のスケジューラー)で ブラウザが余裕のある時間帯(アイドル時間)に作業を小刻みに処理します。 ユーザー入力が来たら即座にそちらを優先できます。

🌳 ダブルバッファリング

Reactは常に2つのFiberツリーを保持します——current tree(現在の画面)と work-in-progress tree(作業中の新しいツリー)です。

ダブルバッファリングの仕組み
current tree

現在ブラウザに表示されている状態のFiberツリー

work-in-progress tree

新しい状態で構築中のFiberツリー(中断可能)

↓ commit phaseで入れ替え
work-in-progress が新しい current になる。old current は次回の work-in-progress として再利用。

この設計により、レンダリング中(render phase)にユーザーが見ているUIは変わりません。 ブラウザへの反映はcommit phaseで一瞬で行われます。

🚀 FiberがConcurrent Modeを可能にした

Fiberアーキテクチャによって、Reactは優先度に基づいた処理スケジューリングを実現しました。

最高
Immediate
SyncレーンのsetState(FlushSync)
UserBlocking
クリック・入力などのユーザーインタラクション
Normal
通常の状態更新(データフェッチ後など)
Low
startTransition でマークされた更新
最低
Idle
Suspenseのprefetch・アイドル時のプリレンダリング

startTransitionの意味

React 18のstartTransitionは 「この更新は遅くていい」とReactに伝えるAPIです。 Fiberのスケジューラーがこの更新を低優先度として扱い、ユーザー入力の処理を先に行います。

📌 まとめ

  • ✓ Stack Reconcilerは再帰処理で中断できず、複雑なUIでJankが発生していた
  • ✓ Fiberは「作業単位」を連結リストで管理し、ループ処理で中断・再開を実現
  • ✓ ダブルバッファリングで、ユーザーが見るUIを変えずに計算できる
  • ✓ 優先度スケジューリングにより、入力など高優先度タスクを先に処理できる
  • ✓ startTransitionはFiberのスケジューラーに「低優先度」を伝えるAPI

関連記事