RNOH 0.88.0-rc.1 适配教程:把 React Native 0.88.0-rc.1 带上 OpenHarmonya
RNOH 0.88.0-rc.1 适配教程:把 React Native 0.88.0-rc.1 带上 OpenHarmony
对象画像:这不是一个三方库,而是 RNOH 框架本身的版本升级适配——把
ohos_react_native的 0.88 线从对齐上游react-native 0.88.0-rc.0推进到0.88.0-rc.1,范围覆盖 JS 运行时、C++(ReactCommon)与 tester 宿主,最终在 HUAWEI nova 12 真机上跑通并把 5 个提交合入oh-react-native/ohos_react_native的main(MR !1,已合并)。
- 适配分支:
0.88-feature/rc.1(fork:uksri/ohos_react_native)- MR:
oh-react-native/ohos_react_native!1(2026-09-18 合并,merged_byjianguoxu)- 执行时间:2026-09-17 → 2026-09-18;撰写时间:2026-09-18
- 姊妹篇:《RNOH 0.88.0-rc.1 使用指南》(面向升级到 rc.1 的应用开发者)
证据分级声明(沿用系列约定):
- 【记录】引自仓库既有文件 / 平台 API 响应 / 本次执行的真实命令输出,可复核到具体路径或命令;
- 【代码】从仓库源码逐字读出,可
grep验证; - 【复核】静态分析或推理得出的结论,尚未全部复验,单列于 §14,不当既成结论引用。
0. 前言
一句话画像:RNOH(React Native for OpenHarmony)是让 RN 应用跑在 OpenHarmony 上的框架层,本篇记录的是把它 从上游 react-native 0.88.0-rc.0 升级到 rc.1 的全过程——上游 rc.1 只改了 52 个文件,但要把这 52 个文件正确地"接"进 RNOH 的 monorepo(JS overlay + C++ vendor + 补丁体系),并在真机上完成验证与合入。
本篇产出:
| 产出 | 状态 |
|---|---|
适配分支 0.88-feature/rc.1(基于 04797515c,5 个提交,全部带 DCO 签名) | ✅ 已推 uksri/ohos_react_native |
MR !1 → oh-react-native/ohos_react_native:main(20 文件) | ✅ 2026-09-18 已合并 |
tester 真机验证(nova 12 / API 24 / arm64-v8a),版本徽标 RN 0.88.0-rc.1 | ✅ |
PlatformConstantsTurboModule 单测 | ✅ 12/12 |
新增适配文件 packages/react-native-harmony/setup-env.js(rc.1 新模块入口) | ✅ 已随 MR 合入 |
packages/react-native.patch 两处 rc.1 适配修复(写回补丁,保证 init-ws 可复现) | ✅ 已随 MR 合入 |
与系列里三方库文章的两点结构差异,先说清楚:

- 系列 §1 的"适配形态①②③④"是针对三方库的;框架升级适配不属于任何形态,本篇按"上游差异合入 + 构建体系排障"组织内容,章节号仍对齐系列模板(含 7′ 踩坑实录,故为 0–18 共 19 节)。
- 系列 §4 的
adaptation-check.py校验的是三方库仓库结构,对框架 monorepo 不适用,本篇以等价自检替代(见 §4.4)。
1. 为什么做这次升级
【记录】RNOH 0.88 线(oh-react-native/ohos_react_native 的 main)在 2026-09-16 停在对齐上游 0.88.0-rc.0(提交 04797515c,tag v0.88.0-rc.0)。上游随后发布 0.88.0-rc.1,npm 双版本可查:
$ npm view react-native@0.88.0-rc.0 version → 0.88.0-rc.0
$ npm view react-native@0.88.0-rc.1 version → 0.88.0-rc.1
rc.1 相对 rc.0 的增量规模(详见 §5):52 个文件(修改 49 + 新增 3、删除 0),集中在 featureflags 体系(C++/JS/Android 三份)、iOS SPM 构建脚本与版本元数据。工作量预估:
| 工作项 | 预估 | 实际 |
|---|---|---|
| 差异分析 | 0.5h | 0.5h(npm 双包逐文件比对) |
| 依赖与源码落位 | 2h | 3h(pnpm 锁文件 + 子模块镜像 + vendor) |
| 构建排障 | 2h | 5h(九连坑,见 §7′) |
| 真机验证 | 1h | 2h(含发现版本上报缺陷并修复) |
| 提交与 MR | 1h | 2h(平台 fork 规则踩坑,见 §12.4) |
选这个目标的理由与系列"选库流程"同理:rc.1 已发布且无人做——
oh-react-native/ohos_react_native的 main 尚停在 rc.0,npm 侧@react-native-oh/react-native-harmony也未见 rc.1 产物(截至 2026-09-17 查询)。
2. 环境准备
环境搭建(DevEco Studio / OpenHarmony SDK / hdc / 签名 / RNOH_C_API_ARCH)请直接参考官方文档,不在此重写:
环境搭建请参考:RNOH 官方环境搭建
本篇的版本配套(实测通过的组合):
| 项 | 版本 | 出处 |
|---|---|---|
| React Native(上游) | 0.88.0-rc.1(npm 包) | 【记录】npm registry |
| React | 19.2.3 | 【记录】pnpm-workspace.yaml overrides |
| RNOH 框架包 | @react-native-oh/react-native-harmony 0.88.0-rc.1(源码构建) | 【记录】packages/react-native-harmony/package.json |
| Node.js / pnpm | 22.x / 10.3.0(packageManager 钉住) | 【记录】根 package.json |
| DevEco Studio / SDK | 26.x(D:\devs\DevEcoStudio,SDK API 26) | 【记录】本机 |
| compatibleSdkVersion(tester) | 6.1.0(23),实机 API 24 可运行 | 【记录】tester build-profile.json5 |
| Metro | 0.83.7 锁定(沿用系列口径【记录】;本篇未复验 0.83.8+,见 §14) | 《RN三方库鸿蒙适配手把手教程.md》1.1 |
工作区来源:框架仓库 clone 到 短路径 C:\rnoh(为什么必须短路径,见 §7′ 坑⑤)。
3. 仓库从哪来(过程,必配 3 图)
3.1 先分清三条"上游"(过程图 1)
框架在这个生态里有三条容易混淆的线,动手前必须分清:

