JSI:その概要、動作原理、アーキテクチャ

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

JSI(JavaScript Interface)は、React Nativeのソフトウェアレイヤーで、JavaScriptからC++のオブジェクトや関数への直接的な同期アクセスを提供し、非同期JSONブリッジであるBridgeを置き換えます。前任者とは異なり、JSIはメッセージのシリアライズなしでネイティブメソッドを呼び出し、C++オブジェクトへの参照を直接JS環境に渡すことができます。React Native Team(2025)によると、JSIはデータ集約型のシナリオにおいて、JSとネイティブコードの相互作用を最大10倍高速化します。

重要なポイント

  • JSI — JavaScript Interface。JSからネイティブC++コードへの同期アクセスを提供
  • 直接アクセス JSONシリアライズと非同期メッセージキューの必要性を排除
  • パフォーマンス JSとネイティブコードの相互作用が5~10倍向上
  • アーキテクチャ JSIは新しいReact NativeアーキテクチャにおけるFabricとTurboModulesの基盤
  • C++統合 ネイティブラッパーなしで任意のC++ライブラリを接続可能

JSIとは?

JSI(JavaScript Interface)は、JavaScriptエンジン(Hermes、JavaScriptCore、V8)にC++オブジェクト、関数、メモリへの直接アクセスを提供するC++レイヤーです。呼び出しをJSONにシリアライズして非同期キューを通して渡していたBridgeとは異なり、JSIはJSコードが同期的にC++メソッドを呼び出し、即座に結果を取得することを可能にします。

JSIはReact Native 0.64で新しいアーキテクチャ(New Architecture)の一部として導入されました。主な目的は、Bridgeがもたらすボトルネックを排除することでした。JSとネイティブコードの間の各相互作用は、シリアライズ、デシリアライズ、メッセージキューの通過に時間を費やしていました。JSIは、jsi::Value、jsi::Object、jsi::Functionインターフェースを実装するラッパーを通じて、JSエンジンにC++オブジェクトへの直接アクセスを提供することでこの問題を解決します。

JSIはBridgeの1対1の置き換えではありません — 統合に対する根本的に異なるアプローチです。Bridgeはメールボックスのように機能していました。JSがメッセージを送信し、キューを通過し、ネイティブ側が処理して返信を送信していました。JSIはポインタのように機能します。JSはC++オブジェクトへの参照を取得し、通常のJS関数と同様にそのメソッドを同期的に呼び出すことができます。これは2つの環境間の相互作用アーキテクチャにおける根本的な違いです。

作成の歴史

JSIの必要性は、React Native 2015で確立されたオリジナルのBridgeの制限から生じました。フレームワークの人気が高まり、アプリケーションが複雑になるにつれて、パフォーマンスの問題が明らかになりました。各ネイティブモジュール呼び出しは、シリアライズに少なくとも3~5ミリ秒を必要としていました。センサー値の読み取りや画面サイズの取得などの単純な操作では許容範囲でしたが、アニメーション、グラフィックス処理、ストリーミングデータ処理では重大な問題でした。React Nativeチームは2019年に新しいアーキテクチャの作業を開始し、JSIがその基盤となりました。

JavaScriptエンジンのサポート

JSIはJavaScriptエンジン上の抽象化レイヤーとして設計されています。Hermes、JavaScriptCore(iOS)、V8(Android)の各エンジンに対して実装された統一C++ APIを提供します。つまり、開発者はエンジン間の違いを気にする必要がありません — FabricとTurboModulesは、内部で使用されているJSエンジンに関係なく同じように動作します。

JSIの仕組み

JSIの中核にはホストオブジェクト(Host Objects)の概念があります — C++オブジェクトがネイティブJSオブジェクトとしてJS環境にエクスポートされます。JSコードがそのようなオブジェクトのプロパティやメソッドにアクセスすると、JSIが呼び出しをインターセプトし、対応するC++メソッドに委任します。これは同期的に、同じスレッドで、コンテキストスイッチなしで、JSON文字列のメモリ割り当てなしで行われます。

