Capacitor 应用鸿蒙化实战:用 hionic 把 React 应用跑在 OpenHarmony 上

本文记录了使用CPF-Ionic 团队开源的 hionic 命令行工具,从一个 Vite + React Web 项目出发,初始化 Capacitor 工程、添加 OpenHarmony 平台、解决 openssl 原生依赖、构建签名 HAP 的完整过程。
包含 Capacitor 框架介绍、hionic 与 capacitor-cli / openharmony-capacitor 的架构关系、逐步操作记录、两轮编译报错的根因分析与修复,以及踩坑复盘。所有步骤均在本机(macOS arm64 + DevEco Studio)实际执行验证。


一、背景

1.1 Capacitor 简介

Capacitor 是 Ionic 团队推出的新一代混合应用框架,可以理解为 “现代版 Cordova”:

维度CordovaCapacitor
Web 资源承载运行时由 WebView 加载 www/,桥接走 cordova.exec 消息队列Web 产物直接打包进原生工程 rawfile,桥接更薄
工程结构CLI 生成平台工程后由 CLI 维护平台工程提交进版本库,开发者直接拥有原生工程
前端集成需 cordova 项目结构任意前端项目(Vite/webpack/Next.js)npx cap init 即可接入
插件 APInavigator.* / cordova.exec现代 Promise API(@capacitor/camera 等),兼容 Cordova 插件
版本cordova 13.xcapacitor 8.x(本文实测 8.5.2)

Capacitor 的核心工作流是四步循环:

前端开发(Vite/React/Vue...)
   → build  (vite build 产出 dist/)
   → sync   (把 dist/ 拷贝进原生工程 rawfile,同步插件注册)
   → open/run(打开 IDE 或运行到设备)

1.2 hionic:华为的 Capacitor 鸿蒙化 CLI

