【开源鸿蒙跨平台开发学习笔记】Day01:React Native 开发 HarmonyOS-环境搭建篇

前言

本次参加开源鸿蒙跨平台开发学习活动,选择了 React Native 开发 HarmonyOS技术栈,在学习的同时顺便整理成一份系列笔记,记录从环境到开发的全过程。react-native-openharmony 目前已经比较成熟,能够让 RN 项目直接运行在鸿蒙设备或模拟器上,对于想做跨平台开发的人来说,是一个不错的选择。

本篇作为第一篇,重点介绍环境准备与项目初始化流程。

一、为什么选择 React Native 开发 HarmonyOS?

React Native 的优势在于生态成熟、组件丰富、工具链完善,开发效率高。通过社区的适配层,RN 可以在 Android、iOS、HarmonyOS 三端同时运行,这意味着:

  • 一套代码多端复用;

  • 保留现有 RN 技术栈;

  • 降低适配鸿蒙的门槛;

  • 更适合前端或跨端背景的开发者。

就比如我本身就是前端开发者,有Vue和RN开发经验,如果要开发HarmonyOS应用,使用RN的跨平台开发就是一个不错的选择。

RNOH架构

如图,React Native for OpenHarmony 在 React Native 的新架构(0.68 以及之后的版本)的基础上,进行了鸿蒙化的适配。按照功能可以进行如下的划分:

  • RN 应用代码:开发者实现的业务代码。
  • RN 库代码:在 React Native 供开发者使用的组件和 API 的封装与声明。
  • JSI(JavaScript Interface):JavaScript 与 CPP 之间进行通信的 API。
  • React Common:所有平台通用的 CPP 代码,用于对 RN 侧传过来的数据进行预处理。
  • OpenHarmony 适配代码:接收并处理 React Common 传过来的数据,对接原生的代码,调用 ArkUI 的原生组件与 API。主要包括了两个部分:分别是 TurboModule 与 Fabric。
  • OS 代码:对接系统底层功能,根据适配层代码传过来的数据进行渲染,或完成对应的功能。

二、环境准备

正式开始前,需要准备以下工具:

环境 说明
Node.js 18+ 建议使用 nvm 管理
React Native CLI 用于创建 RN 项目
OpenHarmony SDK(必装) 可通过 DevEco Studio 或 CLI 安装
HarmonyOS 模拟器或真机 真机可直接 USB 调试
react-native-openharmony RN 的鸿蒙适配层

版本兼容性确认

  • React Native ≥ 0.71

  • react-native-openharmony ≥ 根据OpenHarmony SDK对应

  • DevEco Studio ≥ 5.1(可选)

  • OpenHarmony SDK ≥ API 12(推荐)

HDC环境变量设置

