スプリットバンドルについて
従来、React Nativeアプリは以下の内容を含む1つのアプリバンドルを同梱していました。reactやreact-nativeなどのコアライブラリ- Vega固有のモジュール
- サードパーティライブラリ
- アプリのコード
システム(共通)バンドル
デバイスにプリインストールされているこのバンドルには、react、react-native、@amazon-devices/react-native-keplerなどの広く使われているライブラリが含まれています。詳細については、システム配布ライブラリを参照してください。システムバンドルはネイティブのVegaランタイムと同期された状態に保たれます。
スプリットアプリバンドル
アプリのバンドル(共通ライブラリを除く)。これには、アプリ固有のコードと固有の依存関係のみが含まれます。トランスフォーメーションの仕組み
以下は、モノリシックバンドルの分割方法を簡略化したものです。スプリットバンドルが重要な理由
スプリットバンドルには、主に次のような利点があります。- アプリサイズの縮小:アプリバンドルから共通ライブラリを削除すると、サイズが1MB以上小さくなります。
- 起動時間の短縮(TTFD):コアライブラリがデバイスに事前読み込みされるため、アプリの初期化時間が約100〜150ミリ秒短縮されます。
- 自動バグ修正:システムライブラリは個別に更新されるため、新しいアプリをリリースしなくても、アプリのバグ修正とパフォーマンスの向上が可能になります。
- 互換性問題の軽減:JSコンポーネントとネイティブコンポーネントの両方が同じシステムバージョンにあるため、互換性が確保されます。
スプリットバンドルシステムの仕組み
舞台裏では、スプリットバンドルシステムは、React Nativeが使用するJavaScriptバンドラーであるMetroの拡張に依存しています。通常、Metroはアプリのすべてのコードと依存関係を含む1つのindex.bundleを生成します。分割を可能にするために、VegaはMetroのシリアライザーステージをカスタマイズしています。このステージは、モジュールをバンドルに結合する方法を制御します。
これを可能にするのが、2つの重要なフックです。
processModuleFilter
- システムバンドルですでに提供されているモジュールを除外します。
- アプリバンドルが
reactやreact-nativeのようなライブラリを複製しないようにします。
createModuleIdFactory
- 一貫性のある確定的なIDをモジュールに割り当てて、コードを共有するときにシステムバンドルとアプリバンドルが同じモジュールIDを参照するようにします。
- Vegaは、MetroのデフォルトのインクリメンタルIDの代わりに、モジュールパスのSHA-256などのハッシュベースのスキームを使用して、ビルド間の安定性を保証します。
バンドルのタイプ
スプリットバンドルシステムでは、次の3つの主要なバンドルタイプが作成されます。コアバンドル(システム)
- 基本的なライブラリ(
react、react-native、@amazon-devices/react-native-kepler)が含まれています。 - 最初に生成され、モジュールパスをIDにマッピングする
modules.txtファイルが生成されます。 - このマッピングにより、依存バンドルの参照の一貫性が確保されます。
ライブラリバンドル(システム)
react-native-reanimatedやreact-native-screensのような人気のあるライブラリ用。- すでにバンドルされている依存関係が重複しないように、コアバンドルの
modules.txtを使用して作成されます。 - ライブラリごとに追加の
modules.txtファイルが生成されます。
アプリバンドル(スプリットアプリバンドル)
- アプリのコードは、システムバンドルに既に含まれているものを除外するようにフィルタリングされます。
- 共有IDを使用してシステム提供のモジュールを参照します。
keplerscript-app-system-bundles-config.jsonなどのメタデータが生成され、アプリに必要なシステムバンドルをVegaに伝えます。実行時に、Vegaランタイムはまずシステムバンドルを読み込み、その後アプリバンドルを上に組み込みます。
依存関係とバージョンの扱い
スプリットバンドルの主な課題は、依存関係のバージョン管理です。- システムバンドルに
react-native-screens@2.0.0があっても、アプリに2.1.0が必要な場合、競合が発生する可能性があります。 - 競合を管理するために、Vegaは
react-native-screens__2/のようなバージョン管理されたモジュールパスを内部で使用しています。 - パスにはメジャーバージョンのみがエンコードされます(例:
__2/)。そのため、2.0.0から2.0.1へのバグ修正アップグレードでは互換性が壊れたり、アプリの再ビルドを強制されたりすることはありません。
lodashなどの独自の依存関係が含まれていますが、modules.txtには含まれていません。そのため、アプリが同じバージョンのlodashに依存している場合、そのバージョンはアプリバンドル内に保持され、システムライブラリがアップグレードされた際の偶発的な破損を防ぎます。
同じメジャーバージョン、安全なアップグレード:@amzn/react-native-screens__2/...(2.0.0から2.0.1への更新では、同じパスが維持されます)
メジャーバージョンが異なる、意図的に区別:@amzn/react-native-screens__3/...
このアプローチと安定したIDを組み合わせることで、アプリの互換性を維持しながらシステムを頻繁に更新できます。
システムバンドルビルドのライフサイクル
スプリットバンドルビルドのライフサイクル全体は次のとおりです。- コアバンドルの作成:React、React Native、Vegaモジュールが含まれます。
- ライブラリバンドルの作成:コアバンドルのmodules.txtに基づいて依存関係を考慮したフィルタリングを行います。
- アプリバンドルの作成 :システム提供のモジュールはすべて削除されます。
- メタデータの生成:アプリに必要なシステムバンドルを一覧表示します。
- Vegaの読み込み:最初にシステムバンドル、次にアプリバンドル。
関連トピック
- Vegaアプリ向けReact Nativeのアーキテクチャ:React NativeランタイムをOSに組み込む方法やアプリと動的にリンクする方法など、Vegaの背後にある幅広いアーキテクチャ上の決定事項について説明します。
- サポート対象のライブラリとサービス:システムバンドルの一部として配布されるすべてのシステム配布ライブラリを、そのバージョンと互換性の詳細とともに一覧表示します。
- VMRPを使用してアプリにライブラリをインポートする方法:標準のnpmエイリアスとオーバーライドをサポートしないスプリットバンドルのモジュール解決を設定する方法について説明します。
- アプリのパフォーマンスに関するベストプラクティス:システムバンドルが自動的に処理する範囲を超えて、バンドルサイズを縮小し、起動時間を改善するための追加手法を提供します。
- Vega ESLintプラグインのインストールと設定:
package.jsonでシステム配布ライブラリの使用状況を検証し、スプリットバンドル時に異なる動作をするインポートに対してフラグを立てる、リントルールが含まれます。

