This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
如何使用隔离方法将 Expo 添加到原生应用
编辑页面
一份关于将 Expo 和 React Native 作为原生库添加,并使用隔离方法将其集成到现有(brownfield)原生应用中的指南。
在隔离式方案中,你的 React Native 代码是独立于原生项目进行开发和维护的。你将其打包为原生库,Android 使用 AAR,iOS 使用 XCFramework,并像其他依赖一样将其集成到原生应用中。
当你希望尽量减少 React Native 对现有原生构建流程的影响,或者原生开发与 React Native 开发由不同团队负责时,这种方案最为理想。使用这种方案后,原生开发者不需要 Node.js、Yarn 或任何 React Native 构建工具链,他们只需使用已经构建好的产物即可。
信息 如果你想了解另一种将 React Native 直接集成到原生项目中的方案,请参阅 集成式方案指南。
2 requirements
2 requirements
更多信息请参阅 环境搭建指南。
设置 Expo 项目
1
2
3
调整配置插件(可选)
expo-brownfield 应会自动使用默认配置在你的 app.json 中的 plugins 数组里添加一项,这对于大多数项目来说已经足够。
{ "expo": { "plugins": ["expo-brownfield"] } }
默认值会根据你的应用配置推导而来(例如,目标名称会基于应用的 scheme 或 slug)。你也可以传入选项来自定义目标名称、包标识符和发布配置。
自定义 expo-brownfield 配置
{ "expo": { "plugins": [ [ "expo-brownfield", { "ios": { "targetName": "MyBrownfield", "bundleIdentifier": "com.example.mybrownfield" }, "android": { "libraryName": "mybrownfield", "group": "com.example", "package": "com.example.mybrownfield", "version": "1.0.0" } } ] ] } }
有关所有可用选项的详细信息,请参阅 expo-brownfield API 参考。
将 Expo 项目导出为原生库
完成 Expo 项目设置后,使用 expo-brownfield CLI 将你的 React Native 代码构建为 Android 的 AAR 和 iOS 的 XCFramework。
在你的 Expo 项目目录中运行:
- npx expo-brownfield build:android这会构建 AAR 并将其发布到 Maven 仓库。默认情况下,它会发布到你的本地 Maven 仓库(~/.m2),但也可以配置为发布到远程仓库。
生成的产物名称将由你的配置插件设置决定,在这个例子中是 com.username.myproject:brownfield:1.0.0。
有关构建选项的更多详情,请参阅 API 参考,例如仅构建 debug 或 release、指定自定义输出目录等。
在你的 Expo 项目目录中运行:
- npx expo-brownfield build:ios这会构建 XCFramework 产物:为设备和模拟器架构分别编译 framework 目标,将它们打包为 XCFramework,并复制 Hermes 引擎 framework。
构建过程完成后,输出会放在 ./artifacts 目录中,并包含:
- {TargetName}.xcframework - 你的 Expo 项目作为原生库
- hermesvm.xcframework - Hermes JavaScript 引擎
有关构建选项的更多详情,请参阅 expo-brownfield API 参考,例如仅构建 debug 或 release、指定自定义输出目录等。
将产物作为 Swift 包发布
传入 --package [name] 标志,可以将构建输出打包为一个独立的 Swift 包,而不是分别生成 .xcframework 目录。然后,你可以在 Xcode 中将其作为本地依赖添加到宿主应用,而不是手动将 framework 拖入项目。
- npx expo-brownfield build:ios --release --package MyAppPackage该标志接受一个可选名称。如果省略,包默认命名为 {TargetName}Artifacts。生成的目录是一个完整的 Swift 包,其结构如下:
artifactsMyAppPackagePackage.swiftxcframeworksMyAppPackage.xcframeworkhermesvm.xcframeworkReact.xcframeworkReactNativeDependencies.xcframework调试原生目标
如果你需要调试 Expo 项目目标的原生代码,可以运行 npx expo prebuild 来生成带有 brownfield 库目标的原生项目,位于 android 和 ios 目录中。
- npx expo prebuild上述命令会生成以下内容:
- Android:一个单独的库模块,包含
ReactNativeHostManager、BrownfieldActivity、ReactNativeFragment、ReactNativeViewFactory和BrownfieldMessaging。 - iOS:一个单独的 Xcode framework 目标,包含
ReactNativeHostManager、ReactNativeViewController、ReactNativeView(SwiftUI)、BrownfieldMessaging和ReactNativeDelegate。
集成到你的原生应用中
在构建好产物后,你现在可以将它们集成到现有原生应用中。具体步骤将取决于你的项目结构和构建系统,但整体流程包括将预构建产物作为依赖添加进去,并初始化 React Native host。
1
添加 Maven 依赖
首先将依赖添加到你的应用 build.gradle.kts 中。group、artifact 名称和版本应与你的配置插件设置一致:
dependencies { implementation("com.username.myproject:brownfield:1.0.0") }
如果该库是发布到本地 Maven,请确保在仓库配置中添加 mavenLocal():
dependencyResolutionManagement { repositories { google() mavenCentral() mavenLocal() } }
2
显示 React Native 页面
创建一个继承自 BrownfieldActivity 的 activity,并使用 showReactNativeFragment() 扩展方法:
import android.os.Bundle import com.example.brownfield.BrownfieldActivity import com.example.brownfield.showReactNativeFragment class ExpoActivity : BrownfieldActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) showReactNativeFragment() } }
在你的 AndroidManifest.xml 中添加该 activity,并使用一个非 ActionBar 主题:
<activity android:name=".ExpoActivity" android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" />
然后在应用中的任意位置启动它:
startActivity(Intent(this, ExpoActivity::class.java))
BrownfieldActivity 继承自 AppCompatActivity,并负责将配置变化转发给 Expo 模块。showReactNativeFragment() 扩展方法也会自动配置原生返回按钮处理。
1
将产物添加到项目中
集成步骤取决于你构建的是 XCFramework 还是 Swift 包。
将两个 XCFramework 文件({TargetName}.xcframework 和 hermesvm.xcframework)拖入 Xcode 项目导航器。在弹出的对话框中:
- 勾选 复制项目所需的项目
- 将它们添加到你的 app target
然后,在你的 target 的 常规 选项卡中,找到 框架、库和嵌入内容,确保这两个 framework 都设置为 嵌入并签名。
当 build:ios 生成 Swift 包时(例如 ./artifacts/MyAppPackage-release),在 Xcode 中将其作为本地依赖添加到宿主应用,并选择该包目录。Xcode 会通过聚合库产品自动链接捆绑的 .xcframework 文件。
若要同时支持 --debug 和 --release,请让宿主应用针对每种构建配置指向相应的包。
2
初始化 React Native
在应用生命周期的早期调用 ReactNativeHostManager.shared.initialize()。一个合适的位置是你的 AppDelegate:
import UIKit import MyAppBrownfield // 将其替换为你的 target 名称 @main class AppDelegate: UIResponder, UIApplicationDelegate { func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { ReactNativeHostManager.shared.initialize() return true } }
3
展示 React Native 视图
import UIKit import MyAppBrownfield class ViewController: UIViewController { @IBAction func openReactNative(_ sender: Any) { let rnViewController = ReactNativeViewController(moduleName: "main") navigationController?.pushViewController(rnViewController, animated: true) } }
ReactNativeViewController 也接受可选的 initialProps 和 launchOptions 参数:
let rnViewController = ReactNativeViewController( moduleName: "main", initialProps: ["userId": "123"], launchOptions: [:] )
import SwiftUI import MyAppBrownfield struct ContentView: View { @State private var showReactNative = false var body: some View { Button("打开 React Native") { showReactNative = true } .fullScreenCover(isPresented: $showReactNative) { ReactNativeView(moduleName: "main") } } }
测试你的集成
你已经完成了将 React Native 集成到应用中的所有基础步骤。现在是时候测试一下了。具体流程取决于你运行的是 debug 还是 release 构建。
开发(debug 构建)
现在在 React Native 目录中运行以下命令,以启动 Metro bundler
- npx expo start然后,从 Android Studio 或 Xcode 构建并运行原生应用。当你进入 React Native 屏幕时,它会从 Metro 开发服务器加载,并支持热重载。
生产(release 构建)
在 release 构建中,JavaScript bundle 会嵌入到产物(AAR 或 XCFramework)中,因此不需要 Metro 服务器。以 Release 配置构建原生应用,并确认 React Native 屏幕能够正确加载。
下一步
为 Expo 模块配置应用生命周期监听器,以实现更深度的集成。
探索用于通信、导航等功能的完整 JavaScript API。