各ホストオブジェクトは、get、set、getPropertyNamesメソッドを持つjsi::HostObjectインターフェースを実装します。JSエンジンは、オブジェクトのプロパティにアクセスされるたびにこれらのメソッドを呼び出します。例えば、JSでNativeModule.someMethod()を呼び出すと、JSIはこの呼び出しを対応するホストオブジェクトメソッドへのC++呼び出しに変換します。戻り値はjsi::ValueとしてJSに返されます — 数値、文字列、ブール値、オブジェクト、またはundefinedを表すことができる汎用型です。

JSIの重要な特徴はメッセージキューがないことです。Bridgeは非同期キューを使用していました。JSがリクエストを送信し、他のタスクに切り替え、ネイティブ側がリクエストを処理し、結果がコールバックを介して返されていました。JSIは同期的に動作します。JSがJSIを介してネイティブモジュールメソッドを呼び出すと、結果が受信されるまでJSコードの実行が一時停止します。これによりロジックが簡素化され(コールバックを待つ必要がない)、競合状態が排除されますが、注意が必要です — 長時間の同期呼び出しはJSスレッドをブロックします。

JSI値のライフサイクル

JSIを介して作成された値はJSエンジンのランタイムに存在し、ガベージコレクタによって管理されます。C++コードがjsi::Stringやjsi::Objectを作成してJSに返すと、環境が自動的にメモリを管理します。C++コードが呼び出し間でJS値への参照を保持したい場合は、jsi::Value::getWeak()またはランタイムルートオブジェクトに保存された参照を持つグローバルなjsi::Object::setPropertyが使用されます。これにより、ガベージコレクタによる早期削除が防止されます。

スレッドセーフティ

JSIはデフォルトではスレッドセーフではありません。すべてのJSIメソッド呼び出しは、JSが実行されるスレッド(通常はReact NativeのJSスレッド)から行われる必要があります。ネイティブモジュールが別のスレッドでバックグラウンド処理を開始する場合、結果はTurboModulesのrunOnJSを使用してJSスレッドを介して返される必要があります。この制限は、同期性とシリアライズがないことの代償です。

JSI vs Bridge:比較

JSIとBridgeの違いは根本的であり、JSとネイティブコードの相互作用のすべての側面に影響します。Bridgeは非同期で、データをJSONにシリアライズし、メッセージキューを使用していました。JSIは同期で、ネイティブ参照で動作し、シリアライズを必要としません。

パラメータBridgeJSI
呼び出しモデル非同期キュー同期直接呼び出し
シリアライズJSON(シリアライズ+デシリアライズ)なし(C++オブジェクトへの直接参照)
レイテンシ呼び出しあたり3~10ミリ秒呼び出しあたり0.1~0.5ミリ秒
型付け動的(JSON経由)静的(Codegen経由)
C++統合ネイティブモジュール経由のみ(Java/ObjC)直接、仲介者なし
スレッド別のネイティブスレッドJSスレッド(同期)

React Native Teamによると、Facebook MarketplaceアプリでBridgeからJSIに移行したことで、JSとネイティブ間のデータ重複を排除し、起動時間が35%短縮され、メモリ消費が20%削減されました。

Bridgeが必要だった理由

Bridgeは“間違い”ではありませんでした — 2015年のReact Native作成時に正当化されたアーキテクチャ上の決定でした。異なる言語を持つ2つのプラットフォーム向けのネイティブ開発には、普遍的な交換フォーマットが必要でした。シリアライズフォーマットとしてのJSONはすべてのプラットフォームで利用可能で、相互作用を統一することができました。問題が明らかになったのは、React Nativeが1秒あたり数千のネイティブモジュール呼び出しを行う複雑なアプリケーションに使われ始めた後でした。

後方互換性

React Nativeは後方互換性を維持しています。Bridge用に書かれたネイティブモジュールは、互換性レイヤーを通じて新しいアーキテクチャでも引き続き動作します。ただし、新しいモジュールについては、TurboModulesを介してJSIを直接使用することを推奨します。既存のモジュールの移行は、モジュールのビジネスロジックを変更せずに相互作用プロトコルを置き換えることを意味します。

