React NativeのTurbo Module—概要、JSIの仕組み、アーキテクチャ

著者: IT Sectr 公開日: 2026-06-04 読了時間: 10 分

Turbo Moduleは、JavaScript Interface(JSI)上に構築されたReact Nativeネイティブモジュールの進化形です。Bridgeとは異なり、Turbo Moduleは同期的に動作し、JSONシリアライゼーションが不要なため、大幅なパフォーマンス向上を実現します。Meta Engineering Blog、2024によると、Turbo Moduleは新しいアーキテクチャの主要コンポーネントであり、React Native 0.76+で利用可能です。

重要ポイント

  • Turbo Module — BridgeなしでJSIベースのReact Nativeネイティブモジュール。
  • JSI — JavaScript Interface。JSからC++メソッドを直接呼び出せます。
  • 同期性 — Turbo Moduleはシリアライゼーションなしで同期的な呼び出しをサポート。
  • レイジーローディング — モジュールはJSから初回アクセス時のみロード。
  • Codegen — 型とインターフェースが仕様から自動生成されます。

Turbo Moduleとは

Turbo Moduleは、JavaScriptとネイティブコード間の通信において従来のBridgeを置き換える、新しいReact Nativeアーキテクチャのコンポーネントです。すべてのメッセージがJSONにシリアライズされて非同期で送信されるBridgeとは異なり、Turbo ModuleはJSI(JavaScriptがC++で書かれた関数を直接呼び出せるようにするレイヤー)を使用します。

Turbo Moduleアーキテクチャは、MetaチームによってReact Conf 2021で、「The New Architecture」というコードネームの下でのより大規模なReact Native再構築の一部として発表されました。 Turbo Moduleに加えて、新しいアーキテクチャにはFabric(新しいレンダラー)、Codegen(コードジェネレーター)、JSI(インタラクションインターフェース)が含まれます。これらのコンポーネントは連携して、2015年からReact Nativeに蓄積されていたパフォーマンス問題を解決します。

Turbo Moduleは、従来のネイティブモジュールの3つの主要な問題を解決します:非同期性(すべての呼び出しがキューを通過する)、シリアライゼーション(各呼び出しにJSON変換が必要)、およびローディング(すべてのモジュールがアプリ起動時に初期化される)。Turbo Moduleを使用すると、ネイティブメソッドは同期的に呼び出され、データはコピーなしで転送され、モジュールはオンデマンドでロードされます。

JSIの仕組み

JSI(JavaScript Interface)は、JavaScriptエンジン(HermesまたはJSC)とネイティブコードの間にレイヤーを作成するC++ APIです。JSIはホストオブジェクトを提供します。これは通常のJavaScriptオブジェクトやメソッドのように見えるC++オブジェクトです。JavaScriptがそのようなオブジェクトのメソッドを呼び出すと、JSIはシリアライゼーションやスレッド切り替えなしで、対応するC++コードを直接実行します。

JSIとBridgeの主な違いは、データコピーがないことです。Bridgeでは、各値がJSON文字列にシリアライズされ、キューを通過してデシリアライズされます。JSIはメモリ内のデータへのポインタを渡すため、パフォーマンスを損なうことなく大規模なデータを扱うことができます。Metaのテストによると、JSI呼び出しはBridge経由の同等の呼び出しよりも5〜10倍高速に実行されます。

HostObjectと同期呼び出し

JSIはHostObjectインターフェースを定義します。これはReact NativeがJS環境に通常のオブジェクトとして登録するC++クラスです。JSコードがプロパティにアクセスしたり、HostObjectのメソッドを呼び出したりすると、JSIが呼び出しをインターセプトしてC++コードを実行します。これにより、Bridgeのキューを待たずに同期的に操作を実行できます。

cpp
// JSI HostObjectの例 — 同期ネイティブ呼び出し
class ImageCompressorHostObject : public jsi::HostObject {

