Upgrade to Pro — share decks privately, control downloads, hide ads and more …

解剖"React Native"

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for hacusk hacusk
April 08, 2026

解剖"React Native"

Avatar for hacusk

hacusk

April 08, 2026

More Decks by hacusk

Other Decks in Technology

Transcript

  1. $ whoami Name: はくすけ(@hacusk) / HakataYusuke Job: 株式会社モニクル SWE Language:TypeScript,

    Go, PHP… FavoriteTech: MultiPlatformなもの, OSS, ネ ットワーク Love: 声優, 旅行, ライブ, アイドル, 車, モータ ースポーツ, ガジェット, 飛行機, 麻雀 Community: 函館本線沿線勉強会, フロントエ ンドカンファレンス北海道実行委員会, OSC北 海道実行委員会, 一般社団法人LOCAL Website: https://hacusk.net/ 2
  2. What is "React Native" Learn once, write anywhere. Meta社が主に開発しているOSSのマルチプラットフォームフレームワーク Callstack,Expo,Infinite

    Red,Microsoft,Software Mansion社も大きく関わっている iOS,Android,tvOS,Android TV,Vega OS,macOS,Windows(UWP),Meta Horizon OS,Webなどで動くものを作れる ※一部はReactNativeからforkされているプロジェクト(意外なことにfor macOSはMicrosoft が面倒を見ている) https://reactnative.dev/docs/out-of-tree-platforms Reactとそのネイティブ側のプラットフォームの機能を組み合わせてアプリケーションを作る 既存のネイティブコードをラップしたReactのコンポーネントを用いて,JavaScriptを介してネ イティブのAPIを実行する 3
  3. 今日話すこと ReactNativeがどのようにして実行されているのかを紐解く 各プラットフォーム上でJavaScriptを動かすための仕組み — Metro Bundler / Hermes JavaScriptとプラットフォームAPIをつなぐための仕組み —

    JSI 接続を保証する仕組み — Codegen / TurboModules Reactを動かす仕組み — Fabric / Yoga 前提: iOS,Androidをターゲットとした前提で話します react-native 0.76以降で有効化されているNew Architectureの話です 4
  4. ReactNativeのアーキテクチャ全体像 JS 側 React / App code JSX コンポーネント Hermes

    JSエンジン Codegen ビルド時 · 型定義⾃動⽣成 JSI JavaScript Interface C++ · 同期 · シリアライズなし Native 側 TurboModules 初回呼び出し時に C++ インスタンス⽣成 Fabric React レンダラー · immutable な C++ ツリー Yoga Flexbox 計算 (C++ 実装) iOS APIs UIKit · SwiftUI Android APIs View · Jetpack 5
  5. Metro Bundler コードのバンドル,最適化,バイトコードの生成 主な機能 JSX → JS 変換(Babel) モジュール解決 minify,Tree

    shaking RN固有の役割 HMR(Hot Module Replacement) Platform-specific extensions Hermes向けバイトコード出力 $ pnpm expo export → JavaScript bytecode https://metrobundler.dev/ https://reactnative.dev/docs/metro 6
  6. Hermes リリースビルド時(AOT) 1. Metroがコードをバンドル 2. HermesコンパイラがJSをバイトコード (.hbc)に変換 3. APK /

    IPAに同梱して配布 実行側 バイトコードをそのまま実行(AOTコンパイル 済み) JIT不要 → 起動時のコンパイルコストがゼロ シングルスレッド・イベントループ イベントループの実行順 // HermesInternal でエンジン確認 const isHermes = !!global.HermesInternal; // true console.log('1. 同期処理'); // Call Stack Promise.resolve().then(() => { console.log('2. Microtask'); // Microtask Queue }); setTimeout(() => { console.log('3. Task'); // Task Queue }, 0); // 出力順: 1 → 2 → 3 デバッグモードではMetroからJSを配布し,JITで実行 https://reactnative.dev/docs/hermes https://reactnative.dev/architecture/bundled-hermes 7
  7. JSI — JavaScript Interface シリアライズなし JSオブジェクトをC++ポイン タで直接参照 同期呼び出し可能 await なしでNativeから即座

    に値を受け取れる Codegen連携 TSの型定義から C++,Java,ObjCのI/Fを自動生 成 // C++側: HostObjectとして公開 class NativeCalculator : public HostObject { public: Value get(Runtime& rt, const PropNameID& name) override { // JSオブジェクトをコピーなしで直接参照 return Function::createFromHostFunction(rt, ...); } }; https://reactnative.dev/architecture/landing-page 8
  8. Codegen TSの型定義を唯一の情報源とする export interface Spec extends TurboModule { multiply(a: number,

    b: number): number; fetchData(url: string): Promise<string>; } export default TurboModuleRegistry.getEnforcing<Spec>('Calculator'); ↓ Codegenが自動生成 class NativeCalculatorCxxSpec { public: virtual double multiply(jsi::Runtime& rt, double a, double b) = 0; virtual jsi::Value fetchData(jsi::Runtime& rt, jsi::String url) = 0; }; 型ズレによるランタイムクラッシュが原理的に起きにくくなる https://reactnative.dev/docs/the-new-architecture/what-is-codegen 9
  9. TurboModules — Platform.constantsで読む実装の流れ① // ① JS Spec — 型の定義(Codegenの入力) //

    NativePlatformConstantsIOS.js export interface Spec extends TurboModule { getConstants(): { osVersion: string; reactNativeVersion: {...}; ... }; } export default TurboModuleRegistry.getEnforcing<Spec>('PlatformConstants'); // ② iOS実装 — RCTPlatform.mm RCT_EXPORT_MODULE(PlatformConstants) // モジュール名を登録 - (ModuleConstants)getConstants { return typedConstants<JS::NativePlatformConstantsIOS::Constants>({ .osVersion = [UIDevice currentDevice].systemVersion, ... }); } 11
  10. TurboModules — Platform.constantsで読む実装の流れ② // ③ Android実装 — AndroidInfoModule.kt @ReactModule(name =

    NativePlatformConstantsAndroidSpec.NAME) class AndroidInfoModule : NativePlatformConstantsAndroidSpec(reactContext) { override fun getTypedExportedConstants() = mapOf( "Release" to Build.VERSION.RELEASE, "Model" to Build.MODEL, ... ) } https://github.com/reactwg/react-native-new-architecture/blob/main/docs/turbo-modules.md 12
  11. Fabricのレンダリングパイプライン Phase 1 — Render(JSスレッド) ReactがElement Treeを生成 → JSI経由でC++のShadow Treeにミラーリング

    Phase 2 — Commit(C++スレッド) BeforeMutation → Mutation(差分適用)→ Layout(Yoga・Flexbox計算) JSスレッドをブロックしない Phase 3 — Mount(メインスレッド) 確定した座標でiOS UIView / Android Viewを同期更新 startTransition → Renderフェーズを低優先度に Suspense → Shadow Tree構築を保留しfallbackをMount https://reactnative.dev/architecture/render-pipeline 13
  12. YogaとShadow Tree Shadow Tree C++でReact Element Treeをミラーリング immutable — 並列に複数バージョン保持可能

    これがConcurrent Featuresの土台 Yoga Flexboxレイアウトエンジン(C++実装) WebのCSSとほぼ同じAPIで計算 CommitフェーズのLayoutサブフェーズで動く // Shadow TreeはJSスレッドと同期しているので同期的に正確な座標が返る const boxRef = useRef<View>(null); boxRef.current?.measureInWindow((x, y, width, height) => { console.log(`x:${x} y:${y} w:${width} h:${height}`); }); https://reactnative.dev/architecture/glossary#react-shadow-tree-and-react-shadow-node 14
  13. まとめ: React Nativeにおける"React" React自体はWeb版とまったく同じでコンポーネント・状態管理などがそのまま動くが, レンダラーだけ違う Webの場合 reconciler(Fiber)が差分を計算 react-dom がDOMを更新 React

    Nativeの場合 reconciler(Fiber)が差分を計算(同じ) Fabric がNative UIツリーを更新 React NativeでDOMイベント等は使えないなどの制約はある https://reactnative.dev/architecture/fabric-renderer 15