React Native 跑在 HarmonyOS NEXT 上:RNOH 环境搭建与首个页面运行
本文介绍了《React Native x HarmonyOS NEXT 创新能力接入方案》系列的第一部分,重点讲解了如何搭建React Native(RN)与HarmonyOS NEXT(RNOH)的开发环境。文章详细说明了技术架构,包括RN业务层、RNOH桥接层和HarmonyOS原生层的分工,并指导开发者完成环境准备、创建RN项目、引入HarmonyOS工程等步骤。通过运行示例项目,验证了RN
本文是《React Native x HarmonyOS NEXT 创新能力接入方案》系列第 1 篇。
本篇先完成 RNOH 环境搭建,并让一个 React Native 页面运行在 HarmonyOS 设备上,为后续接入 TTS、OCR、端侧 AI、桌面卡片等能力打基础。
源码: https://atomgit.com/huqi/RNHarmonySkuAssistant
发布成熟度
| 项目 | 状态 |
|---|---|
| 当前成熟度 | 工程桥接 |
| 资料核验时间 | 2026-06-04 |
| 是否代表真实 Kit 完整接入 | 否,除非本文后续补充真机截图、权限配置和真实 API 调用日志 |
| 发布前必须补齐 | 真实设备型号、SDK 版本、权限配置、构建日志、调用日志、截图 |
1. 本篇要实现什么?
本篇目标:
启动 Metro
↓
DevEco Studio 编译 HarmonyOS 工程
↓
安装到鸿蒙设备 / 模拟器
↓
页面显示 React Native 渲染的 SKU 助手首页
后续页面可以做成:
RN Harmony SKU Assistant
商品识别
商品图处理
卖点播报
库存预警
这一步的意义不是页面多复杂,而是证明:
React Native 页面已经成功跑在 HarmonyOS 上。
2. 为什么需要 RNOH?
React Native 适配 HarmonyOS NEXT 不是把 Android 包直接安装过去,而是需要 HarmonyOS 原生工程承载 React Native 运行时。
整体链路是:
React Native JS 代码
↓
RNOH 运行时
↓
HarmonyOS 原生工程
↓
OpenHarmony / HarmonyOS NEXT 设备
3. 技术架构说明
本系列整体架构如下:
RN Harmony SKU Assistant
├── React Native 业务层
│ ├── 页面
│ ├── 组件
│ ├── 状态管理
│ └── JS/TS 调用封装
│
├── RNOH 桥接层
│ ├── TurboModule
│ ├── Codegen
│ ├── JS ↔ ArkTS 通信
│ └── 原生模块注册
│
└── HarmonyOS 原生层
├── ArkTS
├── HarmonyOS Kit
├── 权限处理
└── 系统能力调用
第 1 篇只处理:
React Native 页面
↓
RNOH 承载
↓
HarmonyOS 工程运行
4. 开发环境准备
建议准备:
Node.js
pnpm / yarn / npm
React Native
DevEco Studio
HarmonyOS SDK
RNOH
鸿蒙模拟器或真机
建议在文章中记录版本信息:
| 项目 | 当前环境 |
|---|---|
| Node.js | 22.x |
| React Native | 示例为 0.84.1;实际以 RNOH 版本匹配表为准 |
| RNOH | 示例为本地源码依赖;实际以 AtomGit release/tag 与版本说明为准 |
| DevEco Studio | 6.1.1 Release |
| HarmonyOS SDK | 6.1.1(24) / 6.1.0(23) |
| 运行设备 | HarmonyOS 6.1 模拟器/真机 |
实测补充:下表中的
0.84.1是本文写作时的示例环境,不代表读者必须使用的最新版本。请先核对 AtomGitOpenHarmony-RN/ohos_react_native的 release/tag、docs/zh-cn/05-运维/版本说明.md与 React Native 版本匹配关系。若目标版本未发布 npm 包,可采用本地源码依赖方式接入。源码目录可放在项目同级目录:HarmonyOS/code ├── RNHarmonySkuAssistant └── ohos_react_native
4.1 资料核验与版本口径
本文中的版本表只记录作者当次验证环境,不等同于“最新版本推荐”。正式搭建前建议按下面顺序核验:
1. RNOH 仓库主页:OpenHarmony-RN/ohos_react_native
2. docs/zh-cn/README.md 应用开发者入口
3. docs/zh-cn/05-运维/版本说明.md
4. docs/zh-cn/05-运维/版本升级指导.md
5. 当前 release / tag 与 React Native 版本匹配关系
如果文章、截图和仓库当前 README 出现差异,以仓库文档和实际下载的 SDK / npm 包为准。
5. 创建 React Native 项目
npx @react-native-community/cli@latest init RNHarmonySkuAssistant --version <matched-rn-version>
# or 跳过 ios 等依赖的安装
# npx @react-native-community/cli@latest init AwesomeProject --version <matched-rn-version> --skip-install
cd RNHarmonySkuAssistant
npm start
或:
yarn start
我们先确认 React Native 项目可以运行:

