引言
针对 React Native三方库(后文简称RN三方库)开发,总体可分为三大类型:纯 JS 库、JS 库、原生库。在进行适配开发前,可先在公仓中查询该 RN 三方库是否已完成鸿蒙化,若已完成,可在现有鸿蒙化框架基础上进行改造开发,以达到事半功倍的效果。
一
三方库的分类及相应适配流程
1. 纯 JS 库
1.1 核心特性 - 适配难度最低
纯 JS 库是适配难度最低的类型,本质是因为纯粹的 JavaScript 模块,不依赖 React Native 平台的特定功能,可在多种 JavaScript 环境中运行。
1.2 区分关键点 - 无原生目录与相关依赖
源码目录中不包含 “Android/iOS” 等原生相关目录,且在 package.json 文件中无 react-native 相关依赖。


1.3 移植方式
纯 JS 库的鸿蒙化开发,主要是对三方库的接口进行验证并编写对应的接口测试 Demo。若发现接口无法使用或与预期效果不一致,可以直接在 RNOH(React Native for OpenHarmony)框架侧排查并解决问题。
1.4 主要工作
通过查阅原库的 md 文档或搜索对应库的功能,梳理出需实现的接口(如对外提供的 ABC 接口、内部使用的 DEFG 接口等),在此过程中同步整理输出三方库规格表;在指定的 “Android/iOS” 环境中运行该库,验证功能效果,同时可输出测试 Demo。
2. JS 库
2.1 核心特性 - 适配工作量中等
相对而言,JS 库在RN三方库中适配工作量中等,但不涉及原生代码实现,主要利用 React Native 提供的桥接机制和 API 来实现其功能,或通过其他三方库实现二次封装的功能。
2.2 区分关键点 - 无原生目录有RN相关依赖
源码项目目录中不包含 “Android/iOS” 原生相关目录,但 package.json 文件中存在 react-native 相关依赖(重点关注 dependencies 和 peerDependencies 两个依赖字段,devDependencies 为开发依赖,无需关注)。


2.3 移植方式
与纯 JS 库一致,先对三方库进行功能验证并编写测试 Demo;若功能无异常,则无需额外开发,直接完成上架即可;若存在功能不一致或无法实现的情况,需梳理原库代码流程,定位问题接口并进行修复(通常是将接口调用的原生接口替换为鸿蒙侧对应的功能接口)。
2.4 主要工作
本环节的主要工作是编写测试 Demo 并完成上库;若适配过程有问题,则需要修改适配相关代码,修复接口问题后,将修改后的代码归档、发包并完成上库。
当 JS 库需修改代码时,需对 package.json 文件进行如下调整:
// package.json
"name": "react-native-xxxxx(库名)",
-----> @ohmi/react-native-xxxxx // @组织名/原库库名
"version": "1.0.0",
------> "version": "1.0.0-0.0.1" // 根据主版本进行变更
"repository": {
"type": "git",
"url": "https://gitee.com/kunyuan-hongke/react-native-xxx.git" // 具体地址以项目仓库为准
},
"harmony": {
"alias": "xxxxx库名"
------> "alias": "react-native-xxxxx" // 代码编写中 import 时的原库名
},
"keywords": [
xxxxxxx,
"harmony" // 添加harmony字段
],
完成功能适配和上述配置修改后,在该库目录下运行 `npm pack` 命令进行打包,如此生成对应 tgz格式的鸿蒙适配依赖包;在本地完成 tgz包的功能验证后,即可执行 npm上库操作。
3. 原生库
3.1 核心特性 - 适配工作量最大
原生库是三类库中适配工作量最大的类型,需包含 JS 库的所有开发操作。
3.2 区分关键点 - 有原生目录
源码目录的根目录或 package 目录下,通常包含 “Android/iOS” 原生目录。

3.3 移植步骤
以下步骤均以原生库“react-native-image-picker”为示例。
第一步:创建 Native 层接口文件
1)在 RN 框架集成项目中,安装原库,命令如下:
npm install xxxxxx
------> npm install react-native-image-picker
2) 在“node_modules”目录下找到该库,创建 src 目录。

