メインコンテンツへスキップ

Codegenの使用

このガイドでは、以下の方法を学びます。

  • Codegen の設定。
  • 各プラットフォームで手動で実行する方法。

また、生成されたコードについても説明します。

前提条件

Codegen を手動で実行する場合でも、コードを適切に生成するためには常に React Native アプリが必要です。

Codegen プロセスはアプリのビルドと密接に関連しており、スクリプトは react-native NPM パッケージ内にあります。

このガイドのために、以下のように React Native CLI を使用してプロジェクトを作成してください。

bash
npx @react-native-community/cli@latest init SampleApp --version 0.76.0

Codegen は、カスタムモジュールやコンポーネントのためのグルーコード(接着剤の役割を果たすコード)を生成するために使用されます。作成方法の詳細については、Turbo Native Modules と Fabric Native Components のガイドを参照してください。

Codegen の設定

Codegen は、アプリの package.json ファイルを修正することで設定できます。CodegencodegenConfig というカスタムフィールドによって制御されます。

package.json
  "codegenConfig": {
"name": "<SpecName>",
"type": "<types>",
"jsSrcsDir": "<source_dir>",
"android": {
"javaPackageName": "<java.package.name>"
},
"ios": {
"modules": {
"TestModule": {
"className": "<iOS-class-implementing-the-RCTModuleProvider-protocol>",
"unstableRequiresMainQueueSetup": false,
"conformsToProtocols": ["RCTImageURLLoader", "RCTURLRequestHandler", "RCTImageDataDecoder"],
}
},
"components": {
"TestComponent": {
"className": "<iOS-class-implementing-the-component>"
}
}
}
},

このスニペットをアプリに追加し、様々なフィールドをカスタマイズできます。

  • name: codegen 設定の名前。これは codegen の出力(ファイル名やコード)をカスタマイズします。
  • type
    • modules: モジュール用のコードのみを生成します。
    • components: コンポーネント用のコードのみを生成します。
    • all: 全てのコードを生成します。
  • jsSrcsDir: 全ての仕様ファイル (spec) が存在するルートフォルダ。
  • android: Android 用の Codegen 設定(すべてオプション)
    • .javaPackageName: Android の Java codegen 出力のパッケージ名を設定します。
  • ios: iOS 用の Codegen 設定(すべてオプション)
    • .modules[moduleName]
      • .className: このモジュールの ObjC クラス。または、C++ 専用モジュールの場合は、その RCTModuleProvider クラス。
      • .unstableRequiresMainQueueSetup: JavaScript を実行する前に、このモジュールを UI スレッドで初期化します。
      • .conformsToProtocols: このモジュールが以下のプロトコルのいずれかに準拠しているかを注釈します: RCTImageURLLoader, RCTURLRequestHandler, RCTImageDataDecoder
    • .components[componentName]:
      • .className: このコンポーネントの ObjC クラス (例: TextInput -> RCTTextInput)。

Codegen が実行されると、アプリのすべての依存関係の中から、特定の規約に従った JS ファイルを検索し、必要なコードを生成します。

  • Turbo Native Modules では、仕様ファイル名のプレフィックスが Native である必要があります。例えば、NativeLocalStorage.ts は仕様ファイルの有効な名前です。
  • Native Fabric Components では、仕様ファイル名のサフィックスが NativeComponent である必要があります。例えば、WebViewNativeComponent.ts は仕様ファイルの有効な名前です。

Codegen の実行

このガイドの残りの部分では、プロジェクトに Native Turbo Module、Native Fabric Component、またはその両方がすでに設定されていることを前提としています。また、package.json で指定された jsSrcsDir に有効な仕様ファイルが存在することも前提とします。

Android

Android 用の Codegen は、React Native Gradle Plugin (RNGP) に統合されています。RNGP には、package.json ファイルで定義された設定を読み取り、Codegen を実行するタスクが含まれています。Gradle タスクを実行するには、まずプロジェクトの android フォルダに移動します。次に、以下を実行します。

bash
./gradlew generateCodegenArtifactsFromSchema

このタスクは、アプリのすべてのインポートされたプロジェクト(アプリとそれにリンクされているすべての node modules)に対して generateCodegenArtifactsFromSchema コマンドを呼び出します。対応する node_modules/<dependency> フォルダにコードを生成します。例えば、Node モジュール名が my-fabric-component の Fabric Native Component がある場合、生成されたコードは SampleApp/node_modules/my-fabric-component/android/build/generated/source/codegen パスに配置されます。アプリの場合、コードは android/app/build/generated/source/codegen フォルダに生成されます。

生成されたコード

上記の Gradle コマンドを実行した後、SampleApp/android/app/build フォルダに codegen コードが見つかります。構造は次のようになります。

build
└── generated
└── source
└── codegen
├── java
│ └── com
│ ├── facebook
│ │ └── react
│ │ └── viewmanagers
│ │ ├── <nativeComponent>ManagerDelegate.java
│ │ └── <nativeComponent>ManagerInterface.java
│ └── sampleapp
│ └── NativeLocalStorageSpec.java
├── jni
│ ├── <codegenConfig.name>-generated.cpp
│ ├── <codegenConfig.name>.h
│ ├── CMakeLists.txt
│ └── react
│ └── renderer
│ └── components
│ └── <codegenConfig.name>
│ ├── <codegenConfig.name>JSI-generated.cpp
│ ├── <codegenConfig.name>.h
│ ├── ComponentDescriptors.cpp
│ ├── ComponentDescriptors.h
│ ├── EventEmitters.cpp
│ ├── EventEmitters.h
│ ├── Props.cpp
│ ├── Props.h
│ ├── ShadowNodes.cpp
│ ├── ShadowNodes.h
│ ├── States.cpp
│ └── States.h
└── schema.json

