Javascript Interface(JSI): 反応ネイティブの概要と再構築の必要性

Nov 26 2022
React Native には、クロス プラットフォーム サポート、OTA アップデート、ライブ リロード、コスト効率などの複数の利点がバンドルされていますが、React Native アプリケーションのスケーリングにおける最大のボトルネックは、アプリケーションがデータ集約型になったとき、または複数のモジュールが存在するときのモジュールの追加に伴うパフォーマンスでした。橋を渡る必要があります。しかし、現在のアーキテクチャはどのように機能するのでしょうか? React Native アーキテクチャは、次の 3 つのスレッドに依存します。 a) UI スレッド: これは、Android および iOS ビューのレンダリングに使用されるメイン アプリケーション スレッドです。

React Native には、クロス プラットフォーム サポート、OTA アップデート、ライブ リロード、コスト効率などの複数の利点がバンドルされていますが、React Native アプリケーションのスケーリングにおける最大のボトルネックは、アプリケーションがデータ集約型になったとき、または複数のモジュールが存在するときのモジュールの追加に伴うパフォーマンスでした。橋を渡る必要があります。

しかし、現在のアーキテクチャはどのように機能するのでしょうか?

React Native アーキテクチャは、次の 3 つのスレッドに依存します。a) UI スレッド:これは、Android および iOS ビューのレンダリングに使用されるメイン アプリケーション スレッドです。b) シャドー スレッド:ホスト プラットフォームでレンダリングする前に、 ( Yogaを使用して) 要素のレイアウトを計算する一種のバックグラウンド スレッドです。c) JS スレッド:反応ネイティブ アプリケーションのすべてのロジックの処理を担当するバンドルされた JS 。


ソース: FreeCodeCamp

これらのスレッド間の相互作用は直接的ではなく、あるスレッドが他のスレッドと相互作用する必要があるたびに、データを JSON にシリアライズおよびデシリアライズしてブリッジを通過するという重いタスクを実行する必要があります。これにより、データの不要なコピーが発生し、操作が非同期で厳密な型指定がないため、このブリッジは非常に簡単に混雑を乗り越えることができます。

現在のアーキテクチャのいくつかの制限:
1. Javascript とネイティブ側はお互いを認識せず、非同期の JSON メッセージに依存しています。
2. 起動時にすべてのモジュールが読み込まれるため、操作にかかる時間が長くなります。
3. アクションに優先順位を付けない: 重要なユーザー インタラクションを他のアクションよりも優先することはできません。
4. ブリッジのシリアライゼーション
5. UI 要素は JS スレッドから直接アクセスできません。

反応ネイティブの現在のアーキテクチャ

JSIの紹介

反応ネイティブの新しいアーキテクチャ

JSI は、JavaScript とネイティブ部分の相互作用に大きな変化をもたらします。JS と C++ 間のインターフェースを利用して、2 つの領域間の直接通信を提供します。JavaScript インターフェイスを使用して、JS はホスト オブジェクトへの参照を保持し、それらのメソッドを呼び出すことができます。ホスト オブジェクトの助けを借りて、javascript コンテキストでネイティブ オブジェクトを使用できるようになりました。最大のボトルネックだったブリッジは、次のように分割されます。

ファブリック

UI マネージャーの再構築である、Facebook によって作成された新しいレンダリング システム。このレンダラーは C++ で実装され、コアはプラットフォーム間で共有されます。以前の実装では、レイアウトの作成には、JSON のシリアル化やブリッジをまたぐジャンプなどの複数のステップが含まれていました。これには、ブリッジがブロックされたときに大きな問題が発生していました。新しい実装により、UI マネージャーは Shadow Tree を C++ で直接作成できます。これにより、レルム間のジャンプ数が減り、エクスペリエンスが大幅に向上します。操作は、React (JavaScript) からレンダラー (C++) に (通常は JavaScript スレッドで) 実行される同期的でスレッドセーフです。また、JavaScript 値を JSI から直接取得できるため、データのシリアル化も少なくなります。この直接制御は、アクションの優先順位付けにも役立ちます。レンダラーは、特定のユーザー インタラクションに優先順位を付けて、タイムリーに処理されるようにすることができます。これにより、リスト、ナビゲーション、ジェスチャー処理のパフォーマンスが大幅に向上します。

ターボモジュール

以前の実装では、ネイティブ モジュールへの参照がなかったため、すべてのモジュールが起動時に読み込まれ、TTI (Time to Interactive) が増加しましたが、ターボ モジュールを使用すると、必要に応じてモジュールを遅延読み込みでき、これが役立ちます。起動時間の改善に。例: リンクからドキュメントを印刷するモジュールがある場合、以前のアーキテクチャで行われていたアプリケーションの起動時ではなく、印刷画面に到達したときにこのモジュールをロードできるようになりました。モジュールを C++ で記述できることも、プラットフォーム間での重複した実装を減らすという利点をもたらします。

コード生成

これをすべて接着し、両方のレルムに互換性を持たせるために、React Native チームは型チェッカーを構築して、JS とネイティブ側の間の互換性を自動化しました。このツールはCodegen と呼ばれます。モジュラー アプローチを使用します。つまり、静的に型指定された Javascript 言語は、そのシステムのパーサーを使用してサポートできます。型付けされた JavaScript を信頼できるソースとして使用することにより、このジェネレーターは Fabric と TurboModules が必要とするインターフェイス ファイルを定義して、レルム全体に自信を持ってメッセージを送信できます。Codegen はコンパイル時のタイプ セーフも提供します。つまり、両方の環境で実行時チェックなしでコマンドを実行できるため、出荷するコード サイズが小さくなり、実行が高速になります。
現在、C++ コードがあり、C++ は厳密に型指定されているため、型を定義する必要があり、コード内のどこにも記述できないため、JS コードを型指定する必要があります。基本的にインターフェイスを作成し、C++ で生成されているため、送信されるデータを基本的に信頼できるようになり、データを検証するために行ったり来たりする必要がなくなりました。これは、型チェックを使用することで、致命的なクラッシュやユーザー エクスペリエンスの低下につながる可能性のある問題を開発段階で簡単に特定できることも意味します。

JSI の主な利点

  1. Javascript コードは、任意のネイティブ UI 要素への参照を保持し、その要素のメソッドを呼び出すことができます (Web での DOM 操作に似ています)。
  2. パフォーマンスを大幅に向上させることができるネイティブ コードへの高速かつ直接的なバインディング。たとえば、MMKVは Asyncstorage よりも最大 30 倍高速な JSI を使用します。
  3. JavaScript Core 以外のエンジンも使用できます。
  4. ネイティブ モジュールは、必要に応じてロードできます。
  5. JS とネイティブ コードの互換性を確保するための静的型チェック。

React ネイティブ JSI は現在、実験的なロールアウト段階にあり、この変更を採用するプロジェクトが増えるにつれて、新しいアーキテクチャの制限と影響についてさらに知ることができますが、React Native およびクロスプラットフォーム アプリケーション開発の将来について確かなことは 1 つあります。エキサイティングなようです。