🛣️

React Nativeはどう進化しているのか

2024/12/11に公開

https://qiita.com/advent-calendar/2024/react-native
React Native Advent Calendar 2024 の 11日目の記事です。

はじめに

本記事は、React Nativeのバージョンアップの流れについて、2022年6月 にアナウンスされた v0.69(React 18サポートとHermesのバンドルが導入されたバージョン)から 現行(2024年12月現在)の最新バージョン0.76までにどのような変更があったのかをまとめました。

特に、React Native のアップデートの中心になっている 「New Architecture」「Hermes」 を軸に解説していますので、React Nativeに興味がある方の少しでも参考になればと思います🙏

前提

バージョンアップの軌跡を辿る前に、アップデートの軸となる要素を簡単に解説します。

React と React Native の関連性

React Nativeは、Reactを基盤としたネイティブアプリケーション開発用フレームワークです。そのため、Reactのバージョンアップと密接な関係があります。Reactが新機能を導入した際には、React Nativeもそれをサポートする形で更新されますが、以下の図のようにReactが先行してリリースされ、その後React Nativeが数ヶ月後に追従する形が一般的な流れになります。

ただし、実情は上記の図のようにすぐにReactの新しい機能が使用可能になるわけではなく、いくつかの段階を経る必要があり、その影響で利用可能なタイミングが遅れることが多いです😥

⚪︎ 依存するエコシステムの更新

React Nativeは、React以外にもMetroバンドラーやJavaScriptエンジン(Hermesなど)、ネイティブコード部分(iOSやAndroid)の互換性を考慮する必要があります。
これらのエコシステムが新しいReactに対応するためには、それぞれのアップデートが必要であり、全体の準備が整うまでに時間がかかります。

⚪︎ New Architecture への移行

Reactの一部の新機能(例: SuspenseやuseTransitionなど)は、React Nativeの従来のアーキテクチャーでは完全にサポートされない場合がありました。
New Architectureが整備されていく中で、これらの機能が徐々に利用可能になりました。

⚪︎ テストと安定化

React Nativeはクロスプラットフォームのため、Reactの新機能が両方のプラットフォーム(iOS/Android)で正しく動作することを確認する必要があります。

このプロセスには多くのテストとバグ修正が伴い、Reactのリリースから数ヶ月遅れることがあります。

実際に、React 18で useTransition や Suspense といった新機能が導入されましたが、React Nativeで完全に利用可能になったのは、New Architectureがデフォルトとなる v0.76(2024年10月) です。それまでの間、これらの機能は一部制限付きでの提供にとどまりました。

これらのように、ReactとReact Nativeは方向性としては密接に関連していますが、エコシステムの違いや実装のタイミングのズレから、React Nativeでの新機能利用には一定のタイムラグがあります。そのため、両者のアップデート情報を継続的にキャッチアップすることが重要になります👍

New Architecture

Old Architectureでは 『Bridge』 と呼ばれる中間レイヤーがJavaScriptとネイティブコード間の通信を仲介していました。このブリッジがReact Nativeの処理の中心にありましたが、いくつかの制約や課題がありました。そのため、New Architecture(Bridgeless) では、③ Async Bridgeが完全に削減されました🎉


Removing the Bridge

① <View />:

JavaScriptで定義されたReactコンポーネント(仮想DOM)を示します。
開発者が記述するUIロジックをReact Rendererが受け取ります。

② React Renderer:

JavaScriptエンジン上で動作する、仮想DOMを解析して処理するモジュール。
コンポーネントの状態やプロパティに基づいて、仮想的なUIツリーを生成します。

③ Async Bridge:

JavaScript(React Renderer)とネイティブコード(Native Renderer)の間の通信を仲介する非同期レイヤー。JavaScriptから送られたUIの更新命令を、ネイティブコードに翻訳します。

④ Native Renderer:

ネイティブプラットフォーム(iOSやAndroid)のUIエンジンで動作。Async Bridgeから受け取った命令を解釈して、実際のUI要素を生成します。

⑤ RCTView:

ネイティブUI要素(例: iOSのUIViewやAndroidのView)を指します。Native Rendererが生成する最終的なネイティブUI。

Old Architecture の課題

⚪︎ パフォーマンス問題

  • Bridgeを介した通信は非同期で行われ、データのシリアライズ・デシリアライズが発生するため遅延が発生しやすい。
  • 頻繁な通信がボトルネックになり、パフォーマンスが低下。

⚪︎ スレッドブロッキング

  • JavaScriptスレッドやメイン/UIスレッドが通信待ちでブロックされ、ユーザー操作に遅延が発生。
  • 特にスムーズなアニメーションや高速なタッチレスポンスを求められるシーンで問題となる。