    jsi::Value get(
        jsi::Runtime& rt,
        const jsi::PropNameID& propName
    ) override {
        auto name = propName.utf8(rt);
        if (name == "compressImage") {
            return jsi::Function::createFromHostFunction(
                rt,
                jsi::PropNameID::forUtf8(rt, name),
                2,
                [](jsi::Runtime& rt,
                   const jsi::Value& thisValue,
                   const jsi::Value* args,
                   size_t count) -> jsi::Value {
                    return jsi::Value(rt, compressNative(
                        args[0].asString(rt).utf8(rt),
                        args[1].asNumber()
                    ));
                }
            );
        }
        return jsi::Value::undefined();
    }
};

上記のコードは、JSI HostObjectがJavaScriptからのcompressImage呼び出しをどのように処理するかを示しています。この関数は2つの引数(パス文字列と品質数値)を受け取り、ネイティブ関数compressNativeを呼び出して結果を返します。すべて同期的で、BridgeもJSONも不要です。これが従来のアーキテクチャに対するJSIの主な利点です。

JSIはReact Nativeメインランタイムの一部であり、特定のJavaScriptエンジンに依存しません。HermesとJavaScriptCore(JSC)の両方で動作し、ネイティブ環境との相互作用のための統一インターフェースを提供します。

Turbo Module vs Bridge:比較

Turbo ModuleとBridgeの比較は、React Nativeアーキテクチャの進化を示しています。Bridgeは2015年のReact Nativeの迅速な立ち上げのために設計されましたが、アプリケーションの複雑さが増すにつれて、その制限が重大になりました。Turbo Moduleはこれらの問題をアーキテクチャレベルで解決します。

特性BridgeTurbo Module
呼び出し速度5~15msのオーバーヘッド0.1~0.5msのオーバーヘッド
同期性非同期のみ同期および非同期
シリアライゼーション呼び出しごとにJSONコピー不要のJSIオブジェクト
型安全性なしCodegen + TypeScript
初期化起動時に全モジュールレイジー、オンデマンド

実際には、ネイティブメソッドを頻繁に呼び出す場合(メディア処理やGPUを使用する場合など)に差が最も顕著です。まれな呼び出し(セッションごとに1回)の場合、パフォーマンスの差はごくわずかです。Turbo Moduleはまた、大きなバイナリデータ(画像、動画、バイナリプロトコル)の処理を簡素化します。Bridgeではファイルシステムを使った回避策が必要でした。

Turbo Module作成例

Turbo Moduleの作成は、TypeScriptで仕様を定義することから始まります。Codegenはこの仕様に基づいて、C++インターフェースとObjective-C/Javaスタブを自動生成します。これにより開発アプローチが完全に変わります。開発者はAPIを一度記述するだけで、Codegenが残りすべてを作成します。

typescript
// ImageCompressor.ts — Turbo Module仕様
import type { TurboModule } from 'react-native';
import type { Double } from 'react-native/Libraries/Types/CodegenTypes';

export interface Spec extends TurboModule {
  compressImage(
    imagePath: string,
    quality: Double
  ): Promise<string>;
}

Codegenによるコード生成

CodegenはTypeScriptの仕様を分析し、C++のHostObject、Objective-Cのプロトコル、Javaのインターフェースを生成します。開発者はネイティブロジックを実装するだけです。このアプローチにより、JavaScript側とネイティブ側の型が常に一致することが保証され、手動マッピングのエラーが排除されます。

objective-c
// iOS用TurboModule実装(生成されたスタブ)
@interface ImageCompressorModule ()
    RCT_EXPORT_MODULE(ImageCompressor)
@end

@implementation ImageCompressorModule

RCT_EXPORT_METHOD(compressImage:(NSString *)imagePath
                  quality:(NSNumber *)quality
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    NSData *compressed = [ImageProcessor compressAtPath:imagePath
                                                    quality:quality.doubleValue];
    resolve([NSString stringWithUTF8String:compressed.UTF8String]);
}

@end

