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.h
h和**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