3)在 src 目录下创建 Native 层接口文件(如 NativeImagePicker.ts):
import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'; //(固定模板)
import { TurboModuleRegistry } from 'react-native'; //(固定模板)
export interface xxxx(接口名,自己取,简单一目了然优先) extends TurboModule {
activate: () => void; //(你需要提供出去的接口,这里void表示返回值为空,还有返回Promise的,具体看你自己的接口)
deactivate: () => void; //(你需要提供出去的接口)
}
export default TurboModuleRegistry.get<Spec>('XXXXXXXXXX(取名)NativeModule') as Spec | null;
示例:
import type { TurboModule } from "react-native/Libraries/TurboModule/RCTExport";
import { TurboModuleRegistry } from "react-native";
export interface ImagePickerResponse {
//...
}
export interface ImagePickerOptions {
//...
}
export interface Spec extends TurboModule {
launchCamera(options: ImagePickerOptions, callback: (response: ImagePickerResponse) => void): void;
launchImageLibrary(options: ImagePickerOptions, callback: (response: ImagePickerResponse) => void): void;
showImagePicker: (options: ImagePickerOptions, callback: (response: ImagePickerResponse) => void) => void;
}
export default TurboModuleRegistry.get<Spec>("ImagePicker") as Spec | null;
第二步:配置 package.json 文件
1)在原库目录下的 package.json 文件中,进行如下配置修改:
// packge.json
{
// ...
"name": "@ohmi/xxxx(库名)",
-----> "@ohmi/react-native-image-picker"
"version": "xxxxxxx",
------> "version": "xxxxxx-0.0.1"
"repository": {
"type": "git",
"url": "https://gitee.com/kunyuan-hongke/react-native-image-picker.git"
},
"harmony": {
"alias": "xxxxx库名"
------> "alias": "react-native-image-picker" // 原库名
},
"keywords": [
xxxxxxx,
"harmony" // 添加harmony字段
],
"dependencies": {
"react-native-image-picker": "xxxxxxx" // 添加原库依赖
}
// ...
}
补充说明:在 dependencies 中添加原库依赖,可确保该库安装使用时不影响 “Android/iOS” 平台的正常运行;若开发中需引用原库的工具类,可通过 import 原库文件引用而非本地文件引入,能有效减少后续打包上传的文件大小。
2)在 package.json 的 scripts 中配置 codegen-lib 脚本,配置完成后,运行 `npm run codegen-lib` 命令生成接口文件,配置如下:
//packge.json
"scripts": {
//生成文件位置在 `codegen-lib` 命令中 `output-path` 位置设置:
"codegen-lib": "react-native codegen-lib-harmony --no-safety-check --npm-package-name react-native-image-picker --cpp-output-path ./harmony/image_picker/src/main/cpp/generated --ets-output-path ./harmony/image_picker/src/main/ets/generated --turbo-modules-spec-paths ./src/NativeImagePicker.ts",
//......
}
上述两步主要是进行 codegen 桥接层的编写 详细说明介绍可参考:codegen-lib 的使用:https://gitcode.com/OpenHarmony-RN/ohos_react_native/blob/master/docs/zh-cn/Codegen.md#codegen-lib-harmony
第三步:创建并配置 Harmony 静态模块
1)打开 DevEco Studio,在该库的 harmony 目录下,右键创建 Static Library 类型的 Module,步骤如下:右键 harmony → new → Module → Static Library → Next → 填写 module name(与库名对应,按照同目录的文件名取名)→ Next → Finish。
2)生成的 Module 中,ohosTest 与 test 及相关文件无实际用途,可直接删除。
3)将第二步中生成的 generated 目录下的文件,复制到新建的 Module 中。

4)在刚刚创建的 Module 下的 oh-package.json5 文件,将配置修改为:
//oh-package.json5
{
"name": "@ohmi/react-native-image-picker", //(上文已讲过name的格式,这里就不赘述了)
"version": "xxxxxx-0.0.1", //(同上)
"description": "Please describe the basic information.", //(描述)
"main": "Index.ets", //(主入口文件)
"author": "",
"license": "Apache-2.0",
"dependencies": {
"@rnoh/react-native-openharmony": "file:../react_native_openharmony" // 远程依赖也行 "@rnoh/react-native-openharmony": "0.72.xx"
}
}
5)同 Module 下 src/main 目录中的 module.json5 文件,修改成如下格式:
//module.json5
{
"module": {
"name": "image_picker", //(以你module文件名称为准)
"type": "har",
"deviceTypes": ["default", "tablet", "2in1"]
}
}
6)修改 index.ets 文件:
export * from "./ts";
7)新增 ts.ts 文件:
export * from "./src/main/ets/RNImagePickerPackage"; //(取决于你src/main/ets目录下的package名称)
export * from "./src/main/ets/RNImagePickerTurboModule"; //(取决于你src/main/ets目录下的module名称)

基础框架已述,接下来是核心配置部分。 初次开发 RN 鸿蒙原生库时,调试阶段从 RN 框架到鸿蒙侧常见的通联失败,大概率源于连接层的代码实现不规范。
8)核心配置:在 src/main/ets 目录下,创建 RNXXXXXPackage.ts 和 RNxxxxTurboModle.ts 两个文件。
RNImagePickerTurboModule.ts: 用于实现鸿蒙适配逻辑及对外暴露模块接口。如下图所示的两处需要改动,箭头标识对应文件的来源。 图中 “ImagePicker” 的指向是在第二步中 codegen生成的,文件缺失则为 codegen配置异常导致的。

RNImagePickerPackage.ts: 具体改动项如下图所示,其余部分无需更改。其中“XXXTurboModuleFactory”与“XXXTurboModule”均来自前文对应文件。

