一、记录踩到的坑

参考的是这篇文章,但是踩了好多坑,这里逐一列举出来。ohos_react_native/docs/zh-cn/版本说明.md · OpenHarmony-SIG/ohos_react_native - GitCodehttps://gitcode.com/openharmony-sig/ohos_react_native/blob/master/docs/zh-cn/%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.md?mode=light

1.1 .npmrc文件存在多个

文章说编辑用户级.npmrc配置文件,但是Everything搜索.npmrc,发现有很多个,但是我没有 C:\Users\用户名\.npmrc这个路径的文件。这里我选择了DevEco Studio目录下的.npmrc文件。

1.2 React与HarmonyOS版本不兼容

根据文章执行"npm i @react-native-oh/react-native-harmony@x.x.x"命令。如果@x.x.x没进行指定,默认下载最新版本。于是我就没指定版本直接执行了,下载了v0.76.9的版本。但是在 React Native 0.72+ 版本中,DrawerLayoutAndroid 组件已经被移除了,但 HarmonyOS 插件还在尝试引用这个已经不存在的模块,所以后面就一堆爆红了。后来我查看了GitCode的版本说明,忘记查看了自己的DevEco Studio版本(记得查看自己的DevEco Studio版本),就去问AI了,然后AI叫我去下了个0.76.8的版本,结果就是失败了。这时候查看GitCode的版本说明,最新版本仅支持0.72.101,AI叫我下的版本远超这个版本了。根据官方文档,要下载的是0.72.71,建议一开始就指定适合自己的版本,不然可能会有坑。选择0.72.71版本后,很快就成功了。

ohos_react_native/docs/zh-cn/版本说明.md · OpenHarmony-SIG/ohos_react_native - GitCode

npm i @react-native-oh/react-native-harmony@x.x.x

1.3 忘记把文件拷贝进来

忘记把文件拷贝进来,导致编译错误。执行完"npx react-native@0.72.5 init AwesomeProject --version 0.72.5 --skip-install"命令后,会生成一个AwesomeProject的文件。里面有两个文件:bundle.harmony.js文件和assets文件夹。(注意assets文件夹有两个,选择里面有三个文件那个),然后拷贝进去鸿蒙的rawfile文件夹下。

npx react-native@0.72.5 init AwesomeProject --version 0.72.5 --skip-install

二、React鸿蒙环境搭建

开发环境搭建这里就不讲了,具体可以参考幻影的鸿蒙开发之旅1-安装DevStudio-CSDN博客

2.1 新建系统变量

打开系统环境变量,选择Path点击编辑,分别在里面新建两个变量:

toolchains的路径:"D:\All_ide\HongMeng\ide\OpenHarmony_SDK\20\toolchains"

"HDC_SERVER_PORT":7035

2.2 配置鸿蒙项目

执行"npx react-native@0.72.5 init AwesomeProject --version 0.72.5 --skip-install"会得到一个文件:AwesomeProject

下载并安装鸿蒙化依赖

打开 AwesomeProject 目录下的 package.json,在 scripts 下新增 OpenHarmony 的依赖:

,"dev": "react-native bundle-harmony --dev"1r

{
 "name": "AwesomeProject",
 "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",
+    "dev": "react-native bundle-harmony --dev"
 },
 "dependencies": {
   "react": "18.2.0",
   "react-native": "0.72.5"
 },
 "devDependencies": {
   "@babel/core": "^7.20.0",
   "@babel/preset-env": "^7.20.0",
   "@babel/runtime": "^7.20.0",
   "@react-native/eslint-config": "^0.72.2",
   "@react-native/metro-config": "^0.72.11",
   "@tsconfig/react-native": "^3.0.0",
   "@types/react": "^18.0.24",
   "@types/react-test-renderer": "^18.0.0",
   "babel-jest": "^29.2.1",
   "eslint": "^8.19.0",
   "jest": "^29.2.1",
   "metro-react-native-babel-preset": "0.76.8",
   "prettier": "^2.4.1",
   "react-test-renderer": "18.2.0",
   "typescript": "4.8.4"
 },
 "engines": {
   "node": ">=16"
 }
}

