Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】Benchmarking Expo Router Navigation: Memory Footprint and Frame Drop Analysis Under Deep Stack Depth

2026年10月24日に「Dev.to」が公開したITニュース「Benchmarking Expo Router Navigation: Memory Footprint and Frame Drop Analysis Under Deep Stack Depth」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

Expo Routerで画面の階層が深くなると、アプリの動作が重くなり、アニメーションがカクついたりメモリが増えたりする問題が発生した。原因は動的なスタイル計算などで、`StyleSheet`による静的なスタイル定義に改善することで、パフォーマンスが大幅に向上した。

ITニュース解説

現代のモバイルアプリケーション開発において、ユーザーインターフェース(UI)のスムーズな動作は、優れたユーザー体験を提供する上で非常に重要である。特に、異なる画面への移動(ナビゲーション)が遅延すると、ユーザーはアプリの操作性に不満を感じる可能性がある。今回、React Navigationという広く使われている画面遷移ライブラリから、Expo Routerというファイルベースの新しいルーティングシステムに移行するプロジェクトにおいて、予期せぬパフォーマンス問題が発生した事例が報告された。この問題は、アプリケーションの画面遷移が深くネストされる(階層が深くなる)につれて、アニメーションがカクついたり、アプリが使用するメモリ量が急増したりするという現象である。

具体的には、アプリのルート(画面や機能の単位)が42階層以上深くネストされると、ナビゲーションアニメーションのフレームレート(1秒間に表示される画像の枚数)が、理想とされる60フレーム毎秒(fps)から38fpsにまで低下した。これは、アニメーションが滑らかに見える最低ラインを下回る数値であり、ユーザーには明らかな遅延として感じられる。同時に、Androidの中程度の性能のデバイスでテストしたところ、アプリのメモリ使用量が140メガバイト(MB)も増加した。このようなパフォーマンスの低下は、アプリの動作が重くなり、最悪の場合にはクラッシュを引き起こす可能性もあるため、開発者にとって重大な課題であった。このパフォーマンス低下の発生源と限界点を正確に把握するため、詳細なベンチマークテストが実施された。

テストは、最新のExpo SDK 52とReact Native 0.76の環境で実施された。テストデバイスにはPixel 5(Android 13)とiPhone 12(iOS 17)が使用され、React Native Performance MonitorとAndroid Studio Memory Profilerという専門的なツールを用いて、アプリのパフォーマンスが詳細に測定された。テストのシナリオとしては、アプリケーションのルート構造が最大で6レベルの深い階層を持つように設計され、自動化されたUIテストによって、10、25、50、75といった異なる深さのルートを繰り返し遷移させた。それぞれのシナリオにおいて、ナビゲーションにかかる時間、メモリ使用量の変化、アニメーション中のフレームドロップ(画像の表示が間に合わないことによるカクつき)、そしてUIスレッド(ユーザーインターフェースの描画やイベント処理を行う部分)のCPU使用率が詳細に記録された。

テストの結果、ルートの階層が深くなるにつれて、すべてのパフォーマンス指標が悪化することが明らかになった。例えば、10ルートの深さではナビゲーション時間が平均68ミリ秒、メモリ増加量が22MB、フレームドロップは0回だったのに対し、50ルートの深さではナビゲーション時間が187ミリ秒に増加、メモリは142MBも増え、フレームドロップは9回発生した。さらに75ルートでは、ナビゲーション時間は312ミリ秒に達し、メモリは229MB、フレームドロップは18回と、極めて深刻な状態になった。特に50ルートあたりで、パフォーマンスが劇的に悪化する「変曲点」があることが特定されたのである。

このパフォーマンス問題の根本的な原因は、Expo Routerが提供するuseSegments()というフックにあることが判明した。このフックは、現在のURLパスのセグメント(部分)を取得するために使用されるが、ナビゲーションイベントが発生するたびに、アプリケーションのUIレイアウトツリー全体を再レンダリング(画面の描き直し)していたのだ。深い階層のルートでは、この再レンダリング処理のオーバーヘッドが非常に大きくなる。加えて、スタイリングにTailwindCSSというCSSフレームワークを使用していた場合、ネストされた_layout.tsxコンポーネント(特定のルートグループに共通するレイアウトを定義するファイル)内で動的にクラス名を計算していたため、その再計算処理もパフォーマンスのボトルネックとなっていた。React Nativeが実際のUIツリーと仮想UIツリーの差分を計算し、必要な部分だけを更新する「和解(reconciliation)」処理が、深い階層で特に重くなっていたのである。

