1. アーキテクチャ設計
全体的に、Native、JavaScript、Bridgeの3つの大きな部分に分かれています:
[caption id="attachment_2013" align="alignnone" width="625"]
React Native layers[/caption]
NativeはUIの更新とインタラクションを管理し、JavaScriptはNativeの機能を呼び出してビジネスロジックを実現し、Bridgeはその両者の間でメッセージを伝達します。すなわち:

最上層ではReactのようなサポートを提供し、JavaScriptCoreが提供するJavaScriptランタイム環境で動作します。Bridge層はJavaScriptとNativeの世界を接続します。具体的には、Shadow Treeを使用してUI効果とインタラクション機能を定義し、Native ModulesがNative機能(Bluetoothなど)を提供します。両者はJSONメッセージを介して互いに通信します。
Bridge層はReact Native技術の核心であり、設計上3つの特徴を持っています:
-
非同期(asynchronous):同期通信に依存しない。
-
シリアライズ可能(serializable):すべてのUI操作がJSONにシリアライズされ、元に戻せることを保証する。
-
バッチ処理(batched):Nativeの呼び出しをキューに入れ、一括で処理する。
UI操作を一連の命令として記述し、JSON形式のメッセージにシリアライズします:
Just as React DOM turns React state updates into imperative, mutative calls to DOM APIs like document.createElement(attrs) and .appendChild(), React Native was designed to return a single JSON message that lists mutations to perform, like [["createView", attrs], ["manageChildren", ...]].
非常に柔軟であり、この命令ベースのメカニズムにより、JSコードを別のJSエンジン上で実行することすら可能です。これがChrome debuggingです:
Chrome debugging, which runs all the JavaScript code asynchronously over a WebSocket connection.
2. スレッドモデル
React Nativeには主に以下の3つのスレッドがあります:
-
UI Thread:Android/iOS(またはその他のプラットフォーム)アプリケーションのメインスレッド。
-
Shadow Thread:レイアウト計算とUIの構築を行うスレッド。
-
JS Thread:ReactなどのJavaScriptコードを実行するスレッド。
これに加えて、Native Modulesスレッドというカテゴリがあり、異なるNative Moduleは異なるスレッドで実行される可能性があります(詳細はThreadingを参照):
[caption id="attachment_2014" align="alignnone" width="625"]
React Native threading model[/caption]
スレッド間の相互作用の関係は以下の通りです:

P.S. 図中のqueueはGCD dispatch queueを指しており、(厳密には不正確ですが)スレッドとして簡単に理解できます。
3. 起動プロセス
時系列で見ると、App起動時にReact Nativeのランタイム環境(すなわちBridge)が初期化され、Bridgeの準備が整った後にJSの実行が始まり、最後にNativeのレンダリングが開始されます:

完全な起動プロセスは以下のようになります:
[caption id="attachment_2015" align="alignnone" width="625"]
React Native App start up flow[/caption]
このうち、上半分がBridgeの初期化プロセスです:
以下の4つの部分に分かれます(これらの操作はすべて起動時に行われます):
-
JavaScriptコードのロード:開発モードではネットワークからダウンロードし、本番環境ではデバイスのストレージから読み込みます。
-
Native Modulesの初期化:Native Moduleの登録情報に基づき、すべてのNative Moduleをロードし、インスタンス化します。
-
Native Module情報の注入:Native Moduleの登録情報を取得し、グローバル変数としてJS Contextに注入します。
-
JavaScriptエンジンの初期化:すなわちJavaScriptCoreの初期化です。
Bridgeが確立された後、JavaScriptコードの実行が開始され、ユーザーインターフェースをレンダリングし、ビジネスロジックを実現します。
4. レンダリングメカニズム
[caption id="attachment_2016" align="alignnone" width="625"]
React Native threads[/caption]
JSスレッドはビュー情報(構造、スタイル、プロパティなど)をShadowスレッドに渡し、レイアウト計算用のShadow Treeを作成します。Shadowスレッドがレイアウトを計算した後、完全なビュー情報(幅、高さ、位置などを含む)をメインスレッドに渡し、メインスレッドはそれに基づいてNative Viewを作成します。
ユーザー入力に対しては、まずメインスレッドが関連情報をイベントメッセージとしてパッケージ化し、Shadowスレッドに渡します。次に、Shadow Treeが確立したマッピング関係に基づいて、対応する要素の指定されたイベントを生成します。最後に、そのイベントをJSスレッドに渡し、対応するJSのコールバック関数を実行します。すなわち:
[caption id="attachment_2017" align="alignnone" width="625"]
React Native UI interaction[/caption]
これで、すべてが明確になりました。
コメントはまだありません