hdc 是 OpenHarmony 为开发人员提供的用于调试的命令行工具,鸿蒙 React Native 工程使用 hdc 进行真机调试。hdc 工具通过 OpenHarmony SDK 获取,存放于 SDK 的 toolchains 目录下,请将 {DevEco Studio安装路径}/sdk/{SDK版本}/openharmony/toolchains 的完整路径添加到环境变量中。

  • windows 环境变量设置方法:
  1. 此电脑 > 属性 > 高级系统设置 > 高级 > 环境变量中,编辑系统变量path,添加hdc工具路径。
  2. 此电脑 > 属性 > 高级系统设置 > 高级 > 环境变量 中,添加 HDC 端口变量名为:HDC_SERVER_PORT,变量值可设置为任意未被占用的端口,如 7035
  • macOS 环境变量设置方法:
  1. 打开终端,执行以下命令,打开 .bash_profile 文件。

    bash 复制代码
    vi ~/.bash_profile
  2. 输入以下内容,在 PATH 路径下添加 HDC 工具路径和添加 HDC_SERVER_PORT 端口信息:

    bash 复制代码
    export PATH="/Applications/DevEco-Studio.app/Contents/sdk/{版本路径}/openharmony/toolchains:$PATH" # 按照实际 SDK 安装路径配置,需要选择{显示包内容}
    
    HDC_SERVER_PORT=7035 
    launchctl setenv HDC_SERVER_PORT $HDC_SERVER_PORT 
    export HDC_SERVER_PORT
  3. 执行以下命令使配置的环境变量生效:

    bash 复制代码
    source ~/.bash_profile
  • 配置 CAPI 版本环境变量:当前RN框架提供的 Demo 工程默认为 CAPI 版本,需要配置环境变量 RNOH_C_API_ARCH = 1
  1. Windows 环境:在此电脑 > 属性 > 高级系统设置 > 高级 > 环境变量 中,在系统变量中点击新建,添加变量名为:RNOH_C_API_ARCH,变量值为 1

  2. Mac环境:在终端中,输入以下命令来设置环境变量:export RNOH_C_API_ARCH=1,确认环境变量是否成功设置。在终端中输入以下命令:echo $RNOH_C_API_ARCH。如果输出为 1,则表示环境变量已成功设置。如果希望在每次打开终端时都自动设置该环境变量,可以将上述 export 命令添加到你的 bash 配置文件(例如~/.bash_profile、~/.bashrc 或 ~/.zshrc)。编辑相应的文件,并在末尾添加以下行:export RNOH_C_API_ARCH=1,保存文件并关闭编辑器。

  • 为了使用加速 npm 包的下载,可以配置镜像源

    bash 复制代码
    strict-ssl=false
    sslVerify=false
    registry=https://repo.huaweicloud.com/repository/npm/

    修改 registry 后需执行 npm cache clean --force 清理缓存,以确保新的 registry 生效。完成以上环境配置即可进行鸿蒙的 React Native 项目开发。

三、安装 OpenHarmony SDK

DevEco Studio(官方推荐,最稳定)

  1. 下载 DevEco Studio 5.1+

  2. 第一次启动会弹出"安装 OpenHarmony SDK"提示

  3. 按向导安装完整 SDK

  4. 安装完成后可创建模拟器

验证方式:

DevEco → Tools → SDK Manager → 能看到 HarmonyOS API 12/13,即安装成功。

四、创建React Native工程

可选择一个目录,使用 React Native 内置的命令行工具来创建一个名为 "HarmonyRNTest" 的新项目。这个命令行工具不需要安装,可以直接用 node 自带的 npx 命令来创建,目前 React Native for OpenHarmony 仅支持 0.72.5 版本的 React Native:

bash 复制代码
npx react-native@0.72.5 init HarmonyRNTest --version 0.72.5
cd HarmonyRNTest

五、下载并安装鸿蒙化依赖

使用VS Code IDE打开生成的模版代码。

打开目录下的package.json,在scripts下新增 OpenHarmony 的执行脚本:

bash 复制代码
"scripts": {
   "android": "react-native run-android",
   "ios": "react-native run-ios",
   "lint": "eslint .",
   "start": "react-native start",
   "test": "jest",
    "dev": "react-native bundle-harmony --dev"
 }

运行安装依赖包命令:推荐使用pnpm我用npm总是失败。

bash 复制代码
pnpm i @react-native-oh/react-native-harmony@特定版本

注意:一定要使用和你的HarmonyOS SDK版本对应的react-native-harmony版本,否者会报错!!!

如何查找对应自己环境的版本:

  1. 查看自己配置之前环境变量配置的toolchains对应的SDK版本号:

    我的是6..0.0.47;

  2. 然后去https://gitcode.com/openharmony-sig/ohos_react_native/blob/master/docs/zh-cn/release-notes/react-native-harmony-v6.0.0.508.md地址查询对应的版本号:

    根据我的SDK版本6.0.0.47所以我下载的react-native-harmony版本就应该是0.72.90;

    bash 复制代码
    pnpm i @react-native-oh/react-native-harmony@0.72.90

再去修改metro.config.js文件添加OpenHarmony 的适配代码。

bash 复制代码
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);

运行生成 bundle 文件的命令。运行成功后,会在 HarmonyRNTest/harmony/entry/src/main/resources/rawfile 目录下生成 bundle.harmony.jsassets 文件夹,assets 用来存放图片(如果 bundle 中不涉及本地图片,则没有 assets 文件夹)。

bash 复制代码
pnpm run dev

执行成功后,在项目根目录会生成Harmony文件夹。

好了,看到以上文件夹RN这边先告一段落。

六、在HarmonyOS工程中集成React Native

首先我们创建一个空的新工程。

然后我们再执行如下命令,在原生工程中集成 RNOH:

bash 复制代码
ohpm i @rnoh/react-native-openharmony@0.72.90

集成之后可以查看工程根目录的oh-package.json5文件:

好接下来修改默认工程入口Ability的实现:

  1. 需要重写getPagePath方法,返回程序的入口page;
  2. 如果需要扩展使用对应的生命周期函数请在代码中先用super调用父类也就是RNAbility的生命周期函数实现,因为RNAbility在生命周期函数中进行了对应的操作,这样才能确保原有功能不丢失;
  3. 需确保函数的参数列表与父类保持兼容,建议添加override关键字,以提升代码可读性并增强编译器检查;
TypeScript 复制代码
import { RNAbility } from '@rnoh/react-native-openharmony';
import { Want } from '@kit.AbilityKit';

export default class EntryAbility extends RNAbility {
  getPagePath(): string {
    return "pages/Index"
  }

  override onCreate(want: Want): void {
    super.onCreate(want);
  }
}

在entry\src\main\ets目录下新增RNPackagesFactory.ets文件,它用来在 @rnoh/react-native-openharmony 库中导入 RNPackageContext 和 RNPackage以及在文件中导出 createRNPackages 方法,用于创建三方库或自定义 TurboModule、Fabric的package 对象,由于这次不涉及三方库,这块直接返回[]:

TypeScript 复制代码
import { RNPackageContext, RNPackage } from '@rnoh/react-native-openharmony/ts';
export function createRNPackages(ctx: RNPackageContext): RNPackage[] {
  return [];
}

打开Index.ets文件,添加RNOH的使用代码,修改后如下:

TypeScript 复制代码
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")
    const stopTracing = this.logger.clone("aboutToAppear").startTracing();

    this.shouldShow = true
    stopTracing();
  }

  onBackPress(): boolean | undefined {
    // NOTE: this is required since `Ability`'s `onBackPressed` function always
    // terminates or puts the app in the background, but we want Ark to ignore it completely
    // when handled by RN
    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, // 该项必须为true,用于开启NDK文本测算
            enableBackgroundExecutor: false,
            enableCAPIArchitecture: true, // 该项必须为true,用于开启CAPI
            arkTsComponentNames: []
          },
          initialProps: { "foo": "bar" } as Record<string, string>,
          appKey: "HarmonyRNTest",
          wrappedCustomRNComponentBuilder: wrappedCustomRNComponentBuilder,
          onSetUp: (rnInstance) => {
            rnInstance.enableFeatureFlag("ENABLE_RN_INSTANCE_CLEAN_UP")
          },
          jsBundleProvider: new TraceJSBundleProviderDecorator(
            new AnyJSBundleProvider([
              new MetroJSBundleProvider(),
              // NOTE: to load the bundle from file, place it in
              // `/data/app/el2/100/base/com.rnoh.tester/files/bundle.harmony.js`
              // on your device. The path mismatch is due to app sandboxing on OpenHarmony
              new FileJSBundleProvider('/data/storage/el2/base/files/bundle.harmony.js'),
              new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'hermes_bundle.hbc'),
              new ResourceJSBundleProvider(this.rnohCoreContext.uiAbilityContext.resourceManager, 'bundle.harmony.js')
            ]),
            this.rnohCoreContext.logger),
        })
      }
    }
    .height('100%')
    .width('100%')
  }
}

注意:RNApp的参数appKey需要与RN工程中AppRegistry.registerComponent注册的appName保持一致,否则会导致白屏。

通过以上方式可以获取到这个注册的名字,也就是RN工程的名字。