然后执行"npm i @react-native-oh/react-native-harmony@x.x.x",这里最好指定一下版本,比如我的DevEco Studio是6.0.0版本,React下载的版本最好是0.72.71的。所以命令可以改为"npm i @react-native-oh/react-native-harmony@0.72.71"

运行指令并生成bundle

打开 AwsomeProject\metro.config.js,并添加 OpenHarmony 的适配代码。配置文件的详细介绍,可以参考React Native 中文网。修改完成后的文件内容如下:

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);

新建一个鸿蒙项目

具体怎么新建就不说了,网上很多教程。这里我们讲需要配置哪些文件。

1.在src文件夹中的main目录新建一个cpp文件夹,分别存放CMakeLists.txtPackageProvider.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) # 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)

PackageProvider.cpp文件内容如下:

#include "RNOH/PackageProvider.h"

using namespace rnoh;

std::vector<std::shared_ptr<Package>> PackageProvider::getPackages(Package::Context ctx) {
    return {};
}

2.打开 MyApplicaton\entry\build-profile.json5,将 cpp 中的代码添加到应用工程的编译构建任务中

build-profile.json5文件内容如下:

{
  "apiType": "stageMode",
  "buildOption": {
    "externalNativeOptions": {
      "path": "./src/main/cpp/CMakeLists.txt",
      "arguments": "",
      "cppFlags": "",
      "abiFilters": ["arm64-v8a", "x86_64"]
    },
    "resOptions": {
      "copyCodeResource": {
        "enable": false
      }
    }
  },
  "buildOptionSet": [
    {
      "name": "release",
      "arkOptions": {
        "obfuscation": {
          "ruleOptions": {
            "enable": false,
            "files": [
              "./obfuscation-rules.txt"
            ]
          }
        }
      }
    },
  ],
  "targets": [
    {
      "name": "default"
    },
    {
      "name": "ohosTest",
    }
  ]
}

3.补充ArkTS侧的代码

EntryAbility.ets文件内容如下:

import { RNAbility } from '@rnoh/react-native-openharmony';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';

const DOMAIN = 0x0000;

export default class EntryAbility extends RNAbility {
  getPagePath() {
    return 'pages/Index';
  }

  override onCreate(want: Want): void {
    super.onCreate(want);
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'EntryAbility onCreate');
  }

  override onDestroy(): void {
    super.onDestroy();
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'EntryAbility onDestroy');
  }

  override onWindowStageCreate(windowStage: window.WindowStage): void {
    super.onWindowStageCreate(windowStage);
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'EntryAbility onWindowStageCreate');
  }

  override onWindowStageDestroy(): void {
    super.onWindowStageDestroy();
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'EntryAbility onWindowStageDestroy');
  }

  override onForeground(): void {
    super.onForeground();
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'EntryAbility onForeground');
  }

  override onBackground(): void {
    super.onBackground();
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'EntryAbility onBackground');
  }
}

4.在 MyApplicaton\entry\src\main\ets 目录下新增 RNPackagesFactory.ets,该文件需要满足以下要求:

  • 在 @rnoh/react-native-openharmony 导入 RNPackageContext 和 RNPackage
  • 在文件中导出 createRNPackages 方法,用于创建三方库或自定义 TurboModule、Fabric的package 对象。

5.打开 MyApplicaton\entry\src\main\ets\pages\Index.ets,添加RNOH的使用代码,修改后如下:

​
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: "AwesomeProject",
          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%')
  }
}

​

加载bundle包

参考这篇文章,里面提供了三个方式,我们使用的是方式一。

GitCode - 全球开发者的开源社区,开源代码托管平台

AwesomeProject的文件。里面有两个文件:bundle.harmony.js文件和assets文件夹。(注意assets文件夹有两个,选择里面有三个文件那个),然后拷贝进去鸿蒙的rawfile文件夹下。

至此,所有需要配置的文件配置完毕。

三、运行自己的第一个项目

点击绿色右三角,运行自己的模拟器。成功运行,完结撒花!!!~~

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新

更多推荐