9)在 cpp 文件夹下,创建“CMakeLists.txt”和“RNImagePickerPackage.h”两个文件,其内容固定,仅需替换其中的 Module 名称,该名称与第三步创建的 Module 名称一致。
CMakeLists.txt:自定义模块时该文件中的所有“image_picker” 需替换成自定义模块名:
# the minimum version of CMake
cmake_minimum_required(VERSION 3.13)
set(CMAKE_VERBOSE_MAKEFILE on)
# 设置 Codegen 生成目录,指定 generated 目录路径
set(rnoh_image_colors_generated_dir "${CMAKE_CURRENT_SOURCE_DIR}/generated")
# 使用 GLOB_RECURSE 递归地查找所有在 generated 目录下的 .cpp 文件,并将其存储到变量 rnoh_image_colors_generated_SRC
file(GLOB_RECURSE rnoh_image_colors_generated_SRC "${rnoh_image_colors_generated_dir}/**/*.cpp")
# 查找当前目录下的所有 .cpp 文件,并将其存储到变量 rnoh_image_colors_SRC 中
# CONFIGURE_DEPENDS 表示如果这些文件被修改,CMake 会重新配置
file(GLOB rnoh_image_colors_SRC CONFIGURE_DEPENDS *.cpp)
# 创建一个共享库 rnoh_image_colors,包含两部分:rnoh_image_colors_SRC 和 rnoh_image_colors_generated_SRC
add_library(rnoh_image_colors SHARED ${rnoh_image_colors_SRC} ${rnoh_image_colors_generated_SRC})
# 为目标库 rnoh_image_colors 设置包含路径,这些路径会包含当前源目录和 Codegen 生成文件所在的目录
target_include_directories(rnoh_image_colors PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ${rnoh_image_colors_generated_dir})
# 将库 rnoh_image_colors 链接到 rnoh sdk,意味着 rnoh_image_colors 使用 rnoh sdk 中的功能
target_link_libraries(rnoh_image_colors PUBLIC rnoh)
RNImagePickerPackage.h:该文件名称及内容中导入模块需根据创建模块名修改:
#pragma once
#include "RNOH/generated/BaseReactNativeImagePickerPackage.h" //codegen-lib生成文件
namespace rnoh {
class RNImagePickerPackage : public BaseReactNativeImagePickerPackage {
using Super = BaseReactNativeImagePickerPackage;
public:
RNImagePickerPackage(Package::Context ctx) : Super(ctx) {}
};
} // namespace rnoh
至此,module层的创建与配置全部完成。若部分原生库涉及 Fabric 组件开发,可参考gitcode上的 Fabric 自定义组件开发指导:https://gitcode.com/OpenHarmony-RN/ohos_react_native/blob/master/docs/zh-cn/%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6.md
第四步:调试、打包与交付
1)本地调试:按照使用安装文档进行引入,看看功能是否能正常运行。将 “harmony/entry/oh-package.json5” 中该库的引入安装路径改为本地引用,便于开发调试:
//oh-package.json5
dependencies: {
"@ohmi/react-native-image-picker": "file:../../node_modules/@ohmi/react-native-image-picker/harmony/image_picker.har"
----> "@ohmi/react-native-image-picker": "file:../image_picker" //更改为本地路径调试
}
使用安装文档:https://www.npmjs.com/package/@ohmi/react-native-image-picker。
2)功能实现:在“RNImagePickerTurboModule.ts”文件中,完成鸿蒙侧的接口功能实现`(RNImagePickerTurboModule 类)`。
3)打包 HAR 包:在 DevEco Studio中,选中创建module,依次点击Build→Make Module 'library,生成的 HAR 包将位于module下的“build/default/outputs”目录中。

4)交付准备:在node_modules下对应库中,删除“Android/iOS”等多余目录,新建harmony目录,将修改后的module(删除依赖包)和生成的 HAR 包放入该目录,即为最终交付文件。
5)最终目录结构如下:

二
常见问题
运行`npm run codegen` 时报错,报错内容: `unknown command 'codegen-harmony'`
问题现象
运行React Native鸿蒙项目时,部分三方库使用到了`codegen自动生成桥接代码。运行`npm run codegen`命令时,可能会因为版本问题出现如下错误:

解决措施
该错误是由于react-native-harmony包与react-native-harmony-cli包所依赖的memfs与metro两个包版本过高所导致的,解决方案可在当前项目下执行以下命令:
npm install memfs@4.12.0 metro@0.82.5 -E
注:`-E` 是 `--save-exact` 的简写,作用是让“npm”在“package.json”中记录包的确切版本号,而不是带“^”或者“~”的可更新版本,避免再次出现版本兼容的问题。
三
RN 三方库相关仓库说明
文档仓中主要包含对应库的使用文档查看,可通过其中的源码链接跳转至相关源码库。
RN 三方库文档仓链接:https://gitcode.com/OpenHarmony-RN/usage-docs/blob/master/zh-cn/README.md
更多资讯 关注我们