重要な利点はレイジーローディングです。Turbo Moduleはアプリ起動時に初期化されるのではなく、JavaScriptから初めてアクセスされたときにのみ作成されます。これにより、すべてのネイティブモジュールが即座にロードされる従来のアプローチと比較して、アプリの起動時間が30〜50%短縮されます。

BridgeからTurbo Moduleへの移行

BridgeからTurbo Moduleへの移行は、アプリケーションを完全に書き換える必要はありません。React Native 0.73+は両方のアーキテクチャを並行してサポートしています。Bridgeモジュールは引き続き動作し、新しいモジュールはTurbo Moduleとして作成できます。これにより、モジュールごとに段階的に移行できます。

React Native 0.76+プロジェクトで新しいアーキテクチャを有効にするには、react-native.config.jsファイルでnewArchEnabledフラグをtrueに設定します。その後、既存のすべてのネイティブモジュールはBridge経由で引き続き動作し、新しいモジュールはTurbo Moduleとして作成できます。Codegenは両方のオプションを自動的に処理します。

js
// react-native.config.js — 新しいアーキテクチャを有効化
module.exports = {
  project: {
    ios: {},
    android: {},
  },
  assets: [],
  newArchEnabled: true,
};

JavaScriptから最も頻繁に呼び出されるモジュールから移行を開始することをお勧めします。それらが最大のパフォーマンス向上を得られます。まれにしか呼び出されないモジュール(セッションごとに1回)は、パフォーマンスを大幅に損なうことなくBridgeに残すことができます。

  • Codegen — ネイティブインターフェースの自動生成にはTypeScript仕様を使用してください。
  • E2Eテスト — 特にReact Nativeアップデート後は、両方のアーキテクチャでモジュールの動作を確認してください。
  • バックアップ計画 — Turbo Moduleで問題が発生した場合、設定フラグで一時的にBridgeに戻すことができます。

よくある質問

React Native 0.72でTurbo Moduleを使用できますか?

いいえ、Turbo Moduleは新しいアーキテクチャを有効にしたReact Native 0.73+が必要です。バージョン0.76以降、新しいアーキテクチャは安定し、本番プロジェクトに推奨されています。

Turbo ModuleはiOSとAndroidの両方で動作しますか?

はい、Turbo Moduleは両方のプラットフォームをサポートしています。JSIはクロスプラットフォームのC++レイヤーであり、CodegenはiOSとAndroid向けにそれぞれObjective-CとJavaのスタブを生成します。

Turbo ModuleでHermesを使用する必要はありますか?

いいえ、Turbo ModuleはJSIを介して任意のJSエンジンで動作します。ただし、HermesはJSIと新しいReact Nativeアーキテクチャで動作するように最適化されているため推奨されます。

Turbo Moduleをデバッグするには?

Turbo Moduleのデバッグは、通常のネイティブコードと同様にXcodeまたはAndroid Studioを使用して行います。さらに、JSI呼び出しとモジュールのパフォーマンスを追跡するためにFlipperが利用可能です。

Turbo Moduleはアプリのサイズを増加させますか?

Turbo Moduleはアプリのサイズに実質的に影響しません。JSIのC++コードは既にReact Nativeの一部であり、生成されるコードは最小限で、ロジックの重複がないインターフェースのみです。

まとめ

  • Turbo Module — JSONシリアライゼーションなしでJSIを介して動作する新しいタイプのReact Nativeネイティブモジュール。
  • JSI — JavaScriptからネイティブメソッドへの直接の同期呼び出しを提供するC++レイヤー。
  • 速度 — Turbo Moduleの呼び出しはBridge経由の呼び出しよりも5〜10倍高速に実行されます。
  • レイジーローディング — モジュールは最初のアクセス時にのみ初期化され、アプリの起動を高速化します。
  • Codegen — TypeScript仕様からネイティブインターフェースを自動生成。
  • 互換性 — React Native 0.73+はBridgeとTurbo Moduleの並行動作をサポート。
  • 移行 — 段階的な移行:React Nativeを0.76+に更新、newArchEnabledを有効化、新しいモジュールをTurbo Moduleとして作成。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください