- OpenHarmony
- 移动开发
- 跨平台
【免费下载链接】ohos_react_native
React Native鸿蒙化仓库
本文基于 ohos_react_native 仓库中的 AutolinkingSample 示例工程,系统讲解 React Native 鸿蒙化(RNOH)生态下**三方库自动链接(Autolinking)**的完整落地路径:从编写 RN 三方件(TurboModule / Fabric 组件)、
pnpm pack打包、ReactProject 侧接入与 bundle 生成,到 NativeProject(Harmony 工程)通过link-harmony自动生成 ETS/C++ 链接代码并完成编译运行。读完本文,你将掌握如何把自研三方库以极低人工成本接入 RNOH 工程,并理解自动链接背后"扫描 HAR → 生成 Package 工厂 → 更新 oh-package 依赖 → CMake 自动链接"的底层机制。
AutolinkingSample 运行效果
一、示例工程总览
AutolinkingSample 是 RNOH Autolinking 的演示工程,位于 docs/Samples/AutolinkingSample,其目录结构如下:
AutolinkingSample ├── NativeProject # Harmony(OpenHarmony)原生工程 ├── react-native-oh # RNOH 前端及脚手架 ├── ReactProject # React Native 前端工程 ├── screenshots # 运行效果图 ├── third-party-library-sample # RN 三方件示例(待接入的自研库) └── README.md / README_zh.md # 中英文说明整个示例演示了一条完整的"三方件自研 → 自动链接"链路:
- third-party-library-sample:一个"待发布的 RN 三方库",内部同时包含三种典型原生能力——ETS 实现的 UI 组件(
SelectBox)、C++ 实现的 Fabric 组件(QDGestureFloat)、两个 TurboModule(SampleTurboModule与SampleAnyThreadTurboModule); - ReactProject:普通 RN 前端工程,通过
file:方式依赖本地打包出的三方件,并调用其导出能力; - NativeProject:Harmony 原生壳工程,在编译期自动完成对三方件 HAR(Harmony Archive)与原生代码的链接。
二、环境搭建与运行(五步走)
按照 README_zh.md 的流程,依次执行:
1. 打包三方件:pnpm pack
进入third-party-library-sample目录执行:
pnpm pack该命令基于 third-party-library-sample/package.json 中的files字段(index.ts、src/*、harmony/*)将三方件打成third-party-library-sample-1.0.0.tgz压缩包,供 RN 工程以本地包形式安装。
2. 安装依赖并生成 bundle
在ReactProject目录下依次执行:
pnpm i # 安装依赖 pnpm dev # 打包生成 bundle.harmony.js其中pnpm dev实际执行的是 ReactProject/package.json 中定义的脚本:
"dev": "react-native bundle-harmony --dev false --bundle-output ../NativeProject/entry/src/main/resources/rawfile/bundle.harmony.js"即通过 RNOH CLI 提供的bundle-harmony命令,把 JS 侧代码打包为bundle.harmony.js并直接输出到 NativeProject 的rawfile资源目录,后续 Harmony 工程会以ResourceJSBundleProvider的方式加载该 bundle(见 NativeProject/entry/src/main/ets/pages/Index.ets)。
3. 打开 Harmony 工程并等待同步
用 DevEco Studio 打开NativeProject,等待工程自动同步完成;若未自动同步,可手动执行Sync and Refresh Project。
4. 配置签名
点击File > Project Structure > Signing Configs,登录华为账号并完成自动签名。示例工程的签名配置声明在 NativeProject/build-profile.json5 的signingConfigs中。
5. 运行
点击 DevEco Studio 右上角run启动项目,即可看到示例界面。
提示:默认情况下 NativeProject 直接使用预编译好的
third-party-library-sample/harmony/library.har;如需重新编译该 HAR,可在 build-profile.json5 中取消modules中library模块的注释,将三方件源码目录纳入构建。
三、三方件侧:如何编写一个可被自动链接的 RN 库
third-party-library-sample是理解自动链接入口的关键。它的 npm 包名(third-party-library-sample)与对外暴露的 Harmony 包名(@rnoh/third-party-library-sample)相互独立,分别由两份package.json/oh-package.json5声明。
3.1 npm 侧:声明 autolinking 配置与 codegen 脚本
third-party-library-sample/package.json 中有两处与自动链接直接相关的配置:
"scripts": { "codegen-lib": "react-native codegen-lib-harmony --no-safety-check --npm-package-name third-party-library-sample --cpp-output-path ./harmony/library/src/main/cpp/generated --ets-output-path ./harmony/library/src/main/ets/generated --cpp-components-spec-paths ./src/specs/cpp-components --turbo-modules-spec-paths ./src/specs/turbo-modules --arkts-components-spec-paths ./src/specs/arkts-components" }, "harmony": { "alias": "third-party-library-sample", "autolinking": { "cmakeLibraryTargetName": "third_party_library" } }codegen-lib:调用 RNOH CLI 的codegen-lib-harmony命令,根据 specs 目录中的类型声明生成 ETS 与 C++ 的胶水代码(生成的代码输出到harmony/library/src/main/{cpp,ets}/generated),这是三方件能按 RN Fabric / TurboModule 规范工作的前提;harmony.autolinking:自动链接的总开关。工具在扫描node_modules时,只有包内存在该字段才会被纳入链接(详见第五节源码分析)。cmakeLibraryTargetName指定 CMake 侧链接目标名,本示例为third_party_library。
3.2 specs:用 TypeScript 声明原生能力
三方件通过src/specs下三类声明文件描述自身能力:
- ArkTS 组件SelectBox.ts:声明一个名为
SelectBox的原生组件,包含data: SelectItems[]、onChange: DirectEventHandler<Res>等 props,以及一个emitNativeEvent命令(用于 RN 侧下发指令); - C++ 组件QDGestureFloatNativeComponent.ts:声明
QDGestureFloat组件,带stopPercent、stopPercentMax两个浮点 props、onScroll事件和scrollTo命令; - TurboModuleSampleTurboModule.ts 与 SampleAnyThreadTurboModule.ts:分别声明同步方法
add(a, b)与异步方法power(a, b)。
这些声明文件随后被codegen-lib转化为 ETS/C++ 的基类与胶水代码,并被 third-party-library-sample/index.ts 统一导出为SampleTurboModule、SampleAnyThreadTurboModule、SelectBox、QDGestureFloat四个符号,供 RN 侧import { ... } from 'third-party-library'使用。
3.3 Harmony 侧:实现 Package 与组件实例
三方件的 Harmony 源码位于 third-party-library-sample/harmony/library:
- oh-package.json5:声明 Harmony 包名为
@rnoh/third-party-library-sample,main指向Index.ets,并通过相对路径依赖 ReactProject 中安装的@rnoh/react-native-openharmonyHAR; - Index.ets:默认导出
ThirdPartyLibrarySamplePackage——这是自动链接工具需要找到的RNOHPackage 入口类; - ThirdPartyLibrarySamplePackage.ets:继承
RNOHPackage,注册组件描述符工厂、SelectBox的 UI 构建器,以及两个 TurboModule 的工厂 Map; - SelectBox.ets:ArkTS 组件实现,内部通过
RNC.SelectBox.EventEmitter向 RN 回发change事件、通过CommandReceiver接收 RN 下发的emitNativeEvent命令; - SampleTurboModule.ets / SampleAnyThreadTurboModule.ets:分别实现同步
add与 3 秒后返回结果的异步power; - CMakeLists.txt:将源码与
generated目录下的 C++ 代码编译为third_party_library动态库,与package.json中cmakeLibraryTargetName对应; - QDGestureFloatComponentInstance.cpp:C++ Fabric 组件实例,实现带"吸顶/停留"逻辑的滚动容器(
onScrollStop中根据stopPercent/stopPercentMax决定回弹到顶部还是停留)。
四、RN 侧接入:安装三方件并调用
4.1 依赖声明
ReactProject/package.json 通过file:协议安装本地打包产物:
"dependencies": { "react": "19.2.3", "react-native": "0.86.3", "@react-native-oh/react-native-harmony": "0.86.1", "third-party-library": "file:../third-party-library-sample/third-party-library-sample-1.0.0.tgz" }同时使用 RNOH 提供的 Metro 配置 metro.config.js,通过createHarmonyMetroConfig合并默认配置,使 Metro 能正确处理鸿蒙化 bundle 的构建。
4.2 使用示例
ReactProject/App.tsx 展示了三种能力的典型调用方式:
import { QDGestureFloat, SampleAnyThreadTurboModule, SampleTurboModule } from 'third-party-library'; // TurboModule:同步调用与异步 Promise 调用 const result1 = SampleTurboModule.add(2, 4); SampleAnyThreadTurboModule.power(2, 4).then(result2 => setPowerResult(result2)); // Fabric 组件 + RN 向原生下发命令 <QDGestureFloat ref={floatRef} stopPercent={0.5} stopPercentMax={0.75} onScroll={(event) => console.log(event.nativeEvent.offsetY)} > {/* 点击"点击滚到顶"时通过 UIManager.dispatchViewManagerCommand 下发 scrollTo 命令 */} </QDGestureFloat>其中"RN 向原生发送消息"通过UIManager.dispatchViewManagerCommand(findNodeHandle(ref), 'scrollTo', [...])完成;SelectBoxApp.tsx 中SelectBox组件的单选/多选切换与选项上报则分别依赖emitNativeEvent命令和onChange事件回调。
五、NativeProject 侧:自动链接是如何完成的
5.1 触发入口:link-harmony 命令
自动链接由 RNOH HvigorPlugin 在 Harmony 工程构建前调用link-harmony命令触发(命令实现见 packages/react-native-harmony-cli/src/commands/link-harmony.ts)。该命令支持以下参数:
| 参数 | 默认值 | 说明 |
|---|---|---|
--harmony-project-path | ./harmony | OpenHarmony 工程根目录 |
--node-modules-path | ./node_modules | 存放 npm 包的 node_modules 路径 |
--cmake-autolink-path-relative-to-harmony | ./entry/src/main/cpp/autolinking.cmake | 生成的 CMake 自动链接文件 |
--cpp-rnoh-packages-factory-path-relative-to-harmony | ./entry/src/main/cpp/RNOHPackagesFactory.h | C++ 侧 Package 工厂文件 |
--ets-rnoh-packages-factory-path-relative-to-harmony | ./entry/src/main/ets/RNOHPackagesFactory.ets | ETS 侧 Package 工厂文件 |
--oh-package-path-relative-to-harmony | ./oh-package.json5 | Harmony 工程依赖声明文件 |
--exclude-npm-packages/--include-npm-packages | 无 | 排除/仅包含指定 npm 包(二者互斥) |
5.2 链接产物:四个被自动生成/更新的文件
核心逻辑位于 packages/react-native-harmony-cli/src/autolinking/Autolinking.ts,它通过 Mustache 模板批量生成四类文件:
- ETS 侧 Package 工厂(默认
RNOHPackagesFactory.ets):import三方件包名并new出其RNOHPackage实例; - C++ 侧 Package 工厂(默认
RNOHPackagesFactory.h):#include三方件 C++ Package 头文件并make_shared创建实例; - CMake 自动链接文件(默认
autolinking.cmake):定义autolink_libraries(target)函数,为每个库执行add_subdirectory并链接到应用 target; - oh-package.json5 依赖更新:清理无效的
file:node_modules依赖,并为每个扫描到的 HAR 生成@rnoh/xxx: file:相对路径.har形式的托管依赖条目。
这些产物与工程中已有的接线代码相互配合:
- NativeProject/entry/src/main/ets/PackageProvider.ets 与 PackageProvider.cpp 均通过
createRNOHPackages(来自生成的工厂文件)装配三方件; - NativeProject/entry/src/main/cpp/CMakeLists.txt 中
include(".../autolinking.cmake")后再调用autolink_libraries(rnoh_app),从而把三方件的 C++ 库链接进应用。
5.3 扫描与命名规则
Autolinking.prepareInput会遍历node_modules中所有依赖(通过ProjectDependenciesManager.forEachAsync),读取每个包的package.json.harmony.autolinking:
- 未声明该字段、或被
exclude/include名单排除的包会被记为skip,不参与链接; - 声明了的包会扫描其
harmony目录下的.har文件,进而生成链接产物。
对于未显式指定类名/包名的库,工具按以下规则自动推导(见 Autolinking.ts#L474-L502):
- ETS/C++ Package 类名:
npmPackageName转 PascalCase 后追加Package后缀(scoped 包如@scope/name会拼接 scope 与包名); - CMake target 名:
rnoh__+ snake_case 化后的包名; - oh-package 名:默认
@rnoh/+ kebab-case 化后的包名,单个 npm 包内含多个 HAR 时追加--har文件名后缀区分。
六、运行效果与交互行为
启动应用后(见上文截图),可依次验证以下交互,这些行为由QDGestureFloat、SelectBox与两个 TurboModule 协作完成:
- 点击【点击滚到顶】,QDGestureFloat 内的内容滚动到顶部——对应 RN 侧
UIManager.dispatchViewManagerCommand下发的scrollTo命令; - 滚到顶部后向下拉松手,组件根据滚动位置决定停留在中间(
stopPercent)还是回到顶部; - 点击【选项1/2/3】,选项右侧会显示"选中"标记——由 SelectBox 的
@Observed数据与@ObjectLink子项响应式渲染驱动; - 点击【确定】按钮,VSCode 控制台打印当前选中项的 value,如
{"target": 14, "value": [1]}——这是原生侧通过EventEmitter.emit('change', {value})回传给 RN 的onChange事件对象; - 点击【现在是单选】按钮,文案切换为【现在是多选】,同时 RN 通过
emitNativeEvent命令通知原生切换模式,之后可多选; - 再次点击【确定】,控制台打印多选结果,如
{"target": 14, "value": [1,2]}。
此外页面顶部还会展示2 + 4 = 6、2 ^ 4 = 16两个 TurboModule 的调用结果(同步add与 3 秒延迟的异步power),直观验证 JS ↔ 原生双向通信链路。
七、机制小结:一次link-harmony到底做了什么
结合 Autolinking.ts 的实现,可将 RNOH 自动链接归纳为"扫描 → 判定 → 解析 → 生成"四个阶段:
- 扫描:遍历
node_modules下全部依赖,收集harmony目录内的.har文件; - 判定:依据
package.json.harmony.autolinking是否声明、include/exclude名单,决定每个包参与链接还是跳过; - 解析:根据
ohPackageName(字符串或"har 名 → 包名"映射数组)与默认命名规则,为每个 HAR 确定 oh-package 名称与版本策略(本地file:路径或远程版本号); - 生成:渲染 ETS/C++ Package 工厂、
autolinking.cmake,并通过JSON5Writer合并更新oh-package.json5依赖,随后由 RNOH HvigorPlugin 触发 Harmony 工程构建。
正因如此,开发者在接入一个新的 RNOH 三方库时,通常只需"在 RN 工程安装依赖 → 重新构建 Harmony 工程"两步,无需手工维护任何 Package 注册代码——这正是 AutolinkingSample 想要演示的核心价值。若需排查链接结果,可在构建日志中观察link-harmony输出的[link] 包名与[skip] 包名列表,快速确认哪些库被纳入、哪些被跳过。
- OpenHarmony
- 移动开发
- 跨平台
【免费下载链接】ohos_react_native
React Native鸿蒙化仓库
相关推荐
RNOH Autolinking 实战指南:三方 React Native 库接入鸿蒙工程的自动链接全流程
RNOH Autolinking 实战指南:三方 React Native 库接入鸿蒙工程的自动链接全流程 RNOH(React Native OpenHarm
OpenHarmony移动开发跨平台Expo Modules Autolinking 源码级解析:Expo 原生模块自动链接机制与 CLI 实战指南
Expo Modules Autolinking 源码级解析:Expo 原生模块自动链接机制与 CLI 实战指南 expo modules autolinkin
移动开发前端跨平台原生移动marked 自动链接(Autolink)解析深度指南:从 `<http://example.com/>` 到 `<a>` 的源码级全流程
marked 自动链接(Autolink)解析深度指南:从 <http://example.com/ 到 <a 的源码级全流程 导读 本指南以 marked 仓
前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考