0.69 libray Codegen
0.70官方文档:reactnative.dev/docs/0.70/t…
以下基于 react-native@0.69.4 分析
graph TD
subgraph Android Codegen
react-native-gradle-plugin --> generateCodegenSchemaFromJavaScript
react-native-gradle-plugin --> generateCodegenArtifactsFromSchema
end
generateCodegenSchemaFromJavaScript --> combine-js-to-schema-cli.js
generateCodegenArtifactsFromSchema --> generate-specs-cli.js
subgraph iOS Codegen
react_native_pods.rb
script_phases.sh
end
script_phases.sh -. noDiscovery .-> combine-js-to-schema-cli.js
script_phases.sh -. noDiscovery .-> generate-specs-cli.js
script_phases.sh -- discovery --> generate-artifacts.js
generate-artifacts.js --> generate-specs-cli.js
generate-artifacts.js --> generate-provider-cli.js
react_native_pods.rb -- discovery --> generate-artifacts.js
react_native_pods.rb -. noDiscovery .-> generate-provider-cli.js
subgraph RNCodegen.js
generate
generateFromSchemas
generateViewConfig
end
generate-specs-cli.js --> generate
generate-provider-cli.js -->|fabric| generateFromSchemas
subgraph JavaScript Codegen
babel-plugin-codegen
end
babel-plugin-codegen --> generateViewConfig
library Codegen for Android
示例APP的settings.gradle,github.com/Sunbreak/re…
includeBuild('../node_modules/react-native-gradle-plugin')
集成react-native-gradle-plugin,即可
- 为Turbo Module静态生成
Spec.java和JNI的.h/cpp,github.com/Sunbreak/re…
$ tree ${NODE_MODULES}/${LIBRARY}/android/build/generated/source/codegen
├── java
│ └── com
│ └── turboonly
│ └── NativeTurboOnlySpec.java
├── jni
│ ├── Android.mk
│ ├── CMakeLists.txt
│ ├── RNTurboOnlySpec-generated.cpp
│ ├── RNTurboOnlySpec.h
└── schema.json
- 为Fabric Component静态生成
ComponentDescriptor.h、EventEmitter.h/cpp、Props.h/cpp、ShadowNode.h/cpp、Interface.java、Delegate.java,github.com/Sunbreak/re…
$ tree ${NODE_MODULES}/${LIBRARY}/android/build/generated/source/codegen
├── java
│ └── com
│ └── facebook
│ └── react
│ └── viewmanagers
│ ├── FabricOnlyViewManagerDelegate.java
│ └── FabricOnlyViewManagerInterface.java
├── jni
│ ├── Android.mk
│ ├── CMakeLists.txt
│ └── react
│ └── renderer
│ └── components
│ └── RNFabricOnlyViewSpec
│ ├── ComponentDescriptors.h
│ ├── EventEmitters.cpp
│ ├── EventEmitters.h
│ ├── Props.cpp
│ ├── Props.h
│ ├── ShadowNodes.cpp
│ └── ShadowNodes.h
└── schema.json
- react-native-gradle-plugin的ReactPlugin.kt
classDiagram
class buildCodegenCLI {
+生成CodegenCLI工具
}
buildCodegenCLI <|-- generateCodegenSchemaFromJavaScript
class generateCodegenSchemaFromJavaScript {
+生成schema.json文件
}
generateCodegenSchemaFromJavaScript <|-- generateCodegenArtifactsFromSchema
class generateCodegenArtifactsFromSchema {
+生成Java和C++、CMake/Android.mk文件
}
generateCodegenArtifactsFromSchema <|-- preBuild
class preBuild {
+Gradle内置任务
}
buildCodegenCLI
- react-native-gradle-plugin的BuildCodegenCLITask.kt:
node_modules/react-native-codegen中没有scripts和src,单独运行./gradlew buildCodegenCLI会报错
@get:InputFiles
val input: FileCollection by lazy {
codegenDir.get().files("scripts", "src", "package.json", ".babelrc", ".prettierrc")
}
...
init {
// We need this condition as we want a single instance of BuildCodegenCLITask to execute
// per project. Therefore we can safely skip the task if the lib/cli/ folder is available.
onlyIf {
val cliDir = codegenDir.file("lib/cli/").get().asFile
!cliDir.exists() || cliDir.listFiles()?.size == 0
}
}
- react-native的package.json:
yarn install安装react-native-codegen@0.69.1之后,node_modules/react-native-codegen包含lib/cli,根据BuildCodegenCLITask的onlyIf,codegenCLI并非BuildCodegenCLITask运行时生成,而是从NPM拉取预编译好的包
react-native-codegen@^0.69.1:
version "0.69.1"
- 参考react-native-codegn的package.json和scripts/oss/build.sh:
yarn run build编译即得到codegenCLI
"scripts": {
"build": "yarn clean && node scripts/build.js --verbose",
"clean": "rm -rf lib",
"prepare": "yarn run build"
},
generateCodegenSchemaFromJavaScript
- react-native-gradle-plugin的GenerateCodegenSchemaTask.kt:监控
jsRootDir下的**/*.js文件,一旦有变动,立即调用combine-js-to-schema-cli.js,读取jsRootDir中的文件,生成schema.json
@get:InputFiles val jsInputFiles = project.fileTree(jsRootDir) { it.include("**/*.js") }
@get:OutputFile
val generatedSchemaFile: Provider<RegularFile> = generatedSrcDir.file("schema.json")
...
codegenDir
.file("lib/cli/combine/combine-js-to-schema-cli.js")
.get()
.asFile.absolutePath,
generatedSchemaFile.get().asFile.absolutePath,
jsRootDir.asFile.get().absolutePath,
...
generateCodegenArtifactsFromSchema
- react-native-gradle-plugin的GenerateCodegenArtifactsTask.kt:监控
schema.json,一旦改动,立即调用generate-specs-cli.js,读取schema.json,生成specs*系列文件
@get:InputFile
val generatedSchemaFile: Provider<RegularFile> = generatedSrcDir.file("schema.json")
...
reactNativeDir.file("scripts/generate-specs-cli.js").get().asFile.absolutePath,
"--platform",
"android",
"--schemaPath",
generatedSchemaFile.get().asFile.absolutePath,
"--outputDir",
generatedSrcDir.get().asFile.absolutePath,
"--libraryName",
libraryName.get(),
"--javaPackageName",
codegenJavaPackageName.get()))
...
library Codegen for iOS
集成react_native_pods.rb,即可
- 为Turbo Module静态生成ObjC++的
.h/mm
$ tree ${APP}/ios/build/generated/ios/${LIBRARY}
├── RNTurboOnlySpec-generated.mm
└── RNTurboOnlySpec.h
- 为Fabric Component静态生成
ComponentDescriptor.h、EventEmitter.h/cpp、Props.h/cpp、ShadowNode.h/cpp、RCTComponentViewHelpers.h、RCTThirdPartyFabricComponentsProvider.h/mm
$ tree ${APP}/ios/build/generated/ios
├── RCTThirdPartyFabricComponentsProvider.h
├── RCTThirdPartyFabricComponentsProvider.mm
└── react
└── renderer
└── components
├── RNFabricOnlyViewSpec
│ ├── ComponentDescriptors.h
│ ├── EventEmitters.cpp
│ ├── EventEmitters.h
│ ├── Props.cpp
│ ├── Props.h
│ ├── RCTComponentViewHelpers.h
│ ├── ShadowNodes.cpp
│ └── ShadowNodes.h
graph TD
script_phases.sh -. noDiscovery .-> combine-js-to-schema-cli.js
script_phases.sh -. noDiscovery .-> generate-specs-cli.js
script_phases.sh -- discovery --> generate-artifacts.js
generate-artifacts.js --> generate-provider-cli.js
generate-artifacts.js --> generate-specs-cli.js
react_native_pods.rb -- discovery --> generate-artifacts.js
react_native_pods.rb -. noDiscovery .-> generate-provider-cli.js
subgraph RNCodegen.js
generate
generateFromSchemas
end
generate-specs-cli.js --> generate
generate-provider-cli.js -->|fabric| generateFromSchemas
USE_CODEGEN_DISCOVERY为true
install时自动添加sh、生成spec、生成全部代码
pod install时,use_react_native_codegen_discovery自动找到podspec,将script_phases.sh插入,生成React-Codegen库的spec,生成所有codegen代码
graph TD
Podfile --> use_react_native
subgraph react_native_pods.rb
use_react_native --> use_react_native_codegen_discovery
use_react_native_codegen_discovery --> get_react_codegen_script_phases
use_react_native_codegen_discovery --> generate_react_codegen_podspec
end
get_react_codegen_script_phases --> get_script_phases_with_codegen_discovery
subgraph script_phases.rb
get_script_phases_with_codegen_discovery
end
generate_react_codegen_podspec --> 写入podspec.json
use_react_native_codegen_discovery --> generate-artifacts.js
def use_react_native! (options={})
if ENV['USE_CODEGEN_DISCOVERY'] == '1'
use_react_native_codegen_discovery!({...})
...
else
...
end
...
def get_react_codegen_script_phases(options={})
return {
...
'script': get_script_phases_with_codegen_discovery(...),
}
end
...
def use_react_native_codegen_discovery!(options={})
...
# Generate React-Codegen podspec here to add the script phases.
script_phases = get_react_codegen_script_phases(options)
react_codegen_spec = get_react_codegen_spec(fabric_enabled: fabric_enabled, script_phases: script_phases)
generate_react_codegen_podspec!(react_codegen_spec)
out = Pod::Executable.execute_command(
'node',
[
"#{relative_installation_root}/#{react_native_path}/scripts/generate-artifacts.js",
...
end
- react_native_pods_utils的script_phases.rb
def get_script_phases_with_codegen_discovery(options)
export_vars = {
...
'RCT_SCRIPT_TYPE' => "withCodegenDiscovery",
}
return get_script_template(options[:react_native_path], export_vars)
end
compile时script_phases.sh
graph TD
podspec([x.podspec]) --> withCodgenDiscovery
subgraph script_phases.sh
withCodgenDiscovery --> generateArtifacts
end
generateArtifacts --> generate-artifacts.js
- react_native_pods_utils的script_phases.sh
generateArtifacts () {
...
"$NODE_BINARY" "scripts/generate-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$TEMP_OUTPUT_DIR" --fabricEnabled "$RCT_SCRIPT_FABRIC_ENABLED" --configFileDir "$RCT_SCRIPT_CONFIG_FILE_DIR" --nodeBinary "$NODE_BINARY"
...
}
...
withCodgenDiscovery () {
setup_dirs
find_node
generateArtifacts
moveOutputs
}
USE_CODEGEN_DISCOVERY为false
install前手动添加sh
需要在podspec中手动声明use_react_native_codegen,保证install时添加script_phases.sh
graph TD
podspec([x.podspec]) --> use_react_native_codegen
subgraph react_native_pods.rb
use_react_native_codegen
end
use_react_native_codegen --> get_script_phases_no_codegen_discovery
subgraph script_phases.rb
get_script_phases_no_codegen_discovery
end
- FBReactNativeSpec的FBReactNativeSpec.podspec
require_relative "#{react_native_path}/scripts/react_native_pods.rb"
...
Pod::Spec.new do |s|
...
# This podspec is used to trigger the codegen, and built files are generated in a different location.
# We don't want this pod to actually include any files.
...
use_react_native_codegen!(...)
end
def use_react_native_codegen!(spec, options={})
...
spec.script_phase = {
...
:script => get_script_phases_no_codegen_discovery(...)
...
}
...
end
- react_native_pods_utils的script_phases.rb
def get_script_phases_no_codegen_discovery(options)
export_vars = {
...
'RCT_SCRIPT_LIBRARY_NAME' => "#{options[:library_name]}",
...
}
return get_script_template(options[:react_native_path], export_vars)
end
install时生成spec、生成部分代码
graph TD
Podfile --> use_react_native
subgraph react_native_pods.rb
use_react_native --> generate_react_codegen_podspec
use_react_native -->|fabric| checkAndGenerateEmptyThirdPartyProvider
end
generate_react_codegen_podspec --> 写入podspec.json
checkAndGenerateEmptyThirdPartyProvider --> generate-provider-cli.js
def use_react_native! (options={})
if ENV['USE_CODEGEN_DISCOVERY'] == '1'
...
else
# Generate a podspec file for generated files.
# This gets generated in use_react_native_codegen_discovery when codegen discovery is enabled.
react_codegen_spec = get_react_codegen_spec(fabric_enabled: fabric_enabled)
generate_react_codegen_podspec!(react_codegen_spec)
end
...
if fabric_enabled
checkAndGenerateEmptyThirdPartyProvider!(prefix)
...
end
...
end
...
# This is a temporary supporting function until we enable use_react_native_codegen_discovery by default.
def checkAndGenerateEmptyThirdPartyProvider!(react_native_path)
return if ENV['USE_CODEGEN_DISCOVERY'] == '1'
...
Pod::UI.puts '[Codegen] generating an empty RCTThirdPartyFabricComponentsProvider'
Pod::Executable.execute_command(
'node',
[
"#{relative_installation_root}/#{react_native_path}/scripts/generate-provider-cli.js",
...
end
compile时script_phases.sh
graph TD
podspec([x.podspec]) --> noCodegenDiscovery
subgraph script_phases.sh
noCodegenDiscovery --> generateCodegenSchemaFromJavaScript
noCodegenDiscovery --> generateCodegenArtifactsFromSchema
end
generateCodegenSchemaFromJavaScript --> combine-js-to-schema-cli.js
generateCodegenArtifactsFromSchema --> generate-specs-cli.js
- react_native_pods_utils的script_phases.sh
runSpecCodegen () {
"$NODE_BINARY" "scripts/generate-specs-cli.js" --platform ios --schemaPath "$GENERATED_SCHEMA_FILE" --outputDir "$1" --libraryName "$RCT_SCRIPT_LIBRARY_NAME" --libraryType "$2"
}
generateCodegenSchemaFromJavaScript () {
...
"$NODE_BINARY" "$CODEGEN_CLI_PATH/lib/cli/combine/combine-js-to-schema-cli.js" "$GENERATED_SCHEMA_FILE" $JS_SRCS
}
generateCodegenArtifactsFromSchema () {
...
runSpecCodegen "$TEMP_OUTPUT_DIR/$RCT_SCRIPT_CODEGEN_MODULE_DIR/$RCT_SCRIPT_LIBRARY_NAME" "modules"
runSpecCodegen "$TEMP_OUTPUT_DIR/$RCT_SCRIPT_CODEGEN_COMPONENT_DIR/$RCT_SCRIPT_LIBRARY_NAME" "components"
...
}
...
noCodegenDiscovery () {
setup_dirs
find_node
generateCodegenSchemaFromJavaScript
generateCodegenArtifactsFromSchema
moveOutputs
}
library Codegen for JavaScript
集成@react-native/babel-plugin-codegen,即可
- 为Fabric Component静态生成
NativeViewConfig.js
- babel-plugin-codegen的index.js
...
try {
flow = require('react-native-codegen/src/parsers/flow');
RNCodegen = require('react-native-codegen/src/generators/RNCodegen');
} catch (e) {
// Fallback to lib when source doesn't exit (e.g. when installed as a dev dependency)
flow = require('react-native-codegen/lib/parsers/flow');
RNCodegen = require('react-native-codegen/lib/generators/RNCodegen');
}
function generateViewConfig(filename, code) {
...
return RNCodegen.generateViewConfig({
schema,
libraryName,
});
}
...
module.exports = function ({parse, types: t}) {
return {
...
visitor: {
...
Program: {
exit(path) {
if (this.defaultExport) {
const viewConfig = generateViewConfig(this.filename, this.code);
...
- react-native-codegn的RNCodegen.js
const generateViewConfigJs = require('./components/GenerateViewConfigJs.js');
...
module.exports = {
...
generateViewConfig({libraryName, schema}: LibraryOptions): string {
...
const result = generateViewConfigJs
.generate(libraryName, schema)
.values()
.next();
...
},
}
用途
We just introduced TypeScript support in this babel plugin via D39136171 (df0b690). This version bump will allow us to enable the static ViewConfig codegen in TypeScript React Native libraries, like React Native SVG. See PR: software-mansion/react-native-svg#1847
libray Codegen工具脚本
generate-artifacts-cli.js
graph TD
generate-artifacts.js --> combine-js-to-schema-cli.js
generate-artifacts.js --> generate-specs-cli.js
generate-artifacts.js -->|fabric| generate-provider-cli.js
subgraph RNCodegen.js
generate
generateFromSchemas
end
generate-specs-cli.js --> generate
generate-provider-cli.js --> generateFromSchemas
function main(appRootDir, outputPath) {
...
try {
...
libraries.forEach(library => {
...
executeNodeScript(..., 'combine-js-to-schema-cli.js', ...);
...
executeNodeScript(..., 'generate-specs-cli.js', ...);
...
if (CODEGEN_FABRIC_ENABLED) {
...
executeNodeScript(..., 'generate-provider-cli.js', ...);
...
}
}
}
...
}
try {
RNCodegen = require('../packages/react-native-codegen/lib/generators/RNCodegen.js');
} catch (e) {
RNCodegen = require('react-native-codegen/lib/generators/RNCodegen.js');
...
}
...
RNCodegen.generateFromSchemas(
{
schemas,
outputDirectory,
},
{
generators: GENERATORS[platform],
},
);
...
combine-js-to-schema-cli.js
- react-native-codegn的combine-js-to-schema-cli.js:过滤JS文件,调用
combine-js-to-schema
const combine = require('./combine-js-to-schema');
...
function filterJSFile(file: string) {
return (
/^(Native.+|.+NativeComponent)/.test(path.basename(file)) &&
// NativeUIManager will be deprecated by Fabric UIManager.
// For now, ignore this spec completely because the types are not fully supported.
!file.endsWith('NativeUIManager.js') &&
// NativeSampleTurboModule is for demo purpose. It should be added manually to the
// app for now.
!file.endsWith('NativeSampleTurboModule.js') &&
!file.includes('__tests')
);
}
...
const combined = combine(allFiles);
- react-native-codegn的combine-js-to-schema.js:判断
export default codegenNativeComponent<或者extends TurboModule,然后使用TypeScriptParser或者FlowParser解析
function combineSchemas(files: Array<string>): SchemaType {
...
if (
contents &&
(/export\s+default\s+\(?codegenNativeComponent</.test(contents) ||
/extends TurboModule/.test(contents))
) {
...
const schema = isTypeScript
? TypeScriptParser.parseFile(filename)
: FlowParser.parseFile(filename);
...
}
generate-specs-cli.js
try {
RNCodegen = require('../packages/react-native-codegen/lib/generators/RNCodegen.js');
} catch (e) {
RNCodegen = require('react-native-codegen/lib/generators/RNCodegen.js');
...
}
...
RNCodegen.generate(
{
libraryName,
schema,
outputDirectory,
packageName,
},
{
generators: GENERATORS[libraryType][platform],
},
);
RNCodegen.js
react-native-codegn的RNCodegen.js
generate for Android
- 为Fabric Component静态生成
ComponentDescriptor.h、EventEmitter.h/cpp、Props.h/cpp、ShadowNode.h/cpp、**Interface.java、**Delegate.java
const generateComponentDescriptorH = require('./components/GenerateComponentDescriptorH.js');
// const generateComponentHObjCpp = require('./components/GenerateComponentHObjCpp.js');
const generateEventEmitterCpp = require('./components/GenerateEventEmitterCpp.js');
const generateEventEmitterH = require('./components/GenerateEventEmitterH.js');
const generatePropsCpp = require('./components/GeneratePropsCpp.js');
const generatePropsH = require('./components/GeneratePropsH.js');
...
const generatePropsJavaInterface = require('./components/GeneratePropsJavaInterface.js');
const generatePropsJavaDelegate = require('./components/GeneratePropsJavaDelegate.js');
...
const generateShadowNodeCpp = require('./components/GenerateShadowNodeCpp.js');
const generateShadowNodeH = require('./components/GenerateShadowNodeH.js');
...
const LIBRARY_GENERATORS = {
// TODO: Refactor this to consolidate various C++ output variation instead of forking per platform.
componentsAndroid: [
// JNI/C++ files
generateComponentDescriptorH.generate,
generateEventEmitterCpp.generate,
generateEventEmitterH.generate,
generatePropsCpp.generate,
generatePropsH.generate,
generateShadowNodeCpp.generate,
generateShadowNodeH.generate,
// Java files
generatePropsJavaInterface.generate,
generatePropsJavaDelegate.generate,
],
...
};
...
- 为Turbo JavaModule静态生成
Native**Spec.java和JNI的**Spec.hh和**Spec-generated.cpp - 为Turbo CxxModule静态生成
**SpecJSI.h和**SpecJSI-generated.cpp
// const generateModuleObjCpp = require('./modules/GenerateModuleObjCpp');
const GenerateModuleJavaSpec = require('./modules/GenerateModuleJavaSpec.js');
const GenerateModuleJniCpp = require('./modules/GenerateModuleJniCpp.js');
const GenerateModuleJniH = require('./modules/GenerateModuleJniH.js');
...
const LIBRARY_GENERATORS = {
// TODO: Refactor this to consolidate various C++ output variation instead of forking per platform.
...
modulesAndroid: [
GenerateModuleJniCpp.generate,
GenerateModuleJniH.generate,
generateModuleJavaSpec.generate,
],
modulesCxx: [generateModuleCpp.generate, generateModuleH.generate],
...
};
...
generate for iOS
- 为Fabric Component静态生成
ComponentDescriptor.h、EventEmitter.h/cpp、Props.h/cpp、ShadowNode.h/cpp、RCTComponentViewHelpers.h、RCTThirdPartyFabricComponentsProvider.h/mm
const generateComponentDescriptorH = require('./components/GenerateComponentDescriptorH.js');
const generateComponentHObjCpp = require('./components/GenerateComponentHObjCpp.js');
const generateEventEmitterCpp = require('./components/GenerateEventEmitterCpp.js');
const generateEventEmitterH = require('./components/GenerateEventEmitterH.js');
const generatePropsCpp = require('./components/GeneratePropsCpp.js');
const generatePropsH = require('./components/GeneratePropsH.js');
...
// const generatePropsJavaInterface = require('./components/GeneratePropsJavaInterface.js');
// const generatePropsJavaDelegate = require('./components/GeneratePropsJavaDelegate.js');
...
const generateShadowNodeCpp = require('./components/GenerateShadowNodeCpp.js');
const generateShadowNodeH = require('./components/GenerateShadowNodeH.js');
...
const LIBRARY_GENERATORS = {
// TODO: Refactor this to consolidate various C++ output variation instead of forking per platform.
...
componentsIOS: [
generateComponentDescriptorH.generate,
generateEventEmitterCpp.generate,
generateEventEmitterH.generate,
generateComponentHObjCpp.generate,
generatePropsCpp.generate,
generatePropsH.generate,
generateShadowNodeCpp.generate,
generateShadowNodeH.generate,
],
...
};
...
- 为Turbo ObjcModule静态生成
**Spec.h和**Spec-generated.mm - 为Turbo CxxModule静态生成
**SpecJSI.h和**SpecJSI-generated.cpp
const generateModuleH = require('./modules/GenerateModuleH.js');
const generateModuleCpp = require('./modules/GenerateModuleCpp.js');
const generateModuleObjCpp = require('./modules/GenerateModuleObjCpp');
// const generateModuleJavaSpec = require('./modules/GenerateModuleJavaSpec.js');
// const GenerateModuleJniCpp = require('./modules/GenerateModuleJniCpp.js');
// const GenerateModuleJniH = require('./modules/GenerateModuleJniH.js');
...
const LIBRARY_GENERATORS = {
// TODO: Refactor this to consolidate various C++ output variation instead of forking per platform.
...
modulesCxx: [generateModuleCpp.generate, generateModuleH.generate],
modulesIOS: [generateModuleObjCpp.generate],
...
};
generateFromSchemas for iOS
- 为Fabric Component静态生成
RCTThirdPartyFabricComponentsProvider.h/mm
const generateThirdPartyFabricComponentsProviderObjCpp = require('./components/GenerateThirdPartyFabricComponentsProviderObjCpp.js');
const generateThirdPartyFabricComponentsProviderH = require('./components/GenerateThirdPartyFabricComponentsProviderH.js');
...
const SCHEMAS_GENERATORS = {
providerIOS: [
generateThirdPartyFabricComponentsProviderObjCpp.generate,
generateThirdPartyFabricComponentsProviderH.generate,
],
};
...
module.exports = {
generateFromSchemas(
...
) {
...
const generatedFiles = [];
for (const name of generators) {
for (const generator of SCHEMAS_GENERATORS[name]) {
generatedFiles.push(...generator(schemas));
}
}
...
};
generateViewConfig for JavaScript
- 为Fabric Component静态生成
NativeViewConfig.js
const generateViewConfigJs = require('./components/GenerateViewConfigJs.js');
...
module.exports = {
generateViewConfig({libraryName, schema}: LibraryOptions): string {
schemaValidator.validate(schema);
const result = generateViewConfigJs
.generate(libraryName, schema)
.values()
.next();
...
};
0.70 APP Autolink
0.70官方文档:reactnative.dev/docs/0.70/n…
react-native@0.69.x使用@react-native-community/cli@8.x,Autolink仅生成PackageList.java- 以下基于
react-native@0.70.6对应的@react-native-community/cli@9.3.2 分析
APP Autolink for Android
集成@react-native-community/cli-platform-android的native_modules.gradle,即可
- 根据Autolink生成
PackageList.java、rncli.h/cpp
$ tree ${APP}/android/app/build/generated/rncli/src/main/
├── java
│ └── com
│ └── facebook
│ └── react
│ └── PackageList.java
└── jni
├── Android-rncli.cmake
├── Android-rncli.mk
├── rncli.cpp
└── rncli.h
settings.gradle
示例APP的settings.gradle,github.com/Sunbreak/re…
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
graph TD
setting.gradle -. apply .-> init
subgraph ReactNativeModules
init --> getReactNativeConfig -. init .-> modules[(reactNativeModules)]
addReactNativeModuleProjects -- include --> modules
end
setting.gradle --> applyNativeModulesSettingsGradle --> addReactNativeModuleProjects
- getReactNativeConfig
ArrayList<HashMap<String, String>> getReactNativeConfig() {
...
// node @react-native-community/cli/build/bin.js config
String[] reactNativeConfigCommand = ["node", cliPath, "config"]
// ... 解析reactNativeConfigOutput ...
def dependencies = json["dependencies"]
def project = json["project"]["android"]
...
dependencies.each { name, value ->
...
if (androidConfig != null && androidConfig["sourceDir"] != null) {
...
reactNativeModuleConfig.put("name", name)
...
reactNativeModules.add(reactNativeModuleConfig)
}
...
}
- addReactNativeModuleProjects
void addReactNativeModuleProjects(DefaultSettings defaultSettings) {
reactNativeModules.forEach { reactNativeModule ->
String nameCleansed = reactNativeModule["nameCleansed"]
...
defaultSettings.include(":${nameCleansed}")
...
}
}
build.gradle
示例APP的build.gradle,github.com/Sunbreak/re…
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
graph TD
build.gradle -. apply .-> init
subgraph ReactNativeModules
init --> getReactNativeConfig -. init .-> modules[(reactNativeModules)]
addReactNativeModuleDependencies -- depend --> modules
generatePackagesFile
genNewArch["
generateAndroidMkFile
generateCmakeFile
generateRncliCpp
generateRncliH
"]
end
build.gradle --> applyNativeModulesAppBuildGradle --> addReactNativeModuleDependencies
applyNativeModulesAppBuildGradle --> generatePackageList --> generatePackagesFile
applyNativeModulesAppBuildGradle --> generateNewArchitectureFiles --> genNewArch
- addReactNativeModuleDependencies
void addReactNativeModuleDependencies(Project appProject) {
reactNativeModules.forEach { reactNativeModule ->
...
appProject.dependencies {
if (reactNativeModulesBuildVariants.containsKey(nameCleansed)) {
reactNativeModulesBuildVariants.forEach { buildVariant ->
"${buildVariant}Implementation" project(path: ":${nameCleansed}") // 根据buildVariant依赖project(path: ":${nameCleansed}")
}
} else {
implementation project(path: ":${nameCleansed}") // appProject直接依赖project(path: ":${nameCleansed}")
}
}
}
}
- generatePackagesFile
- 根据
generatedFileContentsTemplate模板生成PackageList.java文件
- 根据
- generateAndroidMkFile
- 根据
androidMkTemplate模板生成Android-rncli.mk文件
- 根据
- generateCmakeFile
- 根据
cmakeTemplate模板生成Android-rncli.cmake文件
- 根据
- generateRncliCpp
- 根据
rncliCppTemplate模板生成rncli.cpp文件
- 根据
- generateRncliH
- 根据
rncliHTemplate模板生成rncli.h文件
- 根据
附录
@react-native/babel-preset
timeline
2016 : babel-preset-react-native
2018 : metro-react-native-babel-preset
2023 : @react-native/babel-preset
Babel presets for React Native applications. React Native itself uses this Babel preset by default when transforming your app's source code.
-
- ReactNative: Use "babel-preset-react-native"
-
metro-react-native-babel-preset
- ReactNative: Move babel-preset-react-native to metro repository