React Native 鸿蒙环境搭建完整实战:从 RN 工程到 RNOH 运行
React Native 鸿蒙环境搭建完整实战:从 RN 工程到 RNOH 运行
React Native 跑鸿蒙不是“装完 Node 再创建一个 RN 项目”这么简单。真正容易出错的地方在中间链路:hdc 找不到设备、RNOH_C_API_ARCH 没配、RN 侧没有生成 bundle.harmony.js、鸿蒙侧没有接入 RNOH 的 C++ 和 ArkTS 代码、RNApp 的 appKey 和 RN 入口不一致。任何一处错了,最后表现都可能是白屏、编译失败或设备连不上。

本文结合 CPF-RN 官方环境搭建文档和一篇实操文章整理,目标是把一条可理解、可排查的 React Native 鸿蒙搭建链路写清楚。官方文档中依赖版本使用 x.x.x 占位,实操文章采用了 React Native 0.72.5、@react-native-oh/react-native-harmony@0.72.53、@rnoh/react-native-openharmony@0.72.53 这一组示例。实际项目应以官方发布版本、团队锁定版本和当前工程模板为准,不要把示例版本机械套到所有项目。


1. 先理解 RN 鸿蒙的两段工程
React Native 鸿蒙一般会同时涉及两个工程视角:RN 侧生成 JS bundle,鸿蒙侧通过 RNOH 容器加载 bundle 并运行。
| 部分 | 负责内容 | 常见文件 |
|---|---|---|
| RN 工程 | JS/TS 业务代码、Metro、bundle 生成 | package.json、metro.config.js、App.tsx |
| 鸿蒙工程 | DevEco 构建、RNOH 容器、C++ 适配层 | entry、Index.ets、CMakeLists.txt |
| RNOH 依赖 | RN 和 OpenHarmony 的桥接层 | @react-native-oh/*、@rnoh/* |
| bundle 资源 | RN 运行入口产物 | bundle.harmony.js、assets |
这也是为什么只创建 RN 工程不够,必须把 RN 侧产物接入鸿蒙侧。
2. 准备 Node、DevEco Studio 和 SDK
先安装 Node.js,并确认 node 和 npm 可用。
node -v
npm -v
代码解释:
node -v用来确认 Node 已安装。npm -v用来确认 npm 可用。- 如果命令不存在,先修 Node 环境,不要继续执行 RN 初始化。
然后安装 DevEco Studio,并在 IDE 内完成 SDK 下载和环境配置。官方文档强调 DevEco Studio 开发环境依赖网络环境,首次配置时要保持网络可用。
DevEco Studio -> SDK Manager -> 安装 OpenHarmony SDK 与工具链
说明:
- DevEco Studio 负责鸿蒙工程创建、构建和运行。
- OpenHarmony SDK 中的
toolchains目录提供hdc。 - 实操文章提到 DevEco Studio API 版本要大于 13;官方文档创建示例工程时使用
Compile SDK API13。如果你使用更新模板,应以当前 RNOH 版本支持范围和项目要求为准。
3. 配置 hdc 和端口
hdc 是 OpenHarmony 调试工具,React Native 鸿蒙工程真机调试也会用到它。官方文档要求把 SDK 下的 openharmony/toolchains 加到环境变量。
Windows 示例:
{DevEco Studio安装路径}/sdk/{SDK版本}/openharmony/toolchains
HDC_SERVER_PORT=7035
代码解释:
toolchains要写完整真实路径。HDC_SERVER_PORT可以设置为未被占用端口,官方示例和实操文章都使用7035。- 配置完建议重新打开终端。
Mac 示例:
export PATH="/Applications/DevEco-Studio.app/Contents/sdk/{版本路径}/openharmony/toolchains:$PATH"
export HDC_SERVER_PORT=7035
launchctl setenv HDC_SERVER_PORT $HDC_SERVER_PORT
代码解释:
- Mac 路径要按 DevEco Studio 实际安装位置替换。
launchctl setenv可以让图形应用也拿到端口变量。- 如果团队已经约定其他端口,按团队配置来。
验证:
hdc -v
hdc list targets
代码解释:
hdc -v能输出版本,说明 PATH 生效。hdc list targets能看到设备或模拟器,说明连接链路基本可用。
4. 配置 CAPI 架构变量
官方文档说明,当前 RN 框架提供的 Demo 工程默认为 CAPI 版本,需要配置:
RNOH_C_API_ARCH=1
Windows 在系统环境变量中新建:
变量名:RNOH_C_API_ARCH
变量值:1
Mac 或 Linux:
export RNOH_C_API_ARCH=1
echo $RNOH_C_API_ARCH
代码解释:
- 这个变量影响 RNOH CAPI 架构相关构建。
echo输出1才说明当前终端已经生效。- 如果 DevEco Studio 从桌面启动,Mac 还要注意 IDE 进程是否拿到了环境变量。
5. 创建 React Native 工程
实操文章使用 RN 0.72.5。官方文档也以 0.72.5 命令为示例。
npx react-native@0.72.5 init AwesomeProject --version 0.72.5 --skip-install
cd AwesomeProject
npm install
代码解释:
--version 0.72.5锁定 RN 版本。--skip-install可以先生成工程,再手动控制依赖安装。- 如果你不想跳过安装,也可以使用官方普通初始化命令。
确认 package.json 中 RN 版本:
{
"dependencies": {
"react-native": "0.72.5"
}
}
代码解释:
- RN 版本要和鸿蒙化依赖版本匹配。
- 不建议 RN 主版本随意升级后继续使用旧 RNOH 包。
6. 安装鸿蒙化 RN 依赖
官方文档使用占位版本:
npm i @react-native-oh/react-native-harmony@x.x.x
实操文章给出的具体示例是:
npm i @react-native-oh/react-native-harmony@0.72.53
代码解释:
@react-native-oh/react-native-harmony用于 RN 侧适配 OpenHarmony。- 官方文档中的
x.x.x应替换为当前官方发布版本。 - 如果你采用
0.72.5RN,实操文章的0.72.53是一个可参考组合,但仍建议以官方 release 和项目模板为准。
7. 配置 metro.config.js 并生成 bundle
RN 侧要让 Metro 知道 Harmony 目标。官方和实操文章都给出了类似配置。
const {mergeConfig, getDefaultConfig} = require('@react-native/metro-config');
const {createHarmonyMetroConfig} = require('@react-native-oh/react-native-harmony/metro.config');
const config = {
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: true,
},
}),
},
};
module.exports = mergeConfig(
getDefaultConfig(__dirname),
createHarmonyMetroConfig({
reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony',
}),
config,
);
代码解释:
createHarmonyMetroConfig是 Harmony 目标的关键配置。reactNativeHarmonyPackageName要和安装的包名一致。- 这段配置建议整体替换原
metro.config.js后再运行 bundle 命令。
在 package.json 的 scripts 中加入:
{
"scripts": {
"dev": "react-native bundle-harmony --dev"
}
}
执行:
npm run dev
代码解释:
- 成功后会生成
bundle.harmony.js。 - 生成目录通常在
harmony/entry/src/main/resources/rawfile。 - 如果报
'react-native' 不是内部或外部命令,先重新执行npm install。
8. 创建或准备鸿蒙工程
官方文档建议新建工程或在已有工程中集成。创建新工程时,示例使用 Compile SDK API13,项目名示例为 MyApplication。
DevEco Studio -> New Project -> Empty Ability -> Compile SDK API13
说明:
- API13 是官方文档示例,不代表所有版本都只能用 API13。
- 项目路径不要太长,Windows 下尤其容易因为路径和构建缓存导致问题。
- 新建后等待 IDE 的 SyncData、ohpm install 等动作完成。
进入鸿蒙工程的 entry 目录安装 RNOH 依赖:
ohpm i @rnoh/react-native-openharmony@0.72.53
代码解释:
- 官方文档写法是
@x.x.x,实操文章示例为0.72.53。 @rnoh/react-native-openharmony是鸿蒙侧 RNOH 容器依赖。- har 包较大,必须等
ohpm install和 IDE 同步完成。
9. 补充 C++ 适配层
在 entry/src/main 下新建 cpp 目录,并添加 CMakeLists.txt。
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(OH_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../oh_modules")
set(RNOH_APP_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(RNOH_CPP_DIR "${OH_MODULE_DIR}/@rnoh/react-native-openharmony/src/main/cpp")
set(RNOH_GENERATED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/generated")
set(CMAKE_ASM_FLAGS "-Wno-error=unused-command-line-argument -Qunused-arguments")
set(CMAKE_CXX_FLAGS "-fstack-protector-strong -Wl,-z,relro,-z,now,-z,noexecstack -s -fPIE -pie")
add_compile_definitions(WITH_HITRACE_SYSTRACE)
set(WITH_HITRACE_SYSTRACE 1)
add_subdirectory("${RNOH_CPP_DIR}" ./rn)
add_library(rnoh_app SHARED
"./PackageProvider.cpp"
"${RNOH_CPP_DIR}/RNOHAppNapiBridge.cpp"
)
target_link_libraries(rnoh_app PUBLIC rnoh)
代码解释:
RNOH_CPP_DIR指向 ohpm 安装后的 RNOH C++ 目录。add_subdirectory把 RNOH 适配层加入构建。rnoh_app是官方要求的 so 命名,自定义 CMake 时也要注意名称。
新增 PackageProvider.cpp:
#include "RNOH/PackageProvider.h"
using namespace rnoh;
std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
return {};
}
代码解释:
- 没有自定义 TurboModule 或 Fabric 组件时返回空数组。
- 后续接三方库或自定义模块时,在这里补 package。
10. 修改 build-profile.json5
打开 entry/build-profile.json5,把 C++ 构建接入模块构建。
{
"buildOption": {
"externalNativeOptions": {
"path": "./src/main/cpp/CMakeLists.txt",
"arguments": "",
"cppFlags": ""
}
}
}
代码解释:
path指向刚才新增的 CMakeLists。- 如果运行 x86_64 架构模拟器,官方文档提示可能需要额外配置
abiFilters并包含x86_64。 - 默认通常面向
arm64-v8a,真机调试时更常见。
11. 补充 ArkTS 入口代码
把 EntryAbility.ets 改为继承 RNAbility。
import { RNAbility } from '@rnoh/react-native-openharmony';
export default class EntryAbility extends RNAbility {
getPagePath() {
return 'pages/Index';
}
}
代码解释:
RNAbility内部处理了 RNOH 运行需要的生命周期逻辑。- 如果你重写生命周期函数,要调用
super,避免 RNOH 原有逻辑丢失。 getPagePath返回 ArkTS 入口页面路径。
新增 entry/src/main/ets/RNPackagesFactory.ets:
import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
return [];
}
代码解释:
- 没有三方库、自定义 TurboModule 或 Fabric 组件时返回空数组。
- 后续接原生模块时从这里扩展。
12. 在 Index.ets 中创建 RNApp
Index.ets 是 RNOH 运行 RN bundle 的关键位置。最容易出错的是 appKey,它必须和 RN 侧 AppRegistry.registerComponent 注册的名字一致。
import {
AnyJSBundleProvider,
ComponentBuilderContext,
FileJSBundleProvider,
MetroJSBundleProvider,
ResourceJSBundleProvider,
RNApp,
RNOHErrorDialog,
RNOHLogger,
TraceJSBundleProviderDecorator,
RNOHCoreContext
} from '@rnoh/react-native-openharmony';
import { createRNPackages } from '../RNPackagesFactory';
@Builder
export function buildCustomRNComponent(ctx: ComponentBuilderContext) {}
const wrappedCustomRNComponentBuilder = wrapBuilder(buildCustomRNComponent);
@Entry
@Component
struct Index {
@StorageLink('RNOHCoreContext') private rnohCoreContext: RNOHCoreContext | undefined = undefined;
@State shouldShow: boolean = false;
private logger!: RNOHLogger;
aboutToAppear() {
this.logger = this.rnohCoreContext!.logger.clone('Index');
this.shouldShow = true;
}
onBackPress(): boolean | undefined {
this.rnohCoreContext!.dispatchBackPress();
return true;
}
build() {
Column() {
if (this.rnohCoreContext && this.shouldShow) {
if (this.rnohCoreContext.isDebugModeEnabled) {
RNOHErrorDialog({ ctx: this.rnohCoreContext });
}
RNApp({
rnInstanceConfig: {
createRNPackages,
enableNDKTextMeasuring: true,
enableBackgroundExecutor: false,
enableCAPIArchitecture: true,
arkTsComponentNames: []
},
initialProps: { foo: 'bar' } as Record<string, string>,
appKey: 'AwesomeProject',
wrappedCustomRNComponentBuilder,
jsBundleProvider: new TraceJSBundleProviderDecorator(
new AnyJSBundleProvider([
new MetroJSBundleProvider(),
new FileJSBundleProvider('/data/storage/el2/base/files/bundle.harmony.js'),
new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'bundle.harmony.js')
]),
this.rnohCoreContext.logger
)
});
}
}
.height('100%')
.width('100%');
}
}
代码解释:
enableCAPIArchitecture: true要和前面的RNOH_C_API_ARCH=1对齐。appKey: 'AwesomeProject'要和 RN 侧AppRegistry.registerComponent的 appName 一致。MetroJSBundleProvider适合开发阶段从 Metro 加载。ResourceJSBundleProvider适合从 rawfile 资源加载bundle.harmony.js。FileJSBundleProvider适合从应用沙箱路径加载 bundle。
RN 侧入口通常类似:
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
代码解释:
- 如果
app.json里的 name 是AwesomeProject,ArkTS 侧appKey也要写AwesomeProject。 - appKey 不一致是白屏高发原因。
13. 加载 bundle 并运行
RN 侧生成 bundle 后,通常会有:
AwesomeProject/harmony/entry/src/main/resources/rawfile/bundle.harmony.js
AwesomeProject/harmony/entry/src/main/resources/rawfile/assets
把 bundle.harmony.js 和 assets 拷贝到鸿蒙工程:
MyApplication/entry/src/main/resources/rawfile/
代码解释:
- 如果使用
ResourceJSBundleProvider,bundle 要放在 rawfile。 - 如果 bundle 中包含本地图片,
assets也要一起拷贝。 - 如果使用
FileJSBundleProvider,可以通过 hdc 把 bundle 推送到应用沙箱。
hdc 推送示例:
hdc file send ./bundle.harmony.js /data/storage/el2/base/files/bundle.harmony.js
代码解释:
- 目标路径要和
FileJSBundleProvider中配置的路径一致。 - 沙箱路径可能随应用和系统环境不同而变化,按设备实际路径确认。
最后用 DevEco Studio 运行鸿蒙工程。运行成功后,RN 页面应出现在鸿蒙应用中。
14. 常见问题和处理方式
| 现象 | 高概率原因 | 处理方式 |
|---|---|---|
| hdc 找不到 | toolchains 没加 PATH | 重新配置 SDK toolchains 路径 |
| 设备列表为空 | 端口或设备连接问题 | 检查 HDC_SERVER_PORT、模拟器、真机授权 |
| C++ 编译失败 | CMakeLists 或 ohpm 依赖没同步 | 等 IDE 同步完成,检查 OH_MODULE_DIR |
| 启动白屏 | appKey 不匹配或 bundle 没加载 |
对齐 AppRegistry 和 RNApp appKey |
| 找不到 bundle | rawfile 没拷贝或路径不一致 | 确认 bundle.harmony.js 位置 |
| CAPI 相关错误 | RNOH_C_API_ARCH 未配置 |
设置为 1 并重启终端/IDE |
| ohpm 安装很慢 | har 包较大或网络差 | 保持网络稳定,等待 SyncData 完成 |
15. 最终验证清单
node -v、npm -v正常。- DevEco Studio 已安装,并能创建鸿蒙工程。
- OpenHarmony SDK toolchains 已加入 PATH。
HDC_SERVER_PORT已配置,示例值为7035。hdc list targets能看到设备或模拟器。RNOH_C_API_ARCH=1生效。- RN 工程使用的 RN 版本与鸿蒙化依赖版本匹配。
metro.config.js已接入createHarmonyMetroConfig。npm run dev能生成bundle.harmony.js。- 鸿蒙工程已安装
@rnoh/react-native-openharmony。 - C++ 侧有
CMakeLists.txt和PackageProvider.cpp。 build-profile.json5已接入 CMake。EntryAbility继承RNAbility。Index.ets中RNApp appKey和 RN 侧 appName 一致。- rawfile 或沙箱路径中能找到 bundle。
- DevEco Studio 能正常运行鸿蒙工程。
16. 总结
React Native 鸿蒙环境搭建的核心是把三条线对齐:工具链线、RN 线、鸿蒙 RNOH 线。工具链线解决 DevEco、SDK、hdc 和 CAPI;RN 线解决 React Native 版本、Metro 配置和 bundle;鸿蒙 RNOH 线解决 ohpm 依赖、C++ 适配层、ArkTS 入口和 RNApp 加载。只要按这个顺序推进,遇到问题时就能快速判断是设备连接、bundle 生成、C++ 构建还是 appKey 配置出错。
参考出处
本文结合以下两篇资料整理:
- CPF-RN 官方文档:
https://gitcode.com/CPF-RN/ohos_react_native/blob/master/docs/zh-cn/环境搭建.md?isLogin=1 - CSDN 实操文章:
https://blog.csdn.net/m0_65369051/article/details/147123793
更多推荐


所有评论(0)