生成されたコードは2つのフォルダに分かれています。

  • java: プラットフォーム固有のコードが含まれています。
  • jni: JS と Java が正しく連携するために必要な C++ コードが含まれています。

java フォルダには、Fabric Native Component の生成コードが com/facebook/viewmanagers サブフォルダ内にあります。

  • <nativeComponent>ManagerDelegate.java には、ViewManager がカスタム Native Component 上で呼び出すことができるメソッドが含まれています。
  • <nativeComponent>ManagerInterface.java には、ViewManager のインターフェースが含まれています。

一方、codegenConfig.android.javaPackageName で設定した名前のフォルダには、Turbo Native Module がタスクを実行するために実装する必要がある抽象クラスがあります。

最後に、jni フォルダには、JS と Android を接続するためのすべてのボイラープレートコードがあります。

  • <codegenConfig.name>.h: カスタム C++ Turbo Native Modules のインターフェースが含まれています。
  • <codegenConfig.name>-generated.cpp: カスタム C++ Turbo Native Modules のグルーコードが含まれています。
  • react/renderer/components/<codegenConfig.name>: このフォルダには、カスタムコンポーネントに必要なすべてのグルーコードが含まれています。

この構造は、codegenConfig.type フィールドに値 all を使用して生成されました。値 modules を使用した場合、react/renderer/components/ フォルダは表示されません。値 components を使用した場合、他のファイルは表示されません。

iOS

iOS 用の Codegen は、ビルドプロセス中に呼び出されるいくつかの Node スクリプトに依存しています。これらのスクリプトは SampleApp/node_modules/react-native/scripts/ フォルダにあります。

メインスクリプトは generate-codegen-artifacts.js スクリプトです。このスクリプトを呼び出すには、アプリのルートフォルダから次のコマンドを実行します。

bash
node node_modules/react-native/scripts/generate-codegen-artifacts.js

Usage: generate-codegen-artifacts.js -p [path to app] -t [target platform] -o [output path]

Options:
--help Show help [boolean]
--version Show version number [boolean]
-p, --path Path to the React Native project root. [required]
-t, --targetPlatform Target platform. Supported values: "android", "ios",
"all". [required]
-o, --outputPath Path where generated artifacts will be output to.

ここで、

  • --path はアプリのルートフォルダへのパスです。
  • --outputPathCodegen が生成されたファイルを書き込む場所です。
  • --targetPlatform はコードを生成したいプラットフォームです。

生成されたコード

これらの引数でスクリプトを実行すると、

shell
node node_modules/react-native/scripts/generate-codegen-artifacts.js \
--path . \
--outputPath ios/ \
--targetPlatform ios

ios/build フォルダにこれらのファイルが生成されます。

build
└── generated
└── ios
├── <codegenConfig.name>
│ ├── <codegenConfig.name>-generated.mm
│ └── <codegenConfig.name>.h
├── <codegenConfig.name>JSI-generated.cpp
├── <codegenConfig.name>JSI.h
├── FBReactNativeSpec
│ ├── FBReactNativeSpec-generated.mm
│ └── FBReactNativeSpec.h
├── FBReactNativeSpecJSI-generated.cpp
├── FBReactNativeSpecJSI.h
├── RCTModulesConformingToProtocolsProvider.h
├── RCTModulesConformingToProtocolsProvider.mm
└── react
└── renderer
└── components
└── <codegenConfig.name>
├── ComponentDescriptors.cpp
├── ComponentDescriptors.h
├── EventEmitters.cpp
├── EventEmitters.h
├── Props.cpp
├── Props.h
├── RCTComponentViewHelpers.h
├── ShadowNodes.cpp
├── ShadowNodes.h
├── States.cpp
└── States.h

これらの生成されたファイルの一部は、React Native のコアで使用されます。そして、package.json の codegenConfig.name フィールドで指定したのと同じ名前を持つ一連のファイルがあります。

  • <codegenConfig.name>/<codegenConfig.name>.h: カスタム iOS Turbo Native Modules のインターフェースが含まれています。
  • <codegenConfig.name>/<codegenConfig.name>-generated.mm: カスタム iOS Turbo Native Modules のグルーコードが含まれています。
  • <codegenConfig.name>JSI.h: カスタム C++ Turbo Native Modules のインターフェースが含まれています。
  • <codegenConfig.name>JSI-generated.h: カスタム C++ Turbo Native Modules のグルーコードが含まれています。
  • react/renderer/components/<codegenConfig.name>: このフォルダには、カスタムコンポーネントに必要なすべてのグルーコードが含まれています。

この構造は、codegenConfig.type フィールドに値 all を使用して生成されました。値 modules を使用した場合、react/renderer/components/ フォルダは表示されません。値 components を使用した場合、他のファイルは表示されません。