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 和 Expo 非常灵活,可以逐步采用,一次一个屏幕(甚至一次一个视图)。你甚至可能会发现,以这种方式使用 Expo 最适合你的特定应用;或者,你也可能会在应用的更多界面中逐渐采用它。无论哪种方式,这种灵活性都使开发者能够立即在原生应用中采用现代的跨平台工具,而不是冒着完全重写的风险。

本指南将带你了解如何将 React Native 视图添加到现有的原生应用中。这里介绍的方法是我们所说的“集成”方式,因为 React Native 和 Expo 会像集成其他任意库一样被集成进来。

Prerequisites

3 requirements

1.

Node.js (LTS)

安装 Node.js 以运行 JavaScript 代码和 Expo CLI。

2.

Yarn

安装 Yarn 作为 JavaScript 依赖项的包管理器。

3.

CocoaPods
iOS

安装 CocoaPods,这是 iOS 的依赖管理系统之一。 CocoaPods 是一个 Ruby gem,你可以使用随最新版本 macOS 一起提供的 Ruby 版本来安装它。

可从 设置环境指南 了解更多。

创建 Expo 项目

首先,在现有原生项目的根目录内创建一个 Expo 项目。

Terminal
npx create-expo-app@latest my-project --template default@sdk-57

此命令会创建一个名为 my-project 的新目录,其中包含你的新 Expo 项目。虽然你可以将项目命名为任何名称,但为了保持一致,本指南使用 my-project。新项目包含一个示例 TypeScript 应用,帮助你快速上手。

设置项目结构

标准的 React Native 项目会将原生代码放在 androidios 目录中。具体如何操作取决于你的项目,但最简单的情况可能只是创建这些目录并将你的项目移过去。例如:

Terminal
mkdir my-project/android
mv /path/to/your/android-project my-project/android/
无法将你的原生项目移动到 android 和 ios 目录?

设置 monorepo

Monorepo(或称“单体代码仓库”)是包含多个应用或软件包的单个代码仓库。请参阅如何使用 monorepo

设置 monorepo 将确保即使在自定义文件夹结构下,Android 和 iOS 脚本也能够调用 Node 库中的命令。要设置 Yarn monorepo,请在项目根目录创建一个 package.json 文件,并添加以下内容:

package.json
{ "version": "1.0.0", "private": true, "workspaces": ["my-project"] }

然后运行 yarn install 来安装依赖。这将确保 node_modules 安装在项目根目录,并且原生脚本可以与 React Native 代码交互。请务必将 ["my-project"] 改为你在上一步创建的 Expo 项目名称。

配置你的原生项目

要在 Android 上集成 React Native,你需要通过修改以下文件来配置原生项目:

  • Gradle 文件settings.gradle、顶层 build.gradleapp/build.gradlegradle.properties,用于添加 React Native Gradle Plugin(RNGP)及其他属性。
  • AndroidManifest.xml:用于添加必要权限。(了解更多
  • MainActivity:用于加载你的 React Native 应用。

配置 Gradle

1

首先编辑你的 settings.gradle 文件,并添加以下行(可参考 最小模板):

settings.gradle
// 为自动链接配置 React Native Gradle Settings 插件 pluginManagement { def reactNativeGradlePlugin = new File( providers.exec { workingDir(rootDir) commandLine("node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })") }.standardOutput.asText.get().trim() ).getParentFile().absolutePath includeBuild(reactNativeGradlePlugin) def expoPluginsPath = new File( providers.exec { workingDir(rootDir) commandLine("node", "--print", "require.resolve('expo-modules-autolinking/package.json', { paths: [require.resolve('expo/package.json')] })") }.standardOutput.asText.get().trim(), "../android/expo-gradle-plugin" ).absolutePath includeBuild(expoPluginsPath) } plugins { id("com.facebook.react.settings") id("expo-autolinking-settings") } extensions.configure(com.facebook.react.ReactSettingsExtension) { ex -> ex.autolinkLibrariesFromCommand(expoAutolinking.rnConfigCommand) } expoAutolinking.useExpoModules() // rootProject.name = 'HelloWorld' expoAutolinking.useExpoVersionCatalog() includeBuild(expoAutolinking.reactNativeGradlePlugin) // 在这里包含你现有的 Gradle 模块。 // include(":app")
使用自定义文件夹结构?

如果你使用的是自定义文件夹结构,那么为了让自动链接正常工作,你需要在 settings.gradle 中显式设置项目根目录。请修改以下行:

2

然后打开顶层 build.gradle 并包含这一行(如 最小模板 所示):

这可以确保 React Native Gradle 和 Expo 插件在你的项目中可用并被应用。

3

将以下行添加到你应用的 build.gradle 文件中(通常是 app/build.gradle — 你可以参考 最小模板文件):

使用自定义文件夹结构?

如果你使用的是自定义文件夹结构,那么你需要在 app/build.gradle 中调整 projectRoot 的值,使其指向你的 Expo 项目根目录。请修改以下行:

4

最后,打开你应用的 gradle.properties 文件,并添加以下几行(可参考 最小模板文件):

gradle.properties
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 newArchEnabled=true hermesEnabled=true

配置你的 manifest

1

首先,确保你的 AndroidManifest.xml 中包含 INTERNET 权限:

2

现在,在你的 debug AndroidManifest.xml 中启用 明文流量

这是让你的应用通过 HTTP 与本地 Metro bundler 通信所必需的。你可以将最小模板中的 AndroidManifest.xml 文件作为参考:调试

将其与你的代码集成

现在,你需要添加一些原生代码来启动 React Native 运行时,并告诉它渲染你的 React 组件。

更新你的 Application

先更新你的 Application 类以初始化 React Native。你可以参考 最小模板 中的 MainApplication.kt

创建一个 ReactActivity

创建一个新的 Activity,让它继承 ReactActivity 并承载 React Native 代码。这个 Activity 将负责启动 React Native 运行时并渲染 React 组件。你可以参考 最小模板中的 MainActivity.kt

MyReactActivity.kt
// package <your-package-here> import android.os.Build import com.facebook.react.ReactActivity import com.facebook.react.ReactActivityDelegate import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled import com.facebook.react.defaults.DefaultReactActivityDelegate import expo.modules.ReactActivityDelegateWrapper class MyReactActivity : ReactActivity() { /** * 返回从 JavaScript 注册的主组件名称。该名称用于安排 * 组件的渲染。 */ override fun getMainComponentName(): String = "main" /** * 返回 [ReactActivityDelegate] 的实例。我们使用 [DefaultReactActivityDelegate] *,它允许你通过一个布尔标志 [fabricEnabled] 启用新架构 */ override fun createReactActivityDelegate(): ReactActivityDelegate { return ReactActivityDelegateWrapper( this, BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, object : DefaultReactActivityDelegate( this, mainComponentName, fabricEnabled ){}) } }

将这个新的 Activity 添加到你的 AndroidManifest.xml 文件中,并确保将 MyReactActivity 的主题设置为 Theme.AppCompat.Light.NoActionBar(或任何不带 ActionBar 的主题),以避免你的应用在 React Native 屏幕上方渲染一个 ActionBar

现在你的 Activity 已准备好运行一些 JavaScript 代码。

测试你的集成

你已经完成了将 React Native 与你的应用集成所需的所有基本步骤。现在,在 React Native 目录中运行以下命令以启动 Metro 打包器

Terminal
npm run start

Metro 会将你的 TypeScript 应用代码构建成一个 bundle,通过其 HTTP 服务器提供该 bundle,并将开发环境中 localhost 上的 bundle 共享到模拟器或设备,从而支持 热重载。现在你可以像往常一样构建并运行你的应用。一旦你在应用中进入由 React 驱动的 Activity,它就应该从开发服务器加载 JavaScript 代码。