この問題に対処するため、まずCSSの最適化が実施された。これまで動的に生成していたTailwindCSSのクラス名を、React Nativeが提供するStyleSheet.createというAPIを使って静的なスタイルオブジェクトとして定義し、それらを条件に応じて適用するように変更した。例えば、以前は特定の状態に応じてCSSの背景色クラスを動的に切り替えていたが、これを「あらかじめ背景色の異なる静的なスタイルオブジェクトを定義しておき、状態に応じてそれらのスタイルオブジェクトを適用する」という形に修正したのだ。これにより、ランタイム(アプリ実行時)でのTailwindCSSのクラス計算が不要となり、再レンダリングの負荷が大幅に軽減された。この変更の結果、50ルートでのナビゲーション時間は187ミリ秒から94ミリ秒に半減し、フレームドロップも9回から3回に減少するなど、顕著な改善が見られた。

次に、タブバーの最適化も行われた。Expo Routerのタブレイアウトを使用すると、タブ間の切り替え時にレイアウト全体が不必要に再レンダリングされることがあった。これを回避するため、タブインジケーターのアニメーションをStyleSheet.createで定義された静的なスタイルオブジェクトとして管理し、レイアウトのスラッシング(不必要なレイアウト計算)を防いだ。ここでも静的なスタイルオブジェクトを使用することが有効であり、タブ切り替え時のUIスレッドのCPU使用率が18%削減される効果が得られた。静的なスタイルオブジェクトを使用する最大のメリットは、TailwindCSSのようなユーティリティファーストのCSSフレームワークが持つ実行時解析のオーバーヘッドを回避できる点にある。

さらに、アクセシビリティ(身体的な制約を持つ人も含め、すべての人がアプリを使いやすくするための配慮)に関する問題も解決された。深いナビゲーションスタックでモーダル(子画面が親画面の上に重なって表示される形式)ルートが開かれた際に、スクリーンリーダー(視覚障がい者が画面の内容を音声で読み上げるためのソフトウェア)のフォーカスがモーダル内に適切に閉じ込められず、背後のタブナビゲーターに漏れてしまうという問題があった。これは、Expo Routerの<Slot />コンポーネントが、accessibilityViewIsModalというアクセシビリティプロパティを子スクリーンに適切に伝播しないことが原因であった。この問題は、<Slot />をaccessible={true}とaccessibilityViewIsModal={true}というプロパティを持つViewコンポーネントでラップすることで解決した。これにより、VoiceOverやTalkBackといったスクリーンリーダーが、フォーカスをモーダル内に適切に閉じ込め、ユーザーが迷うことなく操作できるように改善された。

これらのパフォーマンス最適化とアクセシビリティの改善を経て、Expo Routerの利用に関するいくつかの重要な判断基準が示された。Expo Routerのファイルベースルーティングは、本番環境で40ルートファイル以下のアプリ、タイプセーフなルーティング(コードの記述ミスによるエラーを防ぎやすい)を重視する開発チーム、そしてURLを通じてナビゲーションの状態が永続化する(アプリを再起動しても前回の状態に戻る)プロジェクトには、非常に適している。このような規模のプロジェクトであれば、Expo Routerが提供する優れた開発体験のメリットが、わずかなパフォーマンスコストを上回ると考えられる。

しかし、次のような場合には、従来のReact Navigationへの切り替えを検討すべきである。APIからの応答に基づいて動的にルートを生成する(例えば、コンテンツ管理システム(CMS)によってナビゲーションが制御される)ようなアプリや、'modal'以外の特別なカスタム画面遷移アニメーションが必要なアプリなどだ。さらに、60レベルを超えるような極端に深いネストのルートスタックを持つアプリの場合は、ルーティングシステムの問題以前に、アプリの情報アーキテクチャそのものを見直す必要があるかもしれない。特に50ルートという変曲点は、JavaScriptバンドルのサイズと、ネイティブコードとの連携(ネイティブブリッジ)におけるデータ変換(シリアライゼーション)のオーバーヘッドが交差するポイントであり、このしきい値を超えるとExpo Routerのメリットが性能のコストを上回らなくなるという重要な示唆が得られた。

この事例は、最新のフレームワークやライブラリを採用する際にも、その特性を深く理解し、パフォーマンスとアクセシビリティの両面から適切な設計と最適化を行うことの重要性を示している。システムエンジニアを目指す初心者も、単に新しい技術を取り入れるだけでなく、アプリの要件や規模に応じて最適なツールを選択し、発生しうる問題を深く分析し解決する能力を養うことが求められる。

関連コンテンツ

関連IT用語

関連ITニュース