两个多月前,我写过一篇文章,讲我们团队怎么让深度使用 Expo 的项目跑上 HarmonyOS:《Expo 官方不支持鸿蒙?我用一个开源 CLI,让 Expo 项目复用一套代码跑上 HarmonyOS》。当时打了个比方------RNOH 帮我们搭好了「RN → 鸿蒙」的桥,但「Expo → 鸿蒙」这截桥,没人修。于是我写了一个 expo-harmony-cli,把这截桥修通了。
两个多月过去,这个 CLI 从 1.0 迭代到了 1.5.1,发了七个版本。这篇文章聊聊它长出了什么:双 SDK 基线、工程化护栏,以及桥面下那些不踩不知道的运行时暗坑。
如果你没读过上一篇也不要紧,一张表对齐认知:
| 第一篇文章时 | 现在 | |
|---|---|---|
| Expo 基线 | 仅 SDK 52 | SDK 52 + SDK 54 双版本 |
| React Native / RNOH | 0.77.1 / 0.77.71 | 0.77.x 与 0.82.x 并行 |
| 构建主路径 | CLI 自有链路 | SDK54 直接用官方 Expo 命令 |
| 原生插件链接 | 内置映射表 | 官方 link-harmony 优先 + 映射表补位 |
| 诊断与保护 | 无 | env / doctor、漂移阻断、事务写入 |
| 生成项目质量兜底 | 靠人肉检查 | 装后自动 runtime probes 校验 |
一句话概括这两个月的主题:从「能跑」到「敢用」。
一、双 SDK 时代:桥通到了 RN 0.82
第一篇文章的基线是 Expo SDK 52(RN 0.77.1 / RNOH 0.77.71)。但现实是,Expo 生态在往前走,SDK 54(RN 0.82)来了,新项目想用新版本,存量项目还压在旧版本上------只支持一个基线,等于逼一半人离开。
于是 1.4.0 做了双 SDK:

bash
npx expo-harmony-cli create my-app --sdk 54 # 新项目,上 SDK54
npx expo-harmony-cli my-harmony-app --sdk 52 # 存量基线,保持 legacy 流程
| Expo | React Native | RNOH | 定位 |
|---|---|---|---|
| SDK 52 | 0.77.x | 0.77.x | 存量项目,legacy 全流程 |
| SDK 54 | 0.82.x | 0.82.x | 推荐基线,真机已验证 |
这背后不是「一个参数」那么简单:patches 按 SDK 分目录(content/patches/sdk-52/ 与 sdk-54/)、鸿蒙原生模板分版本(templates/harmony-sdk-52/ 与 harmony-sdk-54/)、兼容表按版本分表维护------每一层都要版本对齐,错一档就是白屏。
更重要的一个决策在 1.5.0:SDK54 的主路径,全面退回官方命令。
bash
# SDK54 的日常就是标准 Expo 工作流
npx expo prebuild --platform harmony # 生成鸿蒙原生工程
npx expo run:harmony # 构建安装到鸿蒙设备
npx expo start # 日常开发起 Metro
创建走官方 create-expo-app@5.0.0,构建走官方 expo prebuild / run / start,CLI 只做官方不做的事:注入鸿蒙基线、管理精确版本的 package patches、校验产物。说白了就一句话------能蹭官方的绝不自己造,自己只造官方没有的。这样 Expo 官方往前走,用户跟着受益,CLI 不用反复追。
诚实说一下限制:
- SDK54 的公开保证范围是 fresh 的
default/blank-typescript模板。旧 SDK54 项目只诊断、不自动迁移,建议 fresh create 后迁移业务代码;SDK55 及以上直接拒绝,不装兼容; - Default 模板里的
expo-image目前只替换为 RNOH 可用的 Image 两处,本版本不提供 expo-image 的 Harmony backend------它是我们下一步的攻坚点。
二、桥上装了护栏:工具的边界感
「CLI 生成的工程,会不会哪天把我手写的代码覆盖了?」------这是脚手架类工具被问得最多的问题,也是从「能跑」到「敢用」之间真正的那道坎。1.2.0 用一套「强迫症」级的机制回答了它。
你的地盘,它不碰。 自定义原生 Package 注册在 PackageProvider.ets / PackageProvider.cpp,永远归用户管理,CLI 不覆盖,模板里还附了注册示例。
它的地盘被你改了,它会拦住。 CLI 托管的 autolinking 文件(RNOHPackagesFactory.ets/.h、autolinking.cmake)和 oh-package.json5 里的托管条目,一旦被手动修改,sync / install / uninstall 会保护性阻断,提示你还原修改或显式 --force------而不是默默覆盖你的修改,让你莫名其妙丢代码。
写入是事务性的。 五阶段事务:暂存 → 备份 → 替换 → 状态原子落账 → 清理,任一阶段失败自动回滚,磁盘上不会出现「半成品」工程。上次跑到一半断了?下次启动自动清理遗留的暂存、还原备份。
生成完还会自我检查。 SDK54 创建项目后自动跑 runtime probes,校验 patch 是否生效、版本是否一致------失败直接报错,而不是静默产出一个「看起来创建了、跑起来白屏」的坏项目。
再加上两个诊断命令:
bash
npx expo-harmony-cli env # 体检:node / hvigor / ohpm / hdc 逐项检查,给修复建议
npx expo-harmony-cli doctor # 会诊:环境汇总 + 项目诊断,按优先级给下一步
退出码是分级的:0 全部通过、1 存在失败、2 仅有警告------一行 shell 就能接进 CI,鸿蒙构建环境自动巡检。
改哪儿、谁管,边界清楚;出问题,可回滚。工具先管住自己的手,别人才敢把工程交给它。
三、原生链接:官方优先,自研补位
鸿蒙适配上最碎的活儿是三方库:一个库带不带鸿蒙原生代码、要不要注册进 RNOHPackagesFactory、CMake 怎么接------每个库查一遍,一天就没了。
1.3.0 把原生链接改成了「官方优先」的三级策略,sync / prebuild / install / uninstall 统一走这条链路:
- 官方优先 :项目里装了 RNOH 官方
link-harmony的包(package.json带harmony.autolinking声明),优先交给官方 CLI 注册,官方结果原样保留; - 自研补位:官方没覆盖的,自动查内置映射表补充注册,以锚点方式插入官方产物,不改写官方已经成功的注册;
- 绝不静默:两者都没覆盖的,逐包报告原因、给出适配指引------宁可明确告诉你「这个没覆盖」,也不假装一切正常。
官方产物里的临时路径会自动改写为项目相对路径,oh-package.json5 的受管合并、npm 包名与 OHPM 包名的差异归一,也都自动处理。甚至旧式适配包在 ArkTS 严格类型检查下会编译失败的问题(新接口方法缺失),生成代码也做了返回类型对齐。
官方和自研不是二选一,是接力:官方修主干,社区补支路,谁都没覆盖的高声喊出来。
四、桥面下的三个暗坑:鸿蒙运行时排障实录
这一节是干货,献给正在手动适配 RNOH 的同学。以下三个坑,手动适配几乎必然撞上------它们现在都被 CLI 内置修复,但每个都值得知道根因。
坑一:FormData 上传直接崩。 现象是鸿蒙端一调文件上传就挂。根因在 RNOH 的 XHR 实现:FormData 挂到 XHR 上的行为链不完整。修法是注入 harmony-form-data.js ESM shim,在 setUpXHR 阶段补齐行为------1.4.0 起随模板注入。
坑二:ExpoAsset 资源 404。 现象是 Expo 资源体系加载不出图片,日志里一片 404。根因是 Expo 的资源解析不认识鸿蒙的包结构,资源 URL 拼出来就是错的。修法是给 ExpoAsset 注入 harmony shim,把资源解析重定向到鸿蒙包内路径。
坑三:Image / PixelRatio 全体罢工(最深的一个)。 现象最诡异:页面能跑,JS 能执行,但 Image 不渲染、PixelRatio 拿不到值。排查到最后,根因在 Metro 配置:CLI 的 metro-config 在某次重构中丢掉了 RNOH 的 serializer 配置,导致 InitializeCore 初始化链路断裂------平台模块没有按 RNOH 期望的方式进入 bundle。修法是 Metro 初始化模块按平台选择,鸿蒙端恢复 RNOH serializer(1.5.0 修复,同时非鸿蒙平台不再加载鸿蒙专属初始化)。
第三个坑的教训值得单独说:「配错一行 Metro 配置,整个图片体系消失」,而且报错位置离根因十万八千里。这也是我认为脚手架真正的价值所在------
把坑焊死在模板里,让后来人无坑可踩。你不用成为踩坑的人,只需要享受坑被填平的路。
五、两个月的成绩单
照例坦诚亮数据:
- GitHub 66 star 、1 fork;npm 月下载 600+;
- 从 0.2.5 到 1.5.1,7 个 release,平均九天一个;
- 第一篇文章里提过的「王牌智剪 AI」仍在华为应用市场持续运营迭代,SDK54 基线已在真机验证通过。
数字不大,但每一个都来自真实的开发者和真实的设备。对一个解决「官方没顾上的缝隙」的开源工具来说,这个增速我们满意------说明这道缝隙是真的,这截桥真的有人要走。
六、五分钟上手(SDK54)
bash
# 1. 创建:官方 create-expo-app + 鸿蒙基线注入
npx expo-harmony-cli@latest create my-app --sdk 54 --template default --pnpm
# 2. 生成鸿蒙原生工程
cd my-app
npx expo prebuild --platform harmony
# 3. 构建安装到鸿蒙设备(原生代码或依赖变更后重新执行)
npx expo run:harmony
# 4. 日常开发:起 Metro,JS 改动即时生效
npx expo start

装个三方库试试:npx expo-harmony-cli install react-native-gesture-handler------适配策略(alias-only / native / patch-only / unsupported)自动判断,原生注册按上一节的三级策略完成。完整的命令手册在仓库 docs/guide.md,随 npm 包分发,离线可查。
国内网络不方便访问 GitHub 的话,Gitee 和 AtomGit 都有同步镜像;npm 可正常 npx 直连使用。
七、写在最后
两个多月前那截「Expo → 鸿蒙」的桥,现在通了双车道(双 SDK)、装了护栏(诊断与保护)、填了桥面的坑(运行时修复)。但鸿蒙生态的河还很宽:expo-image 的 Harmony backend、SDK55、更多三方库的适配......每一块都欢迎一起来修。
- GitHub:stonehill-2345/expo-harmony-cli
- npm:expo-harmony-cli
- 上一篇文章:《Expo 官方不支持鸿蒙?我用一个开源 CLI,让 Expo 项目复用一套代码跑上 HarmonyOS》
如果你的团队正在做 Expo / React Native 的鸿蒙适配,欢迎试用、提 Issue、发 PR。一条命令的事,值得一试;顺手点个 ⭐ Star,能让更多在河这头张望的人看到这截桥。