React NativeとExpo RouterのRSC導入に向けたアップデートが来そう

Expo Routerとは

Expo Routerは、React NativeおよびWebアプリケーション用に設計されたファイルベースのルーティングライブラリ。

docs.expo.dev

RSCを活用してサーバー側でコンポーネントレンダリングとストリーミングを行う新しいSDUIの構想

"Fetch Once, Render Everywhere: React Server Components in Expo Router"はReact Summit 2024におけるExpo作者のひとりEvan Baconによる講演。

gitnation.com

ここでExpoを使った新しいSDUIの構想が発表され、Reactネイティブアプリにおけるサーバー側のコンポーネントレンダリングとストリーミングが提案されてXのタイムラインが盛り上がっていた。
今クライアントがWeb APIで取得して画面に適用しているデータを、RSC(React Server Components)を活用して最初からコンポーネントに埋め込み、サーバー側で合体させたViewを再生することが可能になる。
理想的にはクライアント側の負荷を軽減し、アプリのロジックをシンプルにする。 別の問題も起こりそうだが……. モバイル向けのSDUIの話題はよくAirbnbの魔改造GraphQL UIシステムの例でとりあげられる。

laiso.hatenablog.com

モバイルアプリ開発ではRSCを直接使用できない

この技術は、今後React Nativeでのモバイルアプリ開発におけるBFF(Backend for Frontend)の開発コストを限定的(=React NativeアプリかつフルスタックTSを採用)に解決する可能性があるので注目した。
現在、モバイルアプリ開発ではRESTful、GraphQL、gRPCなどを基盤としたBFFの使用が主流で、React Server Components(RSC)をモバイルアプリから直接使用できない。 というか前提としてフロントエンドとバックエンドは分離している。
統合したいかは別として、この課題は先の"Rails vs Node.js"の議論でも言及されており、モバイルアプリにおいて、RSCでデータフェッチ層を置き換えられないことが問題として挙げられている。

sizu.me

React Server Components in Expo Routerのロードマップ

Expo Routerは2024年末までにこのアップデートの早期ベータ版をリリースすることを目指している。
しかし、実現可能性も含めて、まだ不確定な要素が多く残っている。 プロジェクトはまだ開発の初期段階にあり、我々はEvan BaconのXをウォッチするしかない状況だ。
最新の投稿によるとまもなくベータ版が公開されるとのこと。

講演では言及されていないが、RSCを配信する専用のNode.jsサーバーをデプロイする必要もありそうだ。 すでにExpo Routerに実験的機能としてサーバーサイドのAPI Routesが追加されている。expressなどに乗せて任意のプラットフォームにデプロイできるようになっている。このサーバーをRSC対応にも使うのではないか。

docs.expo.dev

将来的にExpoのSaaSである Expo Application Services (EAS)にマネージドオプションが追加されるのかもしれない (既存システムに後付けするなら単にBFFの通信方式が変わるだけになるな……など感じるところだが) 。

AppStoreポリシーへの準拠

この機能を開発する際は、AppStoreポリシーに違反しないようにする必要がある。
例えば、サーバーから直接ネイティブ機能を呼び出す仕組みにしないこと。
これに違反するとExpoユーザーのアプリは、審査でリジェクトされる。 サーバー経由でiOSのネイティブ機能を利用するSDKが過去にリジェクトされたケースがある。
特にAppleはサーバーを介したネイティブ機能の不正使用に厳しいため、この点を避ける設計が必要だ。
ExpoはすでにOTAによるネイティブアプリのオンライン更新を構築しているので、なれた分野なのかもしれない。

docs.expo.dev

React Native側の課題

もう1つ別の記事を紹介しよう。 Bringing React Server Components to React NativeはRN側のコントリビューターSzymon Rybczakのポストで、これはEvan Baconの発表より前に公開された。

szymonrybczak.dev

React Nativeの内部アーキテクチャに関する知識に基づいており解像度が高い。
ExpoとReact Nativeは、メタフレームワークと基盤フレームワークの関係になる。
ExpoがWeb技術で抽象化を提供し、React Nativeがネイティブな部分を処理するという役割分担がなされている。
この記事は単独の技術解説であり、Expoとの直接的な連携は行っていない。

React NativeにおいてはReact 18のstartTransitionに対応したレンダリングエンジンFabricへの移行が必須(RSCの解釈がこれに依存しているため)。
Fabricは既にデフォルトで有効になっており、新しいアプリではとりあえず問題はない。
次なるステップはRSCに必要なJavaScript APIをHermesエンジンにポリフィルを通じて補完することになる。 いずれHermesのアップデートによってこのポリフィルは不要になる可能性もある。
RNのバンドルやナビゲーションも、RSCとの互換性を持たせる方向で調整が必要。

GitHubリポジトリの実装を調べた

Evan Baconが「だいたいできました」とポストしているということはこのあたりはもう解消されたのだろうかと思い、 GitHubリポジトリの実装を調べた。
現時点で既にconfig.reactServerComponentsという設定フラグが存在しRSC関連のファイルがあるのでベータ開始の見込みは概ねできていそうだ。

サンプルサプリというかE2EテストがあるのでExpoコアのデバッグができる人は試すことができる。私がビルドしてみたところwebビルドは工夫なくそのまま動いたが、ios向けはネイティブモジュールのビルドが成功するよう調整する必要があった。

expo/apps/router-e2e at c06878fa9a1edb1fcf0f6a1b468e25a61095e249 · expo/expo · GitHub

git clone https://github.com/expo/expo.git --depth 1
yarn
cd apps/router-e2e/
yarn run start:rsc
# iOSビルドを直接いじる
EXPO_UNSTABLE_CORE_AUTOLINKING=1 pod install --repo-update
xed ios/

Expo Web向けのRSCリンダリングはflightプロトコルを処理するSSRだと予想できるので、気になるのはネイティブに描画されるまでのパスで、今後はそれを読み解いていきたい。