atomgit.com/oh-react-native/ohos_react_native(0.88 线):main=04797515c,即本次适配的基点(tagv0.88.0-rc.0)。注意它本身是 canonical 仓库CPF-RN/ohos_react_native的一个 fork,0.88 的适配工作在这条 fork 线上推进;gitcode.com/CPF-RN/ohos_react_native(canonical):fork 网络的根项目,main停在 0.86 线(1750e94fd)——MR 评审与合入的网络根,见 §12.4;- 上游 npm 包
react-native:rc.0 / rc.1 两个 tarball 是差异分析的权威依据(§5)。
另外有 7 个 C++ 子模块(boost / folly / fmt / glog / double-conversion / fast_float / hermes)钉在 .gitmodules,直连 GitHub 在本机不可达,经镜像代理(https://gh-proxy.com/https://github.com/...)按 gitlink 钉住的 commit 逐个拉取——必须钉在 superproject 记录的 commit 上,浮动到分支头会在 §7′ 坑⑥⑦ 爆雷。注意嵌套子模块:libs/numeric/ 下还有 conversion / interval / odeint / ublas 四个二级 gitlink,git ls-tree HEAD:libs 只列一级,要用 git ls-tree -r HEAD libs 数全(共 149 个 gitlink)。
3.2 clone 到宿主机,并解开浅克隆(过程图 2)
git clone -b main https://atomgit.com/oh-react-native/ohos_react_native.git
# 若用了 --depth 1(本工作台最初就是),必须解浅:
git fetch --unshallow

浅克隆在这里有两个具体危害:① 系列模板 §3.2 说的 diff 证据拿不到;② 推送被拒——AtomGit 服务端拒绝 shallow update(! [remote rejected] ... (shallow update not allowed)),提交了也推不出去。解浅后 git rev-list --count HEAD = 5860(5858 历史 + 本适配提交后的状态)。
3.3 建分支与目录结构(过程图 3)
分支名沿用系列约定 feat/ohos_<名>_<版本> 的框架变体:0.88-feature/rc.1(对齐 RNOH 社区《仓库分支管理规范》的 ${version}-feature/<name>,规范同时禁止直推 main / *-main / *-stable)。

monorepo 关键目录与本次适配的接触面:
| 目录 | 作用 | 本适配是否触碰 |
|---|---|---|
packages/react-native | 上游 react-native 子模块(gitlink 指向 facebook/react-native) | 版本推进时由 npm 包替代其内容(§6.1) |
packages/react-native-harmony | JS overlay(Libraries/、src/、delegates/、types/ 为 gitignore 的生成物) | ✅ 同步 rc.1 内容 + 新增 setup-env.js |
packages/react-native.patch | 对上游源码的 128 处改动(delegates 化、Harmony 化),init-ws 时应用 | ✅ 两处 rc.1 修复写回(§7′ 坑⑧⑨) |
packages/tester/harmony | tester 宿主(可安装到真机的样例 App),内嵌 react_native_openharmony(框架源码模块) | ✅ 版本串 / 徽标 / 版本常量 |
packages/react-native-harmony-cli / -hvigor-plugin | RNOH CLI 与 hvigor 插件 | ✅ 版本号与 tgz 重建 |
4. 适配结构补全
4.1 如实说明:框架没有"脚手架命令",只有一套生成机制
三方库适配可以手写 11 个文件;框架的正道是复用仓库自带的生成机制,顺序如下(全部是仓库既有脚本,非本篇新造):
pnpm install——安装 workspace 依赖,tester 的 postinstall 会从build-profile.template.json5生成build-profile.json5;pnpm init-ws=git submodule update --init --recursive+pnpm i+pnpm run _integrate-upstream-code+ 重建 hvigor 插件 tgz + 递归setup;_integrate-upstream-code(scripts/integrate-upstream-code.ts)就是框架版的"脚手架":给packages/react-native子模块打react-native.patch,然后把delegates / Libraries / src / types_DEPRECATED(→types)同步进 overlay 包,把ReactCommonvendor 到cpp/third-party/rn/ReactCommon。
本篇因 GitHub 子模块不可达(§3.1),用 npm rc.1 包替代子模块内容复刻了这一机制,见 §6。
4.2 overlay 的"生成物"属性必须先搞清楚
packages/react-native-harmony/.gitignore 明确写着:Libraries/*、types/*、src/*、delegates/* 都是 # To add a new file to one of those directories, use 'git add -f' 的生成目录(仅 Libraries/RegisterPageName/ 与 src/private 的测试/文档白名单例外)。这意味着:
- 全新 clone 的仓库不能直接构建——overlay 是空的(首跑 bundle 即报
Unable to resolve module ./Libraries/Core/InitializeCore,见 §7′ 坑①); - 任何"源码修复"如果只落在生成目录里,等于没有交付——必须写回
react-native.patch或提交为包根的正式文件(§7′ 坑⑧⑨ 的处理原则)。
4.3 本适配需要落位的清单(逐项列路径)
| # | 路径 | 性质 | 说明 |
|---|---|---|---|
| 1 | cpp/third-party/rn/ReactCommon/**(1452 个文件) | 生成物(gitignore) | rc.1 npm 包 ReactCommon/ + react-native.patch 的 ReactCommon 段(128 段中的 50 个既有文件改动 + 若干新增) |
| 2 | overlay Libraries/、src/、delegates/、types/ | 生成物(gitignore) | rc.1 npm 包对应目录 + 补丁(types_DEPRECATED → types,脚本注释明示 0.88 起上游改名、RNOH 保留自身目录名) |
| 3 | packages/react-native-harmony/setup-env.js(18 行) | 正式提交 | rc.1 新增 react-native/setup-env 出口;RNOH 解析器会把该请求重定向到包根,缺失即 bundle 失败(§7′ 坑②)。与包根 index.js / ts.ts / ets.ets 同类,随 files 通配发布 |
| 4 | packages/react-native.patch(128 段中改 2 段) | 正式提交 | jserrorhandler 破环 + RawPropsKey.h 守卫(§7′ 坑⑧⑨),修复必须写回补丁才能让全新 init-ws 复现 |
| 5 | 版本号 ×12(package.json 等)+ pnpm-lock.yaml / oh-package-lock.json5 | 正式提交 | 见 §8 |
4.4 结构自检(等价 adaptation-check.py)
adaptation-check.py 面向三方库仓库,对 monorepo 不适用。本篇用三个等价命令自检(全部可复跑):
# ① 全量补丁能否干净应用于"纯 rc.1 树"(最硬的一条):期望零输出
cd <干净 rc.1 解包目录> && git apply -p3 --check ../ohos_react_native/packages/react-native.patch
# ② 生成目录就位核对:ReactCommon 文件数应为 1452
find packages/tester/harmony/react_native_openharmony/src/main/cpp/third-party/rn/ReactCommon -type f | wc -l
# ③ overlay 关键入口就位
ls packages/react-native-harmony/Libraries/Core/InitializeCore.js packages/react-native-harmony/setup-env.js
①在修复写回补丁后复验通过(0 报错),且补丁应用后的 ReactCommon/jserrorhandler/CMakeLists.txt、ReactCommon/react/renderer/core/RawProps.cpp 与工作台 vendored 文件 逐字节一致(cmp 校验)。
4.5 "零改动证据"的框架版
系列模板要求证明"不改上游接口"。框架版的等价命题是:除声明的适配点外,不额外改动上游源码。证据:
- 上游 rc.1 npm 树 +
react-native.patch全量应用--check通过,即补丁外的上游文件与官方发布逐字节一致; - 本适配对"上游内容"的增量只有两类:①
setup-env.js(包根新增入口,不修改任何上游文件);② patch 内 2 段修复(每一处都在 §7′ 有"现象→根因→修复"记录); Libraries/、src/等生成目录与 rc.1 + patch 的产物一致,未手工增删。
5. 上游差异分析:rc.0 → rc.1 到底改了什么
方法:从 npmmirror 下载 react-native-0.88.0-rc.0.tgz 与 rc.1.tgz,逐文件 diff -qr(比 GitHub 可靠——本机 GitHub 直连不可达,且 npm 包即发布事实)。


合计 52 = 修改 49 + 新增 3、删除 0。按"对鸿蒙适配的落点"归类:
| 落点 | 文件数 | 内容 | 处理 |
|---|---|---|---|
| JS 运行时(进 bundle) | 11 | Libraries/ 4(ReactFabric 三实现 + 版本号)、src/ 6(featureflags、webapis、react-private-interface)、package.json 1(新增 ./setup-env exports) | 随 react-native@0.88.0-rc.1 npm 依赖 + overlay 同步自动带入 |
| C++(vendor 进 .so) | 11 | ReactCommon/react/featureflags/ 8、react/nativemodule/featureflags/ 2、cxxreact/ReactNativeVersion.h 1 | vendor 同步(§4.3#1),版本头实测 Prerelease = "rc.1" |
| 类型 | 2 | types_generated/(新增 FabricUIManager.d.ts、react-private-interface.d.ts) | 随 overlay types/ 同步 |
| Android 专属 | 11 | ReactAndroid/**(featureflags Kotlin/JNI、版本号) | ❌ 鸿蒙无此层,不适用 |
| iOS/Apple 构建脚本 | 14 | scripts/spm/**(新增 ios-deployment-target.js、swiftpm-config.js)+ codegen/setup 脚本 | ❌ 不适用(鸿蒙走 hvigor/CMake) |
| iOS ObjC / 共享头 | 2 | React/Base/RCTVersion.m、FBReactNativeSpecJSI.h | RCTVersion 不适用;JSI 头随 vendor 生效 |
| 版本元数据 | 1 | sdks/hermes-engine/version.properties | 记录项(Hermes 为预编译 .so) |
结论:鸿蒙侧真正要"跟"的是 JS 11 + ReactCommon 11 + 类型 2 + 元数据 1;两个功能性变化点是 rc.1 的 featureflags 扩展与 react-native/setup-env 新模块,后者直接导致一处适配新增(§7′ 坑②)。
6. 架构决策
6.1 为什么"npm 包 + 补丁"而不是"更新子模块"
init-ws 的正规路径要求能克隆 facebook/react-native 子模块(GitHub)。本机 GitHub 直连不可达,而 rc.1 的 npm 包内容 = 官方仓库 packages/react-native/ 的发布物(monorepo 布局,ReactCommon 在 packages/react-native/ 下)。因此:以 npm rc.1 tarball 展开 → git init 提交为基线 → git apply -p3 应用补丁(补丁路径前缀为 packages/react-native/,-p3 恰好剥掉三层)→ 按同步脚本的同款目录映射拷入。验证手段:git apply --check 于纯 rc.1 树零报错。
6.2 修复写回补丁,而不是只改生成目录
rc.1 引入的两处构建阻塞(§7′ 坑⑧⑨)的修复点都在"生成目录"(vendored ReactCommon)里。若只改生成目录:git status 干净、看似无事,但任何一次 init-ws 重新生成就会复现故障。因此修复以 diff 形式写回 packages/react-native.patch(在干净 rc.1 基线仓库里重新生成这两个文件段的 hunk 并拼接),再用"全新树 + 全量补丁 + cmp 逐字节比对 vendored 文件"闭环验证。
6.3 版本上报链路的最小改动原则
真机验证暴露的版本号问题(§11.3)涉及三层:JS bundle 的 ReactNativeVersion(rc.1,自动带入)→ ArkTS 侧常量(RNInstancesCoordinator.ets:245 硬编码,改为 rc.1)→ 下发 JS 的 Platform.constants.reactNativeVersion(PlatformConstantsTurboModule)。修复遵循最小面:ArkTS 常量只改值;TurboModule 按上游契约补 prerelease(§7 对账表),不改调用方。
7. 接口/字段逐一对账
7.1 上游 52 文件 → RNOH 落点对账
见 §5 表格(逐文件 → 落点 → 处理),此处不重复。要点:49 处修改里没有一处落在 RNOH 的 ArkTS/补丁层,即 rc.1 没有动 RNOH 补丁所依赖的上游结构——这是补丁能零冲突应用的根本原因(git apply --check 证实)。
7.2 Platform.constants.reactNativeVersion 契约对账(本篇新增的行为对齐)
真机验证发现徽标只显示 RN 0.88.0-rc.1 的前缀形式(详见 §11.3),排查发现 RNOH 实现与上游契约有偏差:
| 项 | 上游契约(0.88.0-rc.1)【代码】 | RNOH 修复前 | 修复后 |
|---|---|---|---|
| 类型声明 | Libraries/Utilities/Platform.d.ts:{major: number; minor: number; patch: number; prerelease?: string | null | undefined} | — | — |
patch | number | 字符串 '0-rc'(split('.', 3) 把 -rc 卷进第三段) | 0(数字) |
prerelease | 可选字段,上游 Android AndroidInfoHelpers.kt:88 以 major.minor.patch[-prerelease] 拼接 | 缺失 | 'rc.1' |
| RN 自身版本检查 | ReactNativeVersionCheck.js 只比较 major/minor,格式化同样拼 -prerelease | 不受影响 | 不受影响 |
修复位置【代码】:PlatformConstantsTurboModule.ts:18(ReactNativeVersionInfo 接口)、:30(parseReactNativeVersion(),按 - 拆 prerelease、三段转数字、缺失/非数字回退 0)、:67(调用点)。调用链上游:RNInstancesCoordinator.ets:245 的版本常量由 '0.88.0-rc.0' 修正为 '0.88.0-rc.1'(该值经 RNOHCoreContext 下发给 TurboModule)。
7′. 构建踩坑实录(九连坑)
以下全部为本次适配实际发生的阻塞,按时间序。每条按「现象 → 根因 → 修复 → 验证」。先上全景图:

坑① overlay 是空的:Unable to resolve module ./Libraries/Core/InitializeCore
- 现象:首次
react-native bundle-harmony报Unable to resolve module ./Libraries/Core/InitializeCore from ...\react-native-harmony\index.js。 - 根因:overlay 的
Libraries/*、src/*等是init-ws生成物(§4.2),全新 clone 为空,index.js的 require 自然断链。 - 修复:按
integrate-upstream-code.ts的目录映射,把"rc.1 + 全量补丁"的Libraries/ src/ delegates/ types_DEPRECATED→types拷入 overlay。 - 验证:bundle 进入下一阶段(报出新的、更深的错误 = 前一关已过)。
坑② react-native/setup-env 解析失败(rc.1 新增模块)
- 现象:
Unable to resolve module react-native/setup-env from ...\ReactFabric-prod.js(rc.1 的 ReactFabric 新增该 require)。 - 根因:RNOH 的 metro 解析器把
react-native/*请求重定向到 overlay 包根;rc.1 的package.jsonexports 新增./setup-env,而 overlay 根没有对应文件。 - 修复:新增包根
setup-env.js(18 行),内容与上游src/setup-env.js等价、指向 overlay 内同步而来的src/private/setup/setUpDefaultReactNativeEnvironment;作为正式提交交付(§4.3#3)。 - 验证:bundle 生成成功(
bundle.harmony.js,2,308,166 字节)。
坑③ hvigor 依赖自举被 pnpm 拦截:ERR_PNPM_IGNORED_BUILDS
- 现象:hvigor 配置阶段执行的
pnpm install报Ignored build scripts: agent-browser / canvas / esbuild后失败。 - 根因:hvigor wrapper(
~/.hvigor/wrapper/tools/10.28.2)自带 pnpm,默认拒绝未白名单的构建脚本。 - 修复:wrapper 目录
package.json加pnpm.onlyBuiltDependencies白名单(本机环境处理,不入库)。 - 验证:配置阶段继续推进;后续又报
Cannot find module '@rnoh/hvigor-plugin',按系列先例在hvigor-config.json5加'hvigor.dependency.useNpm': true解决(该属性为本机环境项,未随 MR 提交)。
坑④ 路径长度超限:The length of path exceeds the maximum length: 259
- 现象:hvigor 报
00306001 Specification Limit Violation。 - 根因:工作区在
Desktop\tm\rn088\ohos_react_native,深度路径 + 嵌套生成目录超 259 字符限制。 - 修复:工作区整体迁至
C:\rnoh。注意 Junction 无效——hvigor 会把路径规范化回真实长路径,必须物理短路径(robocopy 复制后修复子模块 gitdir 引用)。 - 验证:同一条 cmake 命令不再报限长。
坑⑤ include could not find requested file: BoostRoot
- 现象:entry 的 CMake 配置报
boost/CMakeLists.txt:20 (include): BoostRoot缺失。 - 根因:boost superproject 的
CMakeLists.txt:20依赖tools/cmake子模块(BoostRoot.cmake所在),而该子模块从未拉取。 - 修复:按 gitlink(
69f16e28)经镜像补拉tools/cmake。 - 验证:该错误消失,配置推进到编译期。
坑⑥ Target "boost_date_time" links to: Boost::numeric_conversion but the target was not found
- 现象:CMake generate 阶段报 date_time / lexical_cast 引用了不存在的
Boost::numeric_conversion。 - 根因:
BoostRoot.cmake会做依赖闭包扫描——locale → thread → date_time → numeric_conversion;而numeric_conversion位于libs/numeric/conversion(嵌套 gitlink)。一级git ls-tree HEAD:libs只有 145 个 gitlink,递归共 149 个,嵌套的 4 个(numeric/conversion、interval、odeint、ublas)未拉取。闭包里"应该有"的 target 因子模块缺失而真缺,字母序先处理的 date_time 便报 target 未找到。 - 修复:递归补齐 4 个嵌套子模块。其中
numeric_conversion的 gitlink 名带下划线(仓库boostorg/numeric_conversion),按连字符仓库名拉取会 404/not our ref;同时对不存在的对象哈希做浅拉取会被 GitHub 拒绝,改用完整仓库浅 fetch 解决。 - 验证:
git ls-tree -r HEAD libs | awk '$1=="160000"' | wc -l= 149,全部检出在钉住 commit;CMake generate 通过。
坑⑦ CMake 目标环:react_cxxreact ↔ jserrorhandler(rc.1 引入)
- 现象:
The inter-target dependency graph contains the following strongly connected component (cycle): react_cxxreact ↔ jserrorhandler ... Cyclic dependencies are allowed only among static libraries.(两者都是 OBJECT 库)。 - 根因:rc.1 起上游
react_cxxreact新增链接jserrorhandler;而 RNOH 补丁让jserrorhandler反向链接react_cxxreact(为取<cxxreact/ErrorUtils.h>头)。rc.0 时代单向不成环,rc.1 成环。 - 修复:jserrorhandler 侧只需要头文件——把链接依赖改为
target_include_directories(jserrorhandler PRIVATE ${REACT_COMMON_DIR}/cxxreact),修复写回react-native.patch(§6.2)。 - 验证:CMake generate 通过;全新 rc.1 树全量补丁
--check通过且与 vendored 文件逐字节一致。
坑⑧ RawPropsKey.h 不存在(补丁引用了上游没有的头)
- 现象:
RawProps.cpp:12:10: fatal error: 'react/renderer/core/RawPropsKey.h' file not found。 - 根因:补丁给
RawProps.cpp增加了#include <react/renderer/core/RawPropsKey.h>,但该头在上游 0.88 的 rc.0 与 rc.1 中都不存在(以 GitHub rc.0/rc.1 tag 的git ls-tree核实,npm 包同样没有)。它只服务于补丁的PARALLELIZATION_ON并行化分支。 - 修复:把该 include 收进同一个
#ifdef PARALLELIZATION_ON守卫(本构建未开并行化,语义不变),写回补丁。 - 验证:编译越过该文件;后续唯一编译错误是坑⑨。
坑⑨ boost 线程原语报错:pthread_setcancelstate 未声明
- 现象:
boost/core/detail/sp_thread_sleep.hpp:73:5: error: use of undeclared identifier 'pthread_setcancelstate'。 - 根因:漏了
packages/boost.patch——init-ws机制要求把它打到 boost 子模块上(补丁内容即 OHOS musl 的 pthread 兼容层),手动拉子模块的流程里漏了这一步。 - 修复:
git apply packages/boost.patch于 boost 子模块根。 - 验证:错误消失;随后 BUILD SUCCESSFUL(50 任务,增量 3m21s)。
速查表
| # | 阶段 | 症状关键词 | 一句话修法 | 是否入库 |
|---|---|---|---|---|
| ① | bundle | InitializeCore 解析失败 | 跑 overlay 同步(init-ws 机制) | 否(生成物) |
| ② | bundle | react-native/setup-env 解析失败 | overlay 包根补 setup-env.js | ✅ |
| ③ | hvigor | ERR_PNPM_IGNORED_BUILDS / 找不到 hvigor-plugin | wrapper 白名单;hvigor.dependency.useNpm | 否(本机) |
| ④ | hvigor/cmake | 路径超 259 | 工作区挪短路径(Junction 无效) | 否(本机) |
| ⑤ | cmake | 找不到 BoostRoot | 补 tools/cmake 子模块 | 否(子模块) |
| ⑥ | cmake | Boost::numeric_conversion 未找到 | 补齐嵌套 libs/numeric/*(下划线仓库名) | 否(子模块) |
| ⑦ | cmake | react_cxxreact ↔ jserrorhandler 目标环 | 补丁改为仅注入 include 路径 | ✅(patch) |
| ⑧ | 编译 | RawPropsKey.h not found | include 收进 PARALLELIZATION_ON 守卫 | ✅(patch) |
| ⑨ | 编译 | pthread_setcancelstate 未声明 | 应用 packages/boost.patch | 否(子模块补丁) |
8. 版本号与依赖提升
提升清单(0.88.0-rc.0 → 0.88.0-rc.1,共 12 个文件)【记录】:
| 文件 | 提升内容 |
|---|---|
根 package.json(pnpm.overrides)+ packages/react-native-harmony / -cli / -hvigor-plugin(含 lock)/ -sample-package / template/template / tester 的 package.json | version 与 react-native、@react-native/* 依赖 |
packages/tester/harmony/hvigor/hvigor-config.json5 | 插件 tgz 文件名 rnoh-hvigor-plugin-0.88.0-rc.1.tgz |
packages/tester/harmony/react_native_openharmony/oh-package.json5 + build-profile.json5 | version 与 -DVERSION_STRING="0.88.0-rc.1"(release 档) |
packages/tester/harmony/oh-package-lock.json5 | ohpm 锁定 |
pnpm-lock.yaml | 全量解析(190 处 rc.1 引用,0 处 rc.0 残留) |
RNInstancesCoordinator.ets:245 | ArkTS 下发 JS 的版本常量(§7.2) |
三个坑:
minimumReleaseAge: 4320(pnpm-workspace.yaml,“发布满 3 天才可安装”)会静默跳过刚发布的 rc.1、继续装 rc.0——安装时不报错,bundle 阶段才炸。临时置 0 安装后恢复原值(该配置是上游供应链保护,不应顺手删除)。pnpm-lock.yaml的两万行 diff 是假象:pnpm 10 写单引号、仓库基线是双引号。归一引号后真实差异只剩 rc.1 解析与 peer 哈希;用pnpm install --frozen-lockfile验证锁文件与package.json一致(通过)。- hvigor 插件 tgz 必须重建:
pnpm run _recreate-hvigor-plugin产出rnoh-hvigor-plugin-0.88.0-rc.1.tgz,否则hvigor-config.json5引用断链。
9. 交付文件说明(与三方库模板的差异)
框架仓库已自带系列模板要求的多数交付物,本适配的交付重心因此不同:
| 系列模板要求 | 本仓库现状 | 本适配动作 |
|---|---|---|
README.OpenHarmony.md / _CN.md(七节) | ✅ 仓库既有(0.88 线随 rc.0 已带) | 未改 |
README.OpenSource(7 字段) | ✅ 仓库既有 | 未改 |
spec.json / 代码检查报告 / 契约测试 | tester 自带测试体系 | 补充单测用例(§10) |
.har 预构建 | 仓库以源码分发;官方 har 走发布流程 | 不提交构建产物(遵循仓库 .gitignore) |
react-native.patch(框架特有) | 128 段 | ✅ 2 段修复(本适配的核心交付) |
setup-env.js(rc.1 新增入口) | — | ✅ 新增 18 行 |
CHANGELOG.md / release-notes | 维护者发布流程 | 未代写;维护者合并后已补 664709a7e docs: add 0.88.0-rc.1 release notes |
10. 验证
10.1 单元测试(12/12)
PlatformConstantsTurboModule.test.ts 更新:新增 reports the prerelease separately from patch(0.88.0-rc.1 → {major:0, minor:88, patch:0, prerelease:'rc.1'}),并把原先固化 split('.', 3) 旧行为的两个用例改为断言新契约(非数字段回退 0;仍只取前三段)。

10.2 产物级证据
- bundle(2,308,166 字节)内含
prerelease='rc.1'(grep -ao实测); - vendored
ReactCommon/cxxreact/ReactNativeVersion.h:Prerelease = "rc.1"; - ArkTS 字节码(
ets/modules.abc)含0.88.0-rc.1;libhermestooling.so含0.88.0-rc.1字符串。 - ⚠️ 如实记录:debug 构建(entry 驱动)下
librnoh_core.so的RNOH_LIB_VERSION=标记串为空——entry/build-profile.json5的 cmakearguments未传VERSION_STRING,CMake 从oh-package.json5推导的值在该链路为空(build.ninja 实测-DVERSION_STRING=\"\")。仅影响strings类诊断标记,不影响任何运行行为;修复建议见 §14。
10.3 真机记录
| 项 | 值 |
|---|---|
| 设备 | HUAWEI nova 12(BLK-AL00) |
| 系统 | HarmonyOS 6.1.0.135(SP8C00E120R2P6),API 24,arm64-v8a |
| 安装包 | entry-default-signed.hap(50,037,089 字节,debug 档,调试签名) |
| 启动 | aa start -b <bundleName> -a EntryAbility 正常;hilog 可见 MountingManagerCAPI.cpp:210> Mutation (type:INSERT ...) 连续 Fabric 挂载【记录】 |
| 交互 | uitest uiInput click 进入 AccessibilityInfo 测试页:11 个测试项渲染、按钮可点、‹ Back 可返回 |


11. Demo:tester 在真机跑起来
tester 是仓库自带的宿主(等价三方库文章里的"宿主工程"),步骤:
- 生成内嵌 bundle(tester 从 rawfile 加载
bundle.harmony.js,不依赖 metro 常驻):
cd packages/tester && RNOH_TESTER_ONLY__TARGET_PLATFORM=harmony npx react-native bundle-harmony --dev=false --minify=true - 构建:
hvigorw --mode module -p module=entry@default -p product=default -p buildMode=debug assembleHap(本机构建脚本固定DEVECO_SDK_HOME与 DevEco 自带 node/ohpm 的 PATH)。 - 签名与设备三件套(系列已知坑,本篇全部再踩一遍,方案沿用):调试 profile 必须含本机 UDID(发布档会报
no signature file);hdc install要装-signed.hap;abiFilters要含 arm64-v8a(模拟器是 x86_64)。另有一坑:签名档绑定的bundleName必须与AppScope/app.json5一致,否则报bundleName ... does not match the bundleName in the generated SigningConfigs(本机以调试档对应 bundleName 本地化解,该改动不入库)。 - 安装与启动:
hdc install -r ...entry-default-signed.hap→aa start。
11.3 真机暴露的版本上报缺陷(本篇最有价值的发现)
首装后徽标显示 RN 0.88.0-rc 而非 rc.1。排查链:徽标(Navigation.tsx:173)→ Platform.constants.reactNativeVersion(TurboModule)→ ArkTS 常量(RNInstancesCoordinator.ets:245)。发现两个独立问题:
- 常量硬编码
'0.88.0-rc.0'未随升级修改(§7.2,已修复——这也验证了系列教训:版本提升时--include扫描必须覆盖.ets/.ts源码,不能只扫 json/yaml); - TurboModule 用
split('.', 3)解析,0.88.0-rc.1被截成patch:'0-rc'且prerelease丢失——rc.0 与 rc.1 的显示完全相同,与上游契约(§7.2 对账表)不符。
修复(契约对齐 + 徽标按上游 ReactNativeVersionCheck 格式化)后重装,徽标显示 RN 0.88.0-rc.1(见 §10.3 截图),单测 12/12。两处修复即 MR 的第 4、5 个提交。
12. 提交与发布
12.1 提交内容甄别
| 处理 | 内容 |
|---|---|
| ✅ 提交 | §8 版本提升 15 文件、react-native.patch 2 段修复、setup-env.js、RNInstancesCoordinator.ets 常量、README 版本声明、单测更新 |
| ❌ 不提交 | 本机环境项:hvigor useNpm、调试签名的 signingConfigs、本地 bundleName、abiFilters、CRLF 噪声(oh-package.json5 等 2 处还原)、robocopy 误删的 8 个跟踪文件(先还原) |
| 🚫 绝不提交 | 构建产物(.cxx/build/oh_modules)、token、签名材料 |
12.2 提交结构(5 个,Conventional Commits + Signed-off-by)
9c1bd1e2 chore(Upgrade) 版本提升(含 ArkTS 常量与 README)→ 214d0692 fix(CMake) 两处构建阻塞 → 32916232 feat(Config) setup-env → fa971a52 fix(TurboModules) prerelease 契约 → 75fa3f87 fix(Examples) tester 徽标。commitlint 本地通过(subject 英文、body 含影响范围、DCO 签名)。
12.3 推送坑:浅克隆被服务端拒绝
git push 报 shallow update not allowed——工作台是 depth 1 克隆。git fetch --unshallow(补全 5858 个历史提交)后推送成功。推框架仓库前先确认非浅克隆(git rev-parse --is-shallow-repository)。
12.4 MR 坑:兄弟 fork 之间不能互发 MR
目标仓库 oh-react-native/ohos_react_native 是 CPF-RN/ohos_react_native 的 fork(0.88 线所在地),用户自己的 uksri/ohos_react_native 也是 CPF-RN 的 fork——兄弟 fork 之间无法建 MR(平台一律路由到 fork 网络根项目,导致 base 变成 0.86 线的 main、diff 膨胀到 124 文件;本篇先后误建 #3491/#3492/#3493 并全部关闭)。正确做法:fork 一份目标仓库本身作为载体(uksri/ohos_react_native-rc1,父仓库恰为目标),推送唯一命名分支(0.88-feature/rc1-org,避免与旧 fork 同名分支歧义),再以 head = uksri/ohos_react_native-rc1:0.88-feature/rc1-org 的完整写法调平台 API 建 MR——MR !1 应声而生,20 个文件。
12.5 结果
- MR !1 于 2026-09-18 06:46(UTC+8)被
jianguoxu合并【记录:GitCode APIstate: merged/merged_by]:

- 维护者随后在 main 顺次追加
664709a7e docs: add 0.88.0-rc.1 release notes等 3 个文档提交; - 遗留:仓库当前无
0.88-main/0.88-feature线性分支,0.88 线的后续合入方式以维护者安排为准(见 §14)。
13. FAQ(现象 → 根因 → 修复 → 验证)
Q1:真机上版本徽标只显示 RN 0.88.0-rc,看不到 rc 序号?
现象如题。根因有二:ArkTS 版本常量漏升(RNInstancesCoordinator.ets:245)+ PlatformConstantsTurboModule 的 split('.', 3) 截断且 tester 徽标只渲染三段数字。修复:常量对齐 rc.1;TurboModule 按上游契约输出 patch: number + prerelease;徽标按上游 ReactNativeVersionCheck 格式化。验证:真机徽标 RN 0.88.0-rc.1,单测 12/12。(来源:本篇 §11.3)
Q2:pnpm install 后 bundle 仍按 rc.0 解析?
现象:依赖已写 rc.1,安装不报错但产物是 rc.0。根因:minimumReleaseAge: 4320 让 pnpm 跳过"发布未满 3 天"的 rc.1。修复:临时 minimumReleaseAge: 0 安装后恢复。验证:grep -c '0.88.0-rc.0' pnpm-lock.yaml = 0。(来源:§8)
Q3:hvigor/cmake 报"路径超过 259"?
根因:深层工作区。修复:物理迁移到短路径(如 C:\rnoh);Junction 无效(hvigor 会规范化回真实路径)。验证:原命令不再报 00306001。(来源:坑④)
Q4:CMake 报 Boost 相关 target/文件找不到?
两个子坑:BoostRoot 缺 → 没拉 tools/cmake 子模块;Boost::numeric_conversion 缺 → 没拉嵌套 libs/numeric/*(注意仓库名 numeric_conversion 带下划线)。修复:按 git ls-tree -r 补齐全部 149 个 gitlink 并钉住 commit。验证:git am/构建通过。(来源:坑⑤⑥)
Q5:全新检出按 init-ws 构建,rc.1 还是构建失败?
若 MR 未合入会复现坑⑦⑧——两处修复已写回 packages/react-native.patch,合入后不存在此问题;若从旧基线操作,应用本篇 §4.3 的补丁或 git am 补丁系列。(来源:§6.2)
Q6:给 oh-react-native/ohos_react_native 提 MR 被路由到 CPF-RN?
根因:两者是 fork 网络,平台只允许 fork → 根项目的 MR。修复:fork 目标仓库为载体 + head 用 owner/repo:branch 完整写法。验证:MR base 显示目标仓库、文件数符合预期。(来源:§12.4)
14. 复核发现(未全部复验,单列)
| # | 项 | 状态 |
|---|---|---|
| 1 | debug 构建 librnoh_core.so 的 RNOH_LIB_VERSION= 标记为空(entry 未传 VERSION_STRING,CMake 推导链路为空) | 已定位(build.ninja 实测),未修复;仅影响诊断标记 |
| 2 | compatibleSdkVersion 6.1.0(23) 下仅在 API 24 实机验证,未在 API 23 设备验证 | 未验证 |
| 3 | Release / debugOptimized 档构建与 har 产物安装 | 未验证(本篇仅 debug HAP) |
| 4 | Metro 锁 0.83.7 的口径在 0.88 线是否仍成立 | 沿用【记录】,未复验 |
| 5 | canonical CPF-RN main 仍为 0.86 线,0.88 线合入节奏与 0.88-* 分支规划 | 待维护者 |
| 6 | docs/Samples/** 的示例工程仍钉 rc.0(上游 rc.0 发布提交亦未动它们) | 待维护者 |
| 7 | 本机 pre-push 钩子 verify 的两类既有失败(CHANGE_INFO 未注入导致 cpp-formatting 必失败;tester typecheck 130 个既有错误,含 Navigation.tsx 一处经还原对照确认的既有报错) | 与本适配无关,已如实标注 |
15. 成果与沉淀
| 产出 | 状态 | 备注 |
|---|---|---|
| 0.88.0-rc.1 适配(5 提交 / 20 文件) | ✅ 已合入 oh-react-native/ohos_react_native:main(MR !1,merged 2026-09-18) | 含维护者后续 release-notes 提交 |
真机可运行 tester(徽标 RN 0.88.0-rc.1) | ✅ nova 12 实测 | 截图见 §10.3 |
PlatformConstants 契约对齐 + 单测 | ✅ 12/12 | 对上游类型与 Android/iOS 实现三重对账 |
react-native.patch rc.1 兼容(2 处) | ✅ | 干净 rc.1 树 --check 通过 + 逐字节比对 |
| 九连坑方法论 | ✅ 本篇 §7′ | 子模块钉 commit / 嵌套 gitlink / 补丁写回原则可复用 |
补丁系列(git format-patch 5 个) | ✅ 已存工作台 rn088/pr-patches/ | 干净基点套用验证通过 |
载体 fork uksri/ohos_react_native-rc1 | ✅(MR 合并后可删) | 兄弟 fork 限制的过渡产物 |
16. checklist(可复用给"框架版本升级适配")
代码侧
- 上游 delta 用 npm 双 tarball 逐文件比对(不凭 release notes)
- 每个 delta 文件标落点:JS / C++ / 类型 / 平台不适用
- 子模块按 gitlink 钉 commit(含嵌套 gitlink,
ls-tree -r数全) - 平台专属补丁(如
boost.patch)确认已应用 - 源码修复写回 patch,并在"干净上游树 + 全量补丁"上
--check+ 逐字节比对 - 版本号提升覆盖 全部形态:package.json / oh-package / hvigor tgz / build-profile 版本串 / ArkTS 硬编码常量
- 行为对齐以上游类型 + 上游双端实现 + RN 自身消费代码三重对账
交付侧
- Conventional Commits + DCO;subject 英文、body 含影响范围
- 提交甄别:本机环境项 / CRLF 噪声 / 构建产物一律不进
- 非 shallow 仓库再推送(服务端拒 shallow update)
- MR 目标仓库与 fork 关系先查清(兄弟 fork 需载体 fork +
owner/repo:branch) - 真机记录:设备型号 / API / ABI / 安装包字节数 / 启动与交互 / 截图
- 未复验项如实单列(§14)
17. 参考
- 上游:
react-native@0.88.0-rc.1(npm)、facebook/react-nativetagv0.88.0-rc.1 - 本适配仓库:
oh-react-native/ohos_react_native(0.88 线)、MR !1 - fork:
uksri/ohos_react_native(分支0.88-feature/rc.1)、载体uksri/ohos_react_native-rc1 - 环境文档:RNOH 官方环境搭建
- 系列规范:三方库技术文章 README;姊妹篇:RNOH 0.88.0-rc.1 使用指南
- 同系列对照:
react-native-screenshot-aware(构建四连坑)、react-native-video-duration(真机四连坑)——本篇的"九连坑"是构建期+真机期的合流
更多推荐


所有评论(0)