♠️

React Fiberとその周りについて調べた

2021/09/27に公開
2

「Reactを自作しよう」をやっている途中にReact Fiberを知りたくなったので、調べた内容のメモです。

https://zenn.dev/akatsuki/articles/a2cbd26488fa151b828b#step-4-ファイバー

Fiber

Fiberの目的

  • Reactがスケジューリングや割り込み処理をできるようになること

Fiber以前のレンダリング処理

  • Fiberより前のレンダリング処理は再帰的に行うもので、重い処理だとレンダリングをブロックしてしまったり、途中で止めることもできなかった
  • 同期的な処理を停止したり再開したりできるようにするには、処理をユニットとして分割する必要があるので、分割するフェーズがある

Fiber Node

  • コンポーネントの状態とDOMを保持するオブジェクト
  • React Elementに1対1で存在する
  • 差分比較に使用される
  • レンダリングごとに再生成は行われない
  • 連結リスト(Fiber Tree)にすることで、ひとつひとつの更新処理を独立したものとして扱えるようになる

Fiber Tree

  • Fiber Nodeを連結リストにしたもの
    • 初回レンダリング時にReactがReact Elementをチェックし、Fiber Treeを作成する
  • 1つ以上のルートとなるDOM要素を持っており、それがFiber Treeのルートとなる
  • 子要素・兄弟要素・親要素へリンクしている
  • 子や兄弟がいない場合は親に行き、最終的にrootに到達するまで遡っていく
  • rootに到達した場合はレンダリング処理が終了したことになる

Fiber Treeとレンダリング

  • Current Tree とは現在のUIを描画するために使用されたもの
    • ReactがCurrent Treeを通過するとき、既存のFiber NodeにWorkInProgressツリーを構成する alternate nodeを作成する
      • このnodeは初回レンダリング時のrenderメソッドによって取得したReact Elementからのデータを使用して作成される
  • WorkInProgress Treeとは、次回描画に使用されるツリー
    • WorkInProgress ツリーがUI上に描画されると、Current Treeとして扱われる
  • 探索処理を行う前に、ルートとなるFiber Nodeを持ち、全てのFiber Treeは1つのルートを持つ

Fiber Treeの探索処理

  • 最上位のReact Elementに対してFiberを作成する
  • 子要素に行き、それに対してFiberを作成する
    • 子要素がない場合はnullになる
  • 子要素のある一番深い位置まで探索し、無くなれば兄弟要素に対してFiberを作成する
  • 兄弟要素の一番深い位置まで探索し終えたらroot(親要素)に戻る

Fiberの副作用

  • Reactではデータ取得やDOM操作を副作用としている
    • Fiber NodeもeffectTagフィールドを持つことで副作用に対応している

スケジューリング

  • Reactが更新処理の優先順位を判断・決定する処理のこと
  • 更新の種類には優先順位があり、後回しにできるものがある
    • 重い処理や取得したばかりの要素のレンダリングなどは優先順位が低くなる
    • UIでは変更がすぐに反映される必要はなく、そうしようとするとフレーム落ちやパフォーマンスの悪化になりUXに悪影響が出る
  • 優先順位の判断はReactに任せることができるので開発者は何も気にする必要がない

リコンシエーション (差分検出処理)

  • どの部分に変更が必要なのかを判断するためにDOM同士を比較するアルゴリズム
  • Reactアプリケーションをレンダリングするとき、アプリケーションを構成するノードをメモリに保存する
    • この後、差分検出のためにレンダリング環境に流し込まれる
  • コンポーネントの種類が異なると差分変更処理も大きくなり、Reactは差分を出すのではなく、元のツリーを置き換えようとする
  • 差分検出を行うリコンサイラーと画面表示を行うレンダラが別になっているのでWebやモバイルなど異なった環境でもReactを使うことができる

参考資料

Discussion

XU ZHONGWEIXU ZHONGWEI

世の中によく話している仮想DOMもFiberNodeに変わったことと理解してもよいですか?
これからは仮想DOMではんく、FiberNodeと呼ぶべきでしょうか?