Electron 能跑在鸿蒙上?你多半会以为是什么套壳方案。

不是。 harmonypc-electron 是真把 Node 22 + Chromium 搬进了 HAP——原生 SO 躺在 libs/arm64-v8a/ 里,ArkTS 桥接层负责把鸿蒙的系统能力暴露给 Node。

上篇我说「把 dsh 搬上鸿蒙,只换运行时」,这篇就把这个运行时拆开给你看:它由哪几块组成、Node 和鸿蒙怎么对上话、渲染面怎么贴,以及我们工程是怎么适配它的。看完你也能搞清楚「Electron-on-鸿蒙」到底是怎么一回事。

一、鸿蒙没有官方 Electron:三件事都得自己搭

鸿蒙的桌面形态(2in1 / 平板)没有官方 Electron。想在鸿蒙上跑一个依赖 Node 生态的桌面应用,有三件事得自己搭:

  1. 原生 SO:Electron 的二进制(Node + Chromium 引擎)
  2. 桥接层:让 Node 侧能调用鸿蒙的系统能力(窗口 / 通知 / 剪贴板 / 权限)
  3. 渲染面:把网页内容贴进鸿蒙窗口

harmonypc-electron 就是干这三件事的运行时。下面逐个拆。

二、拆成两个模块:一个管「跑」,一个管「接」

harmonypc-electron 拆成两个模块:

  • electron(type: entry,HAP 入口):承载原生 SO——libelectron.so(约 172MB)、libffmpeg.so、libadapter.so,外加 libc++_shared.so。EntryAbility 从这里启动 Electron 运行时。
  • web_engine(HAR 桥接层):ArkUI Web 组件 + 大量 *AdapterBind.ets(窗口 / 通知 / 剪贴板 / 权限…)+ jsbindings。你的 Electron 应用代码就放在它的 resfile/resources/app/ 里。

一句话:electron 模块管「跑起来」,web_engine 模块管「接上鸿蒙」。

三、桥接三件套:aki / adapter / addon

最核心的是 Node ↔ ArkTS 的桥接,靠「三件套」:

组件产物作用
akilibaki_jsbind.soJS 绑定框架(Node ↔ ArkTS 类型桥)
adapterlibadaptertest.so注册原生方法(getNativeContext + bindFunction)
addonelectron-addon.node(链 libshim.a)Node 侧 require() 入口

数据流是这样:Node 侧 require('electron-addon.node') 拿到入口 → 通过 aki 的类型桥 → 调用 ArkTS 侧 JsBindingMethod.bind() 注册的方法。反过来,鸿蒙的系统事件也能经这条桥回传给 Node。

对我们这个工程来说,这套桥接大部分已经由运行时编译好了,我做的事只是接线——比如通知,订阅 dsh 的 ctx 事件后,经桥接触发鸿蒙通知即可。

四、渲染面:XComponent 贴的原生 Chromium,不是 ArkWeb

渲染层面,web_engine 用 XComponent(SURFACE) 承载一个原生 Chromium 渲染面,把 dsh Web UI 贴进鸿蒙窗口。

注意这个词——「原生 Chromium」,不是 ArkWeb。这点很关键,它直接埋下了后面「上架合规」的坑:AppGallery 要求「渲染网页必须用 ArkWeb」,而我们用的是随包 Chromium。这个坑我在「App 上架合规踩坑」篇会单独讲(还做了个 ArkWeb 的 PoC,结论是可行)。

五、为什么非 Electron 37 / Node 22.17.0 不可

运行时版本不是随便选的。dsh 依赖 node:zlib.createZstdDecompress(解压会话产物),这要求 Node 22+。

而 Electron 34 只带 Node 20.18.1,没有这个 API;Electron 37 的 Node 22.17.0 才行。SQLite 也顺带换了 better-sqlite3 的 Electron 37 / Node ABI v138 aarch64 成品。

六、适配纪律:copy + prune + overlay + bundleName 改写

本工程怎么「适配」这个运行时?核心是 collect-runtime.mjs 这一条流水线。纪律只有一句:「整目录 copy 会回滚你的定制」,所以必须靠下面几步保护:

  • copy:把 ../harmonypc-electron 的 electron + web_engine 模块 + 3 个 SO 物理 copy 进本工程(sibling 存放、产物内嵌)。
  • prune:删掉本应用不用的 4 个上游蓝牙文件(删前先断言存在,缺了硬失败——防止上游结构漂移被静默跳过)。
  • overlay:把 runtime-overlays/ 里的定制文件回盖上去(module.json5、string.json、shortcuts 配置…)。
  • bundleName 改写:把上游写死的包名字面量替换成应用自己的包名。
  • 守卫:md5 一致性 + prune 文件必须不存在 + overlay 源仍含通用字面量,防止某一步静默回滚。

这套「copy 后必须重新施加定制」的纪律,是鸿蒙工程里最容易踩的坑之一——你改了个文件,一跑 collect-runtime,改动没了。

七、写在最后

以上就是 Electron-on-鸿蒙运行时的完整拆解:electron 模块跑起来 + web_engine 模块接鸿蒙 + aki/adapter/addon 三件套桥接 + XComponent 渲染面,适配靠 copy / prune / overlay / 改写 + 守卫。

如果你也在做 Electron 应用的鸿蒙化,这篇的运行时机理和适配纪律可以直接抄。

代码已开源:https://github.com/fellow99/dsh-desktop-hos ,欢迎 star 支持。

相关开源工程:

  • DeepSeek Harness(上游项目):https://github.com/deepseek-ai/deepseek-harness
  • dsh-market(插件市场):https://github.com/dsh-market/dsh-market
  • harmonypc-electron(Electron-on-鸿蒙运行时):https://atomgit.com/jianguoxu/harmonypc-electron
  • deepseek-harness-workspace(工作区总览):https://github.com/fellow99/deepseek-harness-workspace
  • dsh-desktop(桌面端):https://github.com/fellow99/dsh-desktop
  • dsh-desktop-hos(鸿蒙端):https://github.com/fellow99/dsh-desktop-hos

下一篇我写**「鸿蒙真机调试三板斧」**:主进程 inspector + CDP 自动化,还有为什么 Playwright 驱动不了它。关注我,别错过。

感谢各位关注,欢迎访问我的GitHub主页:https://fellow99.github.io/

Logo

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

更多推荐