React NativeアーキテクチャにおけるJSI

JSIは、新しいReact Nativeアーキテクチャのすべてのコンポーネントが構築される基盤となるレイヤーです。JSIがなければ、Fabric(新しいレンダラー)もTurboModules(最適化されたネイティブモジュール)も不可能です。JSIは、すべてのレベルでJSがC++と相互作用する統一された方法を提供します。

FabricとJSI

Fabricは、C++ UI表現への同期アクセスにJSIを使用する新しいReact Nativeレンダラーです。古いアーキテクチャでは、レンダリングはBridgeを通じて行われていました。JSがReact要素を作成し、JSONにシリアライズし、Bridgeを通じて送信し、ネイティブ側がデシリアライズしてUIを作成していました。FabricはJSIを通じてJSから直接C++シャドウツリーオブジェクトを作成し、Yogaを介して同期的にレイアウトを計算し、準備完了したフレームをネイティブレンダラーに渡します — シリアライズは一切行われません。

TurboModulesとJSI

TurboModulesはReact Nativeネイティブモジュールの進化形です。Bridgeにモジュールを登録してJSONを介してメソッドを呼び出す代わりに、TurboModulesは遅延読み込みと直接呼び出しにJSIを使用します。JSコードが最初にモジュールにアクセスすると、JSIがホストオブジェクトを作成します — ネイティブモジュールをロードし、そのメソッドをC++関数として公開します。遅延読み込みとは、モジュールが最初のアクセスまでメモリを消費しないことを意味します — これは、数十のネイティブモジュールを持つアプリケーションで特に重要であり、その多くは特定の画面でのみ使用されます。

JSIによるコード生成

新しいアーキテクチャでJSIを扱うために、Codegen — JavaScript仕様からC++バインディングを生成するツール — が使用されます。開発者はTypeScriptまたはFlowでネイティブモジュールインターフェースを記述し、CodegenがJSI互換のホストオブジェクトを実装するC++コードを生成します。これによりルーチンワークが自動化され、JS側とC++側の型が同期されることが保証されます。

JSIのコード例

実際にJSIを扱う様子を見てみましょう。この例では、JSIを介してJSにエクスポートされる単純なC++クラスを作成し、React NativeのJavaScriptコードからそのメソッドを呼び出します。

cpp
// Calculator.h — JSからアクセス可能なC++クラスヘッダ
class Calculator {
public:
    double add(double a, double b) { return a + b; }
    double multiply(double a, double b) { return a * b; }
};

Calculatorクラスには2つの算術メソッドがあります。これをJSからアクセス可能にする必要があります。そのために、Calculatorをラップし、JSIを介してそのメソッドを公開するホストオブジェクトが作成されます。

cpp
// CalculatorHostObject.cpp — JSIラッパーの実装
class CalculatorHostObject : public jsi::HostObject {
private:
    Calculator calc;

public:
    jsi::Value get(jsi::Runtime& runtime,
        const jsi::PropNameID& name) override {
        auto propName = name.utf8(runtime);

        if (propName == "add") {
            return jsi::Function::createFromHostFunction(
                runtime, name, 2,
                [this](jsi::Runtime& runtime,
                    const jsi::Value& thisVal,
                    const jsi::Value* args,
                    size_t count) -> jsi::Value {
                    return jsi::Value(calc.add(
                        args[0].asNumber(),
                        args[1].asNumber()));
                });
        }
        return jsi::Value::undefined();
    }
};

このコードでは、JSがオブジェクトのプロパティにアクセスするたびにgetメソッドが呼び出されます。プロパティ名が“add”の場合、JSから2つの引数を受け取りcalc.add()を呼び出すC++関数が返されます。値はjsi::Valueとして返されます — JSIが自動的にdoubleをJS数値に変換します。

JavaScriptからの呼び出し