然后我们还需要补充 CPP 侧代码,在entry/src/main目录下新建cpp文件夹。在cpp目录下新增CMakeLists.txt,并将RNOH的适配层代码添加到编译构建中生成librnoh_app.so。

CMakeLists.txt文件内容如下:

TypeScript 复制代码
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) # for other CMakeLists.txt files to use

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)

在cpp目录下新增PackageProvider.cpp,该文件导入RNOH/PackageProvider,并且实现getPackages方法,用于创建三方库或自定义TurboModule或Fabric的package对象。此处不涉及三方库与自定义TurboModule或组件,需要返回空数组。然后打开entry/build-profile.json5,将cpp中的代码添加到应用工程的编译构建任务中;如果x86_64架构的模拟器上运行应用,需在externalNativeOptions配置中额外添加abiFilters字段,并包含x86_64架构参数,如下所示,abiFilters字段当前被注释,默认仅构建适应于arm64-v8a架构的版本。

加载bundle包

在上一章节中已经完成了 bundle 文件的生成,接下来将它加载到 DevEco Studio 中以运行 MyApplication 项目。我们采用加载 本地bundle 包的形式,将 bundle 文件和 assets 图片放在 entry/src/main/resources/rawfile 路径下,在 entry/src/main/ets/pages/Index.ets 中使用。

将之前我们执行npm run dev后的harmony/entry/src/main/resources/rawfile目录下的bundle文件和assets图片拷贝到鸿蒙工程entry/src/main/resources/rawfile路径下。

启动并运行工程~

然后就遇到了一个比较坑的问题,依赖:@rnoh/react-native-openharmony在CMakeLists.txt配置的${OH_MODULE_DIR}/@rnoh/react-native-openharmony路径下是一个"替身"文件,这个可能是MacOS才会报的错。

然后就遇到了一个比较坑的问题,依赖:@rnoh/react-native-openharmony在CMakeLists.txt配置的${OH_MODULE_DIR}/@rnoh/react-native-openharmony路径下是一个"替身"文件,这个可能是MacOS才会报的错。并且CMakeLists.txt里面识别的依赖路径也不对,后来改成绝对路径才可用。新CMakeLists.txt文件内容如下:

复制代码
project(rnapp)
cmake_minimum_required(VERSION 3.4.1)
get_filename_component(PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../../../" ABSOLUTE)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
set(OH_MODULE_DIR "${PROJECT_ROOT}/oh_modules/.ohpm/@rnoh+react-native-openharmony@0.72.90/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) # for other CMakeLists.txt files to use

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)

启动并运行工程~

✿✿ヽ(°▽°)ノ✿,终于好了

总结

本篇内容主要集中在环境搭建,包括:

  • React Native 项目初始化

  • 安装 OpenHarmony SDK(IDE / CLI)

  • 添加 react-native-openharmony 适配

  • HarmonyOS 工程构建与运行

完成这些后,整个跨端开发环境就已经就绪。

相关推荐
@小红花1 小时前
从零到精通 Hadoop 的系统学习文档
大数据·hadoop·学习
lqj_本人1 小时前
鸿蒙与Qt的双线程模型:主线程与UI线程的博弈
qt·ui·harmonyos
d111111111d1 小时前
W25Q60简介--SPI通信(笔记)
笔记·stm32·单片机·嵌入式硬件·学习
御承扬2 小时前
鸿蒙原生系列之拖拽事件
华为·harmonyos·拖拽事件·ndk ui
不爱吃糖的程序媛2 小时前
开源鸿蒙 Cordova 设备信息插件开发详解
华为·开源·harmonyos
minhuan2 小时前
大模型应用:大模型本地部署实战:从零构建可视化智能学习助手.2
学习·生成式ai·大模型应用·大模型本地部署·学习助手
CoderJia程序员甲2 小时前
GitHub 热榜项目 - 日榜(2025-11-22)
ai·开源·llm·github·ai教程
BullSmall3 小时前
《道德经》第六十七章
学习
qy-ll3 小时前
最新MMO-IG生成图像论文学习(25/11/19)
图像处理·深度学习·学习·计算机视觉·论文学习·遥感