华为 CPF-Ionic 团队对 Capacitor 做了完整鸿蒙化,由三个部分组成(已同步到 AtomGit,组织主页 https://atomgit.com/cpf-ionic ):

组件仓库角色
hionic(npm)CPF-Ionic/capacitor-cli命令行工具(npm 包名 hionic,实测版本 2.1.16)
OHOS 平台运行时CPF-Ionic/openHarmony-capacitor(npm 包 @capacitor-ohos/ohos,实测 8.0.2)ArkTS + C++ 实现的鸿蒙 Capacitor 运行时(HAR 源码分发)
插件生态CPF-Ionic 组织(capacitor-geolocation、capacitor-haptics、capacitor-clipboard、ionic-native-* 等 30+ 仓库)Capacitor 官方插件的 OHOS 实现

hionic 的命令设计与 Capacitor 原生 CLI 对齐,并扩展了鸿蒙平台:

hionic start <Cordova|Capacitor> <path> [id] [name] [template]   # 创建 Web 项目(react/vanilla 模板)
hionic init [name] [id]          # 把已有 Web 项目初始化为 Capacitor 工程
hionic add openharmony           # 添加鸿蒙平台
hionic buildui                   # 构建前端产物
hionic sync openharmony          # 同步 Web 产物 + 插件到鸿蒙工程
hionic buildapp openharmony      # 构建应用(实际引导 hvigorw)
hionic run / open <platform>     # 运行 / 用 IDE 打开

1.3 实验目标

维度要求
前端技术栈Vite + React(--template=react),前端代码零改动
平台openharmony(鸿蒙壳工程,DevEco 可直接打开)
构建产物签名 HAP,可安装到模拟器运行

二、环境

依赖版本说明
macOSarm64 (Apple Silicon)
Node.jsv26.0.0
hionic2.1.16npm install -g hionic
@capacitor/core / cli8.5.2 / 项目内hionic 的 init 依赖它们(见踩坑 1)
@capacitor-ohos/ohos8.0.2鸿蒙运行时,add openharmony 时从 node_modules 拷入工程
DevEco Studio内置 hvigor / ohpm / SDK 5.0.5(17)
设备模拟器 7.0.0.106(SP1DEVC00E999R4P11),hdc list targets → 127.0.0.1:5555

三、逐步操作过程

第 1 步:创建项目

hionic start capacitor capacitorMyApp com.nutpi.MyApp capacitorMyHarmonyApp react

这条命令实际执行了三件事:

  1. npm create vite capacitorMyApp -- --template react — 生成 Vite + React 工程;
  2. npm install — 安装 143 个前端依赖(React 19.2.6);
  3. npx cap init capacitorMyHarmonyApp com.nutpi.MyApp — 初始化 Capacitor 配置。

结果:前两步成功,第三步失败(踩坑 1),手动修复后 capacitor.config.json 生成:

{
  "appId": "com.nutpi.MyApp",
  "appName": "capacitorMyHarmonyApp",
  "webDir": "www"
}

注意 webDir 默认是 www,而 Vite 产物目录是 dist,后面 sync 前必须改掉(踩坑 3)。

第 2 步:添加鸿蒙平台

hionic add openharmony

执行过程:

  1. 从 hionic/templates/capacitor 拷贝鸿蒙壳工程模板到 openharmony/;
  2. 把 node_modules/@capacitor-ohos/ohos 运行时源码拷入 openharmony/capacitor/(ArkTS HAR 源码,非预编译 so);
  3. 渲染 48 个模板文件:AppScope/app.json5 写入 bundleName com.nutpi.MyApp、应用名 capacitorMyHarmonyApp、版本 1.0.0 等。

生成结构:

capacitorMyApp/
├── openharmony/                  # 鸿蒙壳工程(DevEco 可直接打开)
│   ├── AppScope/app.json5        # bundleName: com.nutpi.MyApp
│   ├── entry/                    # 主模块(EntryAbility + Capacitor 容器)
│   ├── capacitor/                # @capacitor-ohos/ohos 运行时(ArkTS + C++ HAR)
│   │   └── src/main/cpp/         # 桥接层 C++ 源码(CMakeLists.txt 编译)
│   ├── build-profile.json5       # targetSdk 5.0.5(17) / compatible 5.0.0(12)
│   └── oh-package.json5
├── src/                          # React 源码(零改动)
└── capacitor.config.json

第 3 步:构建前端 + 同步

hionic buildui     # 实际执行 vite build,产出 dist/(222KB JS)

修改 capacitor.config.json 的 webDir 为 dist(踩坑 3),然后:

hionic sync openharmony
# Resolved webDir: dist -> .../capacitorMyApp/dist
# Doing copy openharmony platform success
# Doing sync 0 Capacitor plugins

sync 后验证:openharmony/entry/src/main/resources/rawfile/www/ 下出现了 React 产物(index.html、assets/index-YeS5K1AL.js…)以及 capacitor.js、native-bridge.js 桥接脚本——Web 层与原生层的对接点。

第 4 步:构建 HAP(两轮报错与修复)

第一轮报错:libssl.so.3 missing

用 hvigorw 构建:

cd openharmony
export DEVECO_SDK_HOME=/Applications/DevEco-Studio.app/Contents/sdk
export PATH=".../tools/hvigor/bin:.../tools/node/bin:.../tools/ohpm/bin:$PATH"
hvigorw assembleHap --mode module -p module=entry@default -p product=default -p requiredDeviceType=phone

报错:

ninja: error: '.../openharmony/capacitor/libs/x86_64/libssl.so.3',
needed by '.../obj/x86_64/libcapacitor.so', missing and no known rule to make it

根因:查看 capacitor/src/main/cpp/CMakeLists.txt:

set(OPENSSL_LIB_PATH ${NATIVERENDER_ROOT_PATH}/../../../libs/${OHOS_ARCH})
target_link_libraries(capacitor PUBLIC
    ${OPENSSL_LIB_PATH}/libssl.so.3
    ${OPENSSL_LIB_PATH}/libcrypto.so.3)
target_include_directories(capacitor PUBLIC
    ${NATIVERENDER_ROOT_PATH}/openssl/${OHOS_ARCH}/include)

@capacitor-ohos/ohos 8.0.2 的原生层(自研 Socket/SSLSocket 网络栈)链接 openssl 3.x,需要两组材料:

材料路径状态
编译好的 so/a 库capacitor/libs/<abi>/(libssl.so.3、libcrypto.so.3 等)❌ 缺失
openssl 头文件capacitor/src/main/cpp/openssl/<abi>/include/(142 个头文件)❌ 缺失

其 README 明确写着:“本工程依赖 openssl…编译之前先集成 openssl,只有成功集成后,才可编译”,官方集成方法是 li_in/openharmony-capacitor-openssl3.5 手动编译。而 hionic 的 add openharmony 完全没有 hcordova 那样的 openssl 自动安装逻辑(全局搜索 hionic 源码无任何 openssl 处理)——这是 hionic 与 hcordova 的一个显著功能差距。

修复:恰好此前在同一台机器上用 hcordova 创建过项目,hcordova 的 platform add ohos 曾自动克隆并编译过 openssl 3.x(同属 CPF 生态,ABI 与工具链一致),直接复用:

# 1. 拷贝预编译库(x86_64 模拟器 + arm64-v8a 真机)
SRC=MyApp/harmonyos/cordova/libs
DST=capacitorMyApp/openharmony/capacitor/libs
cp -R $SRC/x86_64    $DST/x86_64     # libssl.so.3 / libcrypto.so.3 / libssl.a / engines-3 / ossl-modules
cp -R $SRC/arm64-v8a $DST/arm64-v8a

# 2. 拷贝 openssl 头文件
SRC2=MyApp/harmonyos/cordova/src/main/cpp/openssl
DST2=capacitorMyApp/openharmony/capacitor/src/main/cpp/openssl
cp -R $SRC2/x86_64    $DST2/x86_64    # include/ 下 142 个头文件
cp -R $SRC2/arm64-v8a $DST2/arm64-v8a
第二轮报错:openssl/ssl.h not found

第一处修完(ninja 能找到 libssl.so.3 了),重新构建,编译器报:

SSLSocket.h:21:10: fatal error: 'openssl/ssl.h' file not found
HttpUrl.cpp:18:10: fatal error: 'openssl/md5.h' file not found

根因:CMake 的 include 路径 cpp/openssl/<abi>/include 为空——修复第一轮时只拷了 libs,头文件没拷。补上第 2 步的头文件拷贝后(共两处材料:libs + 头文件),构建通过。

构建成功
> hvigor Finished :entry:default@PackageHap... after 301 ms
> hvigor Finished :entry:default@SignHap... after 999 ms
> hvigor BUILD SUCCESSFUL in 9 s 112 ms
41 tasks in total: 26 executed, 15 up-to-date

产物(注意这次连签名都自动完成了):

entry/build/default/outputs/default/entry-default-signed.hap      (26 MB)
entry/build/default/outputs/default/entry-default-unsigned.hap

SignHap 任务成功是因为 DevEco Studio 的自动签名已在此前打开工程时配置过(File → Project Structure → Signing Configs → Automatically generate signature),签名配置被写进了 openharmony/build-profile.json5 的 signingConfigs。这也修正了 hcordova 项目里"命令行产物必为 unsigned"的印象——只要 signingConfigs 存在,hvigorw 命令行构建同样会产出 signed HAP。


四、架构对照

4.1 capacitor-android vs @capacitor-ohos/ohos

维度AndroidOHOS(openharmony-capacitor)
WebViewandroid.webkit.WebViewArkWeb
运行时分发gradle 依赖(jar/aar)HAR 源码直接拷入工程(可读可改)
桥接层Java + WebView JSBridgeArkTS 容器 + C++ NAPI(Base64/Socket/SSLSocket/ConnPool/MemPool 等自研模块)
网络栈java.net自研 C++ Socket/SSLSocket + openssl 3.x(需手动集成)
Web 资源assets/rawfile/www/(sync 拷入)
插件注册CapacitorPluginAnnotation 扫描oh-plugins 目录 + capacitor.plugins.json

4.2 hcordova vs hionic(同一 CPF 生态的姊妹 CLI)

维度hcordovahionic
框架CordovaCapacitor(+ Cordova 兼容)
版本(实测)1.0.72.1.16
平台运行时@cordova-ohos/ohos 14.0.2@capacitor-ohos/ohos 8.0.2
openssl 自动安装✅ 有(platform add ohos 交互式克隆编译)❌ 无(需手动集成,报错后才知道)
init 依赖转发原版 cordova CLI(需 npm i -g cordova)调用 npx cap init(需项目内装 @capacitor/cli,见踩坑 1)
模板渲染43 个文件48 个文件
命令丰富度create/platform/plugin + build(仅提示)start/init/sync/copy/buildui/buildapp/run/open/info

五、关键决策说明

决策 1:复用 hcordova 的 openssl 材料,而非从头编译

官方路线是按 openharmony-capacitor-openssl3.5 自行编译 openssl 3.5(Configure OHOS 交叉编译参数 → make)。本机 hcordova 项目里已有同源 openssl 3.x 编译产物(同样的 OHOS NDK clang 工具链、同样的 x86_64/arm64-v8a ABI、同样的 .so.3 命名),直接复用零成本通过验证。若没有 hcordova 项目垫底,则应走官方编译路线。

决策 2:手改 webDir 而非改 vite 产物目录

capacitor.config.json 的 webDir: www 与 Vite 惯例 dist 冲突。改配置一行 vs 改 vite.config 的 outDir 再全局约定——选前者,保持前端工程零改动原则。

决策 3:签名交给 DevEco 自动签名

模拟器/个人调试场景,DevEco 自动签名(登录华为账号一键生成 p12/cer/p7b 并写入 build-profile.json5)是最省事且可持续的方式;CI 场景再考虑 hap-sign-tool 手动签名链路。


六、测试与验证

验证项结果
Vite 构建✅ 383ms,产出 dist/(222KB JS gzip 69KB)
sync 同步✅ dist 内容进入 rawfile/www/,含 native-bridge.js
hvigorw 构建✅ 41 任务(含 capacitor HAR 的 C++ NAPI 编译),9.1s
签名✅ SignHap 成功(DevEco 自动签名),产出 signed HAP
包名核对✅ hdc shell bm dump -n com.nutpi.MyApp

运行:

hdc install -r openharmony/entry/build/default/outputs/default/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.nutpi.MyApp

七、踩坑复盘

#踩坑点现象 / 报错根因与解法
1npx cap init 失败npm error could not determine executable to run(日志 pkgid cap@0.2.1)hionic 未先给项目装 @capacitor/core + @capacitor/cli,npx 远端匹配到无关旧包 cap。解法:项目内 npm i @capacitor/core @capacitor/cli 后手动 npx cap init
2openssl 库缺失ninja: error: 'libs/x86_64/libssl.so.3' ... missing and no known rulehionic 无 openssl 自动安装(hcordova 有);CMakeLists 要求 capacitor/libs/<abi>/libssl.so.3。解法:拷入 hcordova 项目编译好的 openssl 3.x(或按官方 openharmony-capacitor-openssl3.5 仓库自行编译)
3webDir 不匹配sync 报 Web directory not found: .../www 或同步了错误内容hionic 模板写死 webDir: www,Vite 产物在 dist。解法:改 capacitor.config.json 的 webDir 为 dist
4openssl 头文件缺失fatal error: 'openssl/ssl.h' file not found(多个 .cpp)CMake include 路径 cpp/openssl/<abi>/include 为空。解法:除 libs 外还需拷贝 openssl 头文件目录,两处材料缺一不可
5hvigorw 环境变量DEVECO_IDE_PATH is not configured(hionic buildapp 检查)hionic 的 buildapp 要求两个环境变量:DEVECO_SDK_HOME 和 DEVECO_IDE_PATH(=/Applications/DevEco-Studio.app);hvigorw/ohpm/node 需加入 PATH
6命令行也能签名之前以为 CLI 构建必产 unsigned HAP实际上只要 build-profile.json5 有 signingConfigs(DevEco 自动签名写入过),hvigorw 就会执行 SignHap 产出 signed HAP

八、遗留问题与改进方向

已知问题

  1. hionic 未自动集成 openssl — 与 hcordova 相比是明显的能力缺口,建议在 add openharmony 时检测 capacitor/libs/ 是否存在并提示/自动下载(可对标 hcordova 的交互式 openssl 安装器)
  2. hionic start 的 init 步骤不稳 — 依赖 npx 远端解析 cap 命令,需先装 @capacitor/cli(建议 hionic 在 create 流程中显式 npm i -D @capacitor/cli)
  3. webDir 默认值与 Vite 不符 — react 模板应默认 dist

未来优化

  • openssl 预编译 HAR 化:把 openssl 3.x so + 头文件做成 ohpm 包(如 @capacitor-ohos/openssl),让 CMake 直接依赖 oh_modules,免去手动拷贝
  • 插件适配覆盖度:CPF-Ionic 已有 geolocation/haptics/clipboard/app-launcher/native-settings 等插件,常用插件的鸿蒙覆盖情况需逐一核验

九、总结

把一个 Vite + React 前端项目跑到 OpenHarmony 上,核心路径可以概括为三步走:

1. 接入   ── hionic start/init + add openharmony,生成 ArkWeb 壳工程,前端零改动
2. 补材料 ── 手动集成 openssl 3.x(libs + 头文件两处),hionic 未自动做
3. 循环   ── buildui → sync → hvigorw buildapp → 模拟器运行

与 hcordova 相比,hionic 的 Capacitor 路线工程现代化程度更高(HAR 源码运行时、插件注册透明、原生工程归开发者所有),但 openssl 集成是每个新项目都要踩的坑。两个 CLI 也可以共存协作:hcordova 项目里自动下载的 openssl 编译产物,恰好成为 hionic 项目的现成依赖——CPF 生态的 openssl 材料是同构的。


参考文档

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