JS環境にホストオブジェクトを登録した後、呼び出しは通常のJS関数のように見えます。すべての型はコード生成段階でチェックされ、実行時の型不一致エラーを排除します。

js
// JavaScript — JSIを介したC++電卓の呼び出し
import { Calculator } from 'react-native-calculator'

const result = Calculator.add(5, 3)
console.log(result) // 8 — 同期、遅延なし

const product = Calculator.multiply(4, 2.5)
console.log(product) // 10 — 即時結果

注意:結果は即座に返され、Promise、await、コールバックはありません。これはBridgeアーキテクチャでは不可能だった同期呼び出しです。長時間実行される操作(ファイル読み取り、ネットワークリクエスト)には、非同期パターンを使用する必要があります — JSIは重いタスクに対するバックグラウンドスレッドの必要性を排除しません。

実際には、ほとんどの開発者はJSIホストオブジェクトを手動で作成しません — この作業は、TypeScript仕様に基づいてC++ラッパーを生成するCodegenが行います。ただし、JSIが内部でどのように機能するかを理解することは、効果的なパフォーマンスデバッグや、C++ライブラリ(Skia、FFmpeg、OpenCV)への直接アクセスを必要とする複雑なネイティブモジュールを作成する際に必要です。

よくある質問

React NativeでJSIはBridgeとどう違うのですか?

BridgeはJSONシリアライズとメッセージキューを通じて非同期的に動作します — 各呼び出しはデータ変換に3~10ミリ秒かかります。JSIはシリアライズなしでC++オブジェクトへの同期直接アクセスを提供し、レイテンシを0.1~0.5ミリ秒に削減します。JSIはコピーではなくオブジェクト参照の受け渡しもサポートしています。

JSIはすべてのJavaScriptエンジンをサポートしていますか?

はい、JSIはHermes(React Nativeデフォルト)、JavaScriptCore(iOS)、V8(Android)向けに実装された統一C++ APIを提供します。開発者は異なるエンジン向けに異なるコードを書く必要はありません — FabricとTurboModulesはサポートされているすべてのエンジンで同じように動作します。

古いネイティブモジュールはJSIで使用できますか?

はい、React Nativeは後方互換性レイヤーを提供します。Bridge用に書かれたネイティブモジュールは新しいアーキテクチャでも引き続き動作します。ただし、JSIの利点 — 遅延読み込みと同期呼び出し — を得るために、TurboModulesに移行することを推奨します。

JSIを使用するにはC++の知識が必要ですか?

日常的な開発には — いいえ。ネイティブモジュールのTypeScript仕様は、Codegenを通じて自動的にC++バインディングにコンパイルされます。C++の知識は、カスタムC++ライブラリを作成する場合や、ランタイムレベルでJSIのパフォーマンスをデバッグする場合にのみ必要です。

JSIはどのような問題を解決しますか?

JSIはBridgeの3つの主要な問題を解決します。JSONシリアライズによる高レイテンシ、同期呼び出しの欠如、複雑なオブジェクトを参照で渡せないことです。JSIはJavaやObjective-Cの仲介者なしでC++ライブラリを直接統合することも可能にします。

まとめ

  • JSI(JavaScript Interface)— React NativeでJavaScriptからC++オブジェクトへの直接同期アクセスを実現する技術
  • アーキテクチャ JSIはホストオブジェクトに基づく — C++オブジェクトがネイティブJSオブジェクトとしてJSにエクスポートされる
  • パフォーマンス JSIを介した呼び出しは、シリアライズがないためBridgeの10~50倍高速
  • FabricとTurboModules — JSI上に構築された新しいReact Nativeアーキテクチャの主要コンポーネント
  • 同期性 JSIはコードロジックを簡素化するが、長時間の操作には注意が必要
  • C++統合 プラットフォームラッパーなしで任意のネイティブライブラリを接続可能
  • 使用 高性能なネイティブモジュールにはJSIを使用し、既存のものはBridgeから移行する

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

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

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

こちらもお読みください