⚪︎ ノードの冗長性

  • UIノードの状態をJavaScriptとネイティブ双方で管理しており、メモリ消費が大きくなる。
  • 状態の同期処理に手間がかかり、複雑なUIではエラーの温床に。

⚪︎ 優先度の低いタスクの中断ができない

  • 高優先度の更新(例: ユーザー入力や緊急のUI更新)を低優先度のタスクより優先する仕組みが不足。
  • アニメーションやスクロール中に「カクつき」やフレームの欠落が発生する。

そこで New Architecture(Bridgeless)では、JSI(JavaScript Interface)やTurboModules、Fabric Rendererが導入され、Bridgeの制約を解消しています。

New Architecture の利点

⚪︎ ブリッジが不要になり、直接通信による高速化

  • JavaScriptとネイティブ間の通信が直接行われるため、Bridgeのオーバーヘッドが解消。
  • 通信速度が向上し、レスポンスが早くなる。
  • 同期・非同期通信の柔軟な選択が可能に。

⚪︎ TurboModules

  • 必要なモジュールのみをロードする仕組みにより、アプリの起動時間が短縮。
  • メモリ使用量を削減し、パフォーマンスを向上。

⚪︎ Fabric Renderer

  • メイン/UIスレッドをブロックせず、バックグラウンドで低優先度タスクを処理可能。
  • 優先度の高いタスク(ユーザー入力など)をリアルタイムで処理。
  • イミュータブル(変更不可)なツリー構造を採用し、スレッドセーフな処理が可能。

これにより、従来のReact Nativeでどうしても残っていたWebアプリのような使用感が改善されました。
ブリッジが不要になったことで、ユーザーがボタンを押した際には即座にネイティブコードで処理が行われ、スクロール中もバックグラウンドで更新が行われるため、滑らかで速い操作感を実現することが可能になりました。これにより、ネイティブらしい使用感を提供できるようになりました。

Hermes

Hermesは、ReactやReact Nativeと同様にFacebook(現Meta)によって開発されたJavaScriptエンジンです。
2020年頃からReact Nativeでの導入が進められ、v0.64で初めて標準エンジンとして選択可能となり、v0.70ではデフォルトエンジンとして有効化されました。

実行モデルの違い: AOT vs JIT

Hermesでは、JavaScriptコードを事前に 「バイトコード」 という中間形式に変換して実行します。

通常のJavaScriptエンジン(例: V8やJavaScriptCore)は、JIT(Just-In-Time) コンパイルを採用しており、実行時にソースコードを解析(パース)してバイトコードを生成・実行します。一方、HermesではAOT(Ahead-Of-Time) コンパイルを採用し、アプリのビルド時にあらかじめバイトコードを生成します。この事前コンパイルにより、実行時のオーバーヘッドが削減され、以下のような効果があります:

  • アプリの起動時間が短縮される。
  • 実行時のリソース使用量が抑えられる。
  • バイトコードのみを保持するため、メモリ効率が向上。

gif
引用: Hermes as the Default · React Native

高効率なメモリ管理: 分割世代型ガベージコレクター(GC)

メモリ管理の効率を高めるために 分割世代型ガベージコレクター(GC) を採用しています。このアプローチにより、アプリケーションのリアルタイム性を確保しつつ、メモリ消費を最小限に抑えています。
以下のようなメリットがあります。

  • バックグラウンドで起動している場合場合でも、メモリ管理が効率的に行われる。
  • 不要になったオブジェクトを即座に解放し、次のアクションにメモリを効率よく割り当てる。
  • 低スペックのデバイスでも、スムーズな動作を実現。

Hermesは、React Nativeアプリのパフォーマンスを大幅に向上させるために設計されており、特にリソースの限られたモバイル環境において効果を発揮します。AOTコンパイルと効率的なGCによるメモリ管理により、安定した動作と高速なレスポンスを実現し、より良いユーザー体験を実現します。

バージョンアップの軌跡 🎉

これまでのReact Native

React Nativeは、2015年にFacebook(現Meta) によってオープンソースとして公開されたフレームワークで、JavaScriptでネイティブアプリを開発するためのプラットフォームです。

React Nativeはクロスプラットフォームのため、1つのコードベースでiOSとAndroid向けのアプリを効率よく開発ができます。
また、JavaScriptコードを利用しながら最終的にネイティブのUIコンポーネントに変換されるため、Webアプリとは異なる、ネイティブアプリ特有の見た目や操作性を実現しています。

特に、開発のスピードを重視する組織や、Webエンジニアが多い組織では、React Nativeはその利便性から広く採用されてきました。

ただし、実際に課題も多く存在し、パフォーマンス(特にアニメーションや複雑なUIの更新)がWebアプリに近く、ネイティブアプリ感がどうしても及ばないケースがありました。
また、新しいReactの機能(Suspense や Concurrent Modeなど)は、Old Architecture では対応できない場合がありました。

以下の直近のアップデートの傾向から、よりネイティブらしいユーザービリティを実現できるようなエコシステムの進化が見られるかと思います🎊

v0.69

2022年6月21日 にリリースされました。

React 18のサポート

React 18がデフォルトで有効化されることで新しいフックのuseIdやuseTransition、 Suspenseなどが利用できるようになりました。

ただ、これらの機能を完全に活用するには、New Architecture の移行が必要で、Old Architecture では一部の機能に制限がありました。
↓で再度記載していますが、の v0.76(2024年10月リリース)では、New Architecture がデフォルトで有効化され、SuspenseやuseTransitionなどのReactの最新機能がフルサポートされました。

Hermesエンジンの統合

Hermesのバージョン管理がReact Native自体に組み込まれたため、React Native各バージョンが、対応するHermesの特定バージョンを管理されるようになったため、package.jsonやビルドスクリプトで手動指定する必要がなくなりました。

他にもAndroidの新しいビルドシステムの導入(Gradle 7など)やGradleのバージョンアップなど、更新がありましたがこちらでは省略します。

v0.70

2022年9月5日 にリリースされました。

Hermesがデフォルトエンジンになる

オプションとしてのHermesを利用するのではなく、React Nativeのデフォルトエンジンとして有効化され、特別な設定なしでHermesが利用されるようになりました。(移行が推奨 → デフォルトに)
開発者がHermesを明示的に選択・設定しなくても、自動的にHermesが利用されます。これにより、エンジンのバージョン管理や互換性調整がReact Native側で統一的に行われ、開発者の負担が軽減されました。React Native の New Architecture や Codegen の統一設定と連動し、より効率的に動作します。

New Architecture の採用の促進

React Native 0.70では、(FabricやTurboModules)の採用を促進し、移行をスムーズにするためのドキュメントが強化され、移行ガイドやチュートリアルが追加されました。

v0.71

2023年1月12日 にリリースされました。

TypeScriptのデフォルト化

新規プロジェクトでTypeScriptがデフォルトになりました。これにより、プロジェクトには自動的にtsconfig.jsonが含まれ、初期設定のままで利用可能です。

また、従来使用されていた @types/react-native が不要になり、react-nativeパッケージ内で正確な型定義が直接提供されるようになりました。これにより、React Nativeのバージョンアップと型定義の更新が同期され、メンテナンスがさらに簡単になりました。

Flexbox Gapのサポート

gap、rowGap、columnGapプロパティがサポートされ、Flexboxの子要素間のスペースを簡単に調整できるようになりました。

これまでは子要素にmarginを個別に設定する必要がありましたが、gapを使用することで、一貫性のあるレイアウトがより簡単に実現できるようになりました。


引用: React Native: Styles- Part V. Styles continue.. | by Divyanshu Mamidwar | Medium

Web標準のPropsをNativeでも追加

ARIA(Accessible Rich Internet Applications)プロパティがサポートされました。これによりユーザー体験を向上させる aria-labelaria-labelledby などプロパティが追加されました。

さらにWebエンジニアには馴染みがあるようなWeb DOM APIに似たPropsをサポートするようになりました。Imageのaltやsrc、tintColorやTextInputのautoCompleteやinputModeなどが追加されました。

v0.72

2023年6月21日 にリリースされました。

Metroの新機能

Metroは、React Nativeアプリケーション専用のバンドラーで、JavaScriptやその他のアセットを効率的にまとめ、モバイルアプリに適した形で提供する役割を担っています。必要最小限のコードをバンドルしてアプリに配信したり、ホットリロードとファストリフレッシュをサポートしています。

この段階ではまだベータ版ですが、シンボリックリンクのサポートしました。モノレポやpnpmのワークフローを簡略化され利用がスムーズになりました。

Hermesの性能向上

大規模オブジェクトリテラルの重複除去アルゴリズムを改善されました。全データセットを巨大なオブジェクトリテラルで表現していたケースでは、最大97% のコンパイル時間短縮を達成。

v0.73

2023年12月6日 にリリースされました。

Hermesのデバッグ機能向上

従来はアプリ起動直後のログを確認するのが困難でしたが、Hermesがすべてのconsole.log()呼び出しをバックグラウンドで記録するようになりました。
これにより、デバッガ接続時に過去のログを確認可能になりました。

Android 14サポート

Android 14(APIレベル34)を正式サポートし、最新のAndroid機能やセキュリティ向上に対応しました。これにより、最新のAndroidエコシステムでの動作を保証しつつ、新しいプライバシー機能(選択的メディアアクセス)も利用可能です。
また、ビルド環境としてJava 17が必須化され、よりモダンで効率的な開発環境が提供されます。

v0.74

2024年4月22日 にリリースされました。

Yoga 3.0

YogaはFacebook(現Meta)が開発した、React Nativeや他のUIツールキットで使用される軽量で高速なレイアウトエンジンで、スタイリングの予測可能性が向上します。
具体的には、alignContent: 'space-evenly' と position: 'static' などのサポート追加されました。


引用: Announcing Yoga 3.0 | Yoga

Bridgeless Mode

New Architecture で Bridgeless Modeがデフォルト化。Interop Layerが強化され、Bridgeless環境下での既存ライブラリの互換性を確保。新しいレンダラーのInterop Layerがデフォルト有効化されました。

デフォルトがYarn 3

React Native CLIで初期化された新しいプロジェクトにYarn 3が採用され、デフォルトでYarn3.6.4を使うようになりました。

v0.75

2024年8月14日 にリリースされました。

Yoga 3.1とレイアウト改善

% 値のサポート追加: gap, columnGap, rowGap などにパーセンテージ値を使用可能。
transform プロパティでの%サポートされコンテナサイズを基準にした動的な配置が実現可能となり、アニメーション等で柔軟に使用できるようになりました。

const styles = StyleSheet.create({
  container: {
    rowGap: '20%',
  },
  box: {
    transform: [{ translateY: '100%' }],
  },
});

New Architectureの安定化

多数のバグ修正(例: adjustsFontSizeToFit や textAlign に関する問題)。Bridgeless Mode のさらなる改良と安定化。

Expo推奨

React Nativeアプリの開発にExpoなどのフレームワークを使用することを推奨。
Expoとは、React Nativeの公式エコシステムであり、開発環境のセットアップを簡素化されるフレームワークです。

このアップデートにより、react-native init コマンドの廃止予定(2024年12月31日以降)。
テンプレートの分離: @react-native-community/template パッケージに移行。

v0.76

2024年10月23日 にリリースされました。

New Architecture がデフォルト

React Native 0.76から、New Architectureがデフォルトで有効化になりました。これにより従来から利用できなかったReact18の機能等が利用できるようになりました。

高品質なネイティブアプリケーション開発を可能にする内部リファクタリング。本番環境での利用が推奨される段階になりました。

React Native DevTools

React Native専用のDevToolsが新たな標準デバッグツールとしてリリースされました。このツールは開発者体験の向上されるようになりました。

  • Chrome DevToolsに基づいたデバッグ(ブレークポイント、ステップ実行、スタック検査など)。
  • React DevToolsの統合(コンポーネントインスペクターとプロファイラーの高速化)。
  • DevToolsの接続が再起動や再コンパイル後も維持される。
  • 即時起動と複数のエミュレーターやデバイスのサポート。

これで、Web Developer Tools に近い感覚でデバッグができるようになりました。ただし、Network など一部の機能はまだサポートされていないため、今後のアップデートに期待してます🤩


引用: React Native DevTools · React Native

Hermesのさらなる進化

引き続きHermes JavaScriptエンジンも改良されています。
ECMAScript 2024対応し、最新のJavaScript仕様に対応し、開発者がモダンな言語機能を活用可能になりました。
大規模データセットの処理速度や、アプリ起動時のコンパイル時間が短縮され、ユーザー体験が向上されました。

さいごに

React Nativeは、Reactを基盤にしながら、ネイティブアプリケーション開発に特化した強力なフレームワークとして進化を続けています。特に、New Architectureの普及やHermesエンジンの改良により、開発者体験とユーザー体験の両面で、パフォーマンスや安定性が大幅に向上しました✨

ただし、New ArchitectureやHermesといったエコシステムの刷新に関する情報は、意識的に追わないと置いてけぼりになってしまう部分でもあります。これらの技術はReact Nativeの進化を把握する上で重要な要素であるため、引き続きバージョンアップや技術動向を注視していきたいと思います。

個人的には、ネットワークの挙動確認のために普段 Proxyman を利用していますが、React Native DevTools内でネットワーク関連のデバッグが完結できるようになると、より開発がスムーズになると感じています。今後のDevToolsの進化に期待してます!
さらに、Web Developer Tools に近い感覚で Lighthouseのように、React Nativeにも似たような総合的なパフォーマンスチェックツールが導入されると、アプリ品質の向上がさらに加速し良い開発体験を得られると思っています🙌

参考文献

Discussion