6. 引入 HarmonyOS 工程
- 打开
RNHarmonySkuAssistant目录下的package.json,在scripts下新增 OpenHarmony 的依赖:
"name": "RNHarmonySkuAssistant",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"lint": "eslint .",
"start": "react-native start",
"test": "jest",
+ "harmony": "react-native bundle-harmony --dev"
},
-
安装鸿蒙依赖:
# 如果目标 RNOH 版本未发布 npm 包,可通过源码方式安装依赖;具体版本以官方版本说明为准 # npm install @react-native-oh/react-native-harmony@<matched-version> @react-native-oh/react-native-harmony-cli --legacy-peer-deps# 下载源码,建议放在 RN 项目同级目录 cd .. git clone https://atomgit.com/OpenHarmony-RN/ohos_react_native cd RNHarmonySkuAssistant npm install \ file:../ohos_react_native/packages/react-native-harmony \ file:../ohos_react_native/packages/react-native-harmony-cli \ --legacy-peer-deps # 甚至我们可以通过 atomcode 来辅助安装
-
运行指令并生成bundle
打开
RNHarmonySkuAssistant\metro.config.js,并添加 OpenHarmony 的适配代码:const {mergeConfig, getDefaultConfig} = require('@react-native/metro-config'); const {createHarmonyMetroConfig} = require('@react-native-oh/react-native-harmony/metro.config'); /** * @type {import("metro-config").ConfigT} */ const config = { transformer: { getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, inlineRequires: true, }, }), }, }; module.exports = mergeConfig(getDefaultConfig(__dirname), createHarmonyMetroConfig({ reactNativeHarmonyPackageName: '@react-native-oh/react-native-harmony', }), config);运行
npm run harmony之后harmony/entry/src/main/resources/rawfile/bundle.harmony.js就生成了。npm run harmony

同时也会生成静态资源 assets 目录

-
创建鸿蒙工程
打开 DevEcho Studio 创建空白项目:


项目名称:RNHarmonySkuAssistant
Bundle 名称: host.huqi.sku_assistant
路径: RNHarmonySkuAssistant/harmony/entry2
SDK: 6.1.0(23)
5 合并文件
cd harmony
# 1. 把 entry2 下除了 entry 之外的内容移到 harmony 根目录
cp -R entry2/AppScope entry2/.hvigor entry2/.idea entry2/hvigor entry2/oh_modules .
# 2. 把 entry2/entry 的内容合并到 entry/
cp -R entry2/entry/* entry/
cp -a entry2/entry/.* entry/ 2>/dev/null
# 3. 确认没问题后删除 entry2
rm -rf entry2

当前项目最终目录采用
harmony/entry作为唯一 entry 模块,不再保留entry2。如果是从 DevEco 新建空白工程再合并,完成合并后要确认:harmony ├── AppScope ├── entry ├── build-profile.json5 ├── hvigorfile.ts ├── hvigor └── oh-package.json5
在 entry 目录下执行命令:
ohpm i
项目结构示例:
RNHarmonySkuAssistant
├── App.tsx
├── package.json
├── src
│ ├── pages
│ └── components
└── harmony
├── AppScope
├── entry
├── build-profile.json5
└── oh-package.json5
7. 编写第一个 RN 页面
修改 App.tsx:
import React from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
StyleSheet,
Text,
View,
Pressable,
} from 'react-native';
const features = [
'商品包装 OCR 识别',
'商品主图抠图换背景',
'商品卖点 TTS 播报',
'库存预警桌面卡片',
'SKU 碰一碰分享',
];
export default function App() {
return (
<SafeAreaView style={styles.safeArea}>
<StatusBar />
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View style={styles.container}>
<Text style={styles.title}>RN Harmony SKU Assistant</Text>
<Text style={styles.subtitle}>
React Native x HarmonyOS 创新能力接入方案 Demo
</Text>
<View style={styles.card}>
<Text style={styles.cardTitle}>本系列将逐步实现:</Text>
{features.map((item) => (
<View key={item} style={styles.featureItem}>
<Text style={styles.featureText}>{item}</Text>
</View>
))}
</View>
<Pressable style={styles.button}>
<Text style={styles.buttonText}>开始体验</Text>
</Pressable>
</View>
</ScrollView>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
safeArea: {
flex: 1,
backgroundColor: '#F7F8FA',
},
container: {
padding: 20,
},
title: {
fontSize: 26,
fontWeight: '700',
color: '#111827',
marginTop: 24,
},
subtitle: {
fontSize: 15,
color: '#6B7280',
marginTop: 8,
lineHeight: 22,
},
card: {
backgroundColor: '#FFFFFF',
borderRadius: 18,
padding: 18,
marginTop: 24,
},
cardTitle: {
fontSize: 17,
fontWeight: '600',
color: '#111827',
marginBottom: 12,
},
featureItem: {
paddingVertical: 10,
borderBottomWidth: StyleSheet.hairlineWidth,
borderBottomColor: '#E5E7EB',
},
featureText: {
fontSize: 15,
color: '#374151',
},
button: {
marginTop: 24,
backgroundColor: '#0A59F7',
borderRadius: 16,
paddingVertical: 14,
alignItems: 'center',
},
buttonText: {
fontSize: 16,
color: '#FFFFFF',
fontWeight: '600',
},
});

8. 在 DevEco Studio 中运行 HarmonyOS 工程
运行前确认:
1. SDK 已正确配置
2. 签名配置正常
3. 设备已连接
4. Metro 已启动
5. entry 模块可以正常编译

9. 示例环境排障记录
本文原本内置了一段较长的 0.84.1 + HarmonyOS 6.1 排障记录。为了保持环境篇主线清晰,详细过程已拆到独立文章:
附录覆盖的问题包括:
1. Metro 找不到 react-native
2. hvigor root node 报错
3. 模拟器版本与 SDK 匹配
4. safe-area-context 导致白屏
5. bundle / HAP / 安装启动验证
注意:附录是一次具体环境的排障记录,不代表所有版本都应套用相同修复。
10. 常见问题
页面白屏
优先检查:
1. Metro 是否启动
2. 设备是否能访问 Metro 地址
3. JS Bundle 是否加载成功
4. DevEco Studio 控制台是否有报错
5. RNOH 版本是否与 RN 版本匹配
如果日志中出现:
Couldn't find Turbo Module on the ArkTs side, name: 'RNCSafeAreaContext'
先不要继续反复重装模拟器。这个更像是 react-native-safe-area-context Harmony 原生包与当前 RNOH 版本的兼容问题。第一篇环境跑通阶段可以先用上面的 JS shim;后续如果业务需要真实安全区能力,再单独适配该三方包的 ArkTS / C++ TurboModule 注册。
编译失败
优先检查:
1. HarmonyOS SDK 是否安装完整
2. oh_modules 是否安装成功
3. hvigor 是否同步成功
4. 签名配置是否正确
5. RNOH 依赖版本是否一致
11. 本篇小结
本篇完成了系列第一步:
React Native 项目
↓
接入 RNOH
↓
运行在 HarmonyOS 工程中
↓
显示第一个 RN 页面
从下一篇开始,我们会进入真正的核心:
React Native 如何调用 HarmonyOS 原生能力?
下一篇会实现一个最小 TurboModule:
RN 页面点击按钮
↓
调用 ArkTS 原生模块
↓
返回设备信息 / Toast 结果
↓
RN 页面展示结果
更多推荐



所有评论(0)