一、写在前面

鸿蒙适配开源地址:https://atomgit.com/OpenHarmonyPCDeveloper/ohos_AnotherRedisDesktopManager

欢迎在PC社区平台申请新建项目:https://atomgit.com/OpenHarmonyPCDeveloper

环境搭建文章:https://blog.csdn.net/lbcyllqj/article/details/161286249?sharetype=blogdetail&sharerId=161286249&sharerefer=PC&sharesource=lbcyllqj&spm=1011.2480.3001.8118

这篇文章记录的是 Another Redis Desktop Manager 在 OpenHarmony / HarmonyOS Electron 运行环境中的适配过程。

Another Redis Desktop Manager 是一个传统桌面 Electron + Vue 2 项目,内部直接使用了很多 Electron、Node 和 Redis 相关能力:

  • electron
  • ioredis
  • tunnel-ssh
  • ssh2
  • fs
  • zlib
  • child_process
  • remote
  • ipcRenderer

这也决定了它的鸿蒙适配不能只看“页面资源路径对不对”,还要处理更多运行时协作问题:

Electron 主进程、Vue renderer、Node 原生模块、Redis 网络栈和鸿蒙运行时之间要同时协调。

本次适配完成了 Another Redis Desktop Manager 在 OpenHarmony / HarmonyOS Electron 环境中的整体鸿蒙化改造,覆盖 HAP 工程接入、主进程平台兼容、renderer 运行链路、Electron API 兼容、Redis 连接能力、SSH / SSL 相关能力承载、运行时依赖同步以及命令行构建流程。

这篇记录会偏向“工程复盘”。原因很简单:ARDM 的业务逻辑本来就长在 Electron 和 Node 能力上。Redis 连接、SSH 隧道、文件选择、压缩解压、外部命令,这些能力放在传统桌面端里都很自然,迁移到鸿蒙 Electron runtime 后,需要把主进程、renderer、Node 依赖和 HAP 资源组织方式重新梳理清楚。

这次适配围绕完整可用的桌面工具体验展开,重点处理了几条主线:

  • HAP 工程能够独立构建和安装
  • 主进程能够在鸿蒙环境中加载正确资源
  • renderer 能够稳定承载 Vue 业务界面
  • Electron renderer API 能够通过兼容层统一收口
  • Redis、SSH、文件选择、导入导出等能力能够进入鸿蒙运行环境
  • 运行时依赖能够随 HAP 资源一起完整同步

适配完成后,ARDM 在鸿蒙 Electron runtime 中具备完整的应用启动、连接管理、数据查看、配置操作和构建交付链路。
在这里插入图片描述


二、项目背景

Another Redis Desktop Manager 是一个 Redis 桌面管理工具,项目描述是:

A faster, better and more stable redis desktop manager, compatible with Linux, windows, mac

当前适配项目版本:

1.1.1

项目技术栈包括:

  • Electron 12
  • Vue 2
  • Element UI
  • webpack 4
  • ioredis
  • tunnel-ssh / ssh2
  • Monaco Editor
  • 多种 Redis value viewer

这个项目的一个关键特点是:

Redis 连接能力就在 renderer 侧深度参与业务逻辑,并且会带入大量 Node 网络模块。

因此鸿蒙适配时,不能只处理 HAP 工程,还必须处理 renderer 启动链路。

ARDM 的很多模块并不是“点到某个功能时才加载”。在原始桌面环境里,启动阶段同步加载大量模块通常能够正常工作,因为 Electron + Node 的能力默认都在。迁移到鸿蒙 runtime 后,需要让这些能力的加载顺序更加清晰,避免 Redis、SSH、文件导入等重能力影响应用启动效率。

这也是后面要做 electronCompat.js 和异步组件拆分的原因。它们的目标是让应用启动、连接管理、数据操作、文件能力各自有清晰边界,既保留桌面端能力,也让鸿蒙运行时的资源加载更加稳定。


三、总体变化概览

3.1 新增鸿蒙工程壳

项目新增:

ohos_hap/
├── AppScope/
├── electron/
├── web_engine/
└── build-profile.json5

鸿蒙侧运行资源目录:

ohos_hap/web_engine/src/main/resources/resfile/resources/app

3.2 新增构建脚本

新增:

scripts/build-ohos-package.js
scripts/build-ohos-hap.js

并在 package.json 中增加:

{
  "build:ohos": "node scripts/build-ohos-package.js",
  "ohos:sync": "OHOS_ARDM_OUT=ohos_hap/web_engine/src/main/resources/resfile/resources/app npm run build:ohos",
  "ohos:build": "node scripts/build-ohos-hap.js"
}

3.3 主进程适配

pack/electron/electron-main.js 增加了:

  • ARDM_OPENHARMONY 平台识别
  • 鸿蒙环境禁用 GPU
  • 鸿蒙环境关闭自动更新
  • HAP 环境加载 dist/index.html
  • renderer 诊断日志
  • did-fail-load
  • did-finish-load
  • console-message
  • render-process-gone

3.4 renderer 启动兼容

新增:

src/electronCompat.js

用于集中处理:

  • ipcRenderer
  • remote
  • webFrame
  • shell
  • clipboard

当鸿蒙环境中某些 Electron renderer API 表现不一致时,页面可以通过兼容层获得稳定兜底。

在这里插入图片描述


四、原始项目直接迁移的问题

4.1 主进程默认面向桌面 Electron

原始项目的 electron-main.js 默认是桌面端运行方式:

  • 创建 BrowserWindow
  • 开启 nodeIntegration
  • 启用 remote
  • 加载本地页面或开发服务器
  • 生产环境启用自动更新

这些逻辑在 Windows / macOS / Linux 上没有问题,但在鸿蒙 Electron runtime 中,自动更新、GPU、窗口行为和资源路径都需要重新判断。

4.2 renderer 启动链路过重

ARDM 的 Vue 入口会同步引入:

  • App.vue
  • Aside.vue
  • Tabs.vue
  • UpdateCheck.vue
  • shortcut.js
  • addon.js
  • util.js

而这些模块继续带入:

  • Electron IPC
  • remote
  • webFrame
  • clipboard
  • Redis 连接组件
  • 文件选择组件
  • 压缩/解压 viewer

这意味着 renderer 启动链路需要重新梳理,避免业务模块在初始化阶段互相牵连。

4.3 Redis 相关依赖更复杂

redisClient.js 顶层依赖:

  • ioredis
  • tunnel-ssh
  • ssh2
  • fs
  • electron.remote

这些依赖在普通桌面 Electron 里是合理的。鸿蒙适配中对它们进行了加载顺序调整,让 net/tls/dns/fs 等 Node 原生能力跟随 Redis 连接场景进入运行链路。


五、鸿蒙适配核心路径

5.1 第一步:补齐 HAP 工程和资源同步

scripts/build-ohos-package.js 做了几件事:

  1. 确认桌面构建产物存在
  2. 清理并创建输出目录
  3. 拷贝 dist
  4. 拷贝 Electron 主进程文件
  5. 写入鸿蒙启动 main.js
  6. 写入 runtime package.json
  7. 拷贝运行时依赖

启动引导会注入:

process.env.ARDM_OPENHARMONY = '1';
process.env.ARDM_DISABLE_GPU = process.env.ARDM_DISABLE_GPU || '1';
require('./electron-main.js');

这一步让原本桌面 Electron 工程进入鸿蒙 Electron runtime。

5.2 第二步:修正 HAP 内 renderer 加载路径

桌面打包时,electron-main.js 通常从当前目录加载页面。
但 HAP 运行时资源目录结构里,真正的 renderer 页面位于:

resources/app/dist/index.html

因此主进程需要在鸿蒙模式下加载:

const indexHtmlPath = global.IS_OPENHARMONY ? 'dist/index.html' : 'index.html';

否则就可能出现窗口起来但页面资源不对的问题。

5.3 第三步:关闭鸿蒙下不适合的能力

主进程增加:

global.IS_OPENHARMONY = process.env.ARDM_OPENHARMONY === '1' ||
  /^(ohos|openharmony|harmony)$/i.test(process.platform);

并在鸿蒙下:

  • app.disableHardwareAcceleration()
  • 跳过自动更新
  • 跳过 macOS 菜单逻辑
  • 输出主进程加载日志

这一步解决的是“桌面端默认能力不适合鸿蒙”的问题。

5.4 第四步:给 HTML 壳增加运行诊断

index.html 增加了:

  • window.onerror
  • window.onunhandledrejection
  • window.__ARDM_SHOW_RENDERER_ERROR__
  • window.__ARDM_BOOT_LOG__

如果 renderer 入口出现异常,页面会直接显示:

[ARDM renderer error]

这一步让鸿蒙运行环境中的资源加载、模块初始化、业务启动状态都能被快速定位,方便日常维护和问题追踪。

5.5 第五步:收口 Electron renderer API

新增 src/electronCompat.js,把 Electron API 访问集中起来。

它提供:

getIpcRenderer()
getRemote()
getWebFrame()
getShell()
getClipboard()

如果 require('electron') 失败,返回安全兜底对象,而不是让模块顶层直接抛错。

随后这些文件都被改造为走兼容层:

  • src/addon.js
  • src/shortcut.js
  • src/util.js
  • src/components/UpdateCheck.vue
  • src/components/Setting.vue
  • src/components/FileInput.vue
  • src/components/ConnectionMenu.vue
  • src/components/OperateItem.vue
  • src/redisClient.js

5.6 第六步:拆分启动期同步依赖

为了让 Redis、SSH、文件导入等重能力跟随实际业务场景加载,适配中做了懒加载:

  • ConnectionWrapper.vue 中的 redisClient.js 改成动态 import
  • Tabs.vue 中各 tab 组件改成异步组件
  • Aside.vue 中设置、日志、新建连接等弹窗改成异步加载
  • ConnectionWrapper.vueKeyListOperateItemConnectionMenu 改成异步加载

这一步的核心思想是:

应用启动链路保持轻量,业务能力按使用场景进入运行链路。

5.7 第七步:收口启动期 Electron API

适配中梳理到 OperateItem.vue 中使用了:

ipcRenderer.on('closingWindow', ...)

但原文件没有显式导入 ipcRenderer。在普通桌面环境里这个问题可能不明显,但在鸿蒙 renderer 下很容易导致启动异常。

适配后改为:

import { getIpcRenderer } from '@/electronCompat';
const ipcRenderer = getIpcRenderer();

这类改动让 renderer 对 Electron API 的使用更加明确,也让鸿蒙环境中的 IPC 事件处理更加稳定。

5.8 第八步:只复制运行时真正需要的依赖

ARDM 属于带运行时依赖的 Electron 应用,HAP 运行目录里需要同步一部分 node_modules。如果把整个开发依赖都塞进去,包体会变大,也更难判断哪个依赖是运行时必须的。

scripts/build-ohos-package.js 的做法是读取 package-lock.json,筛出非 dev 依赖,再把这些依赖复制到:

resources/app/node_modules

同时额外补上 font-list,因为它来自 pack/electron/package.json。这个细节很容易漏:桌面项目经常会有根 package.json 和 Electron 打包目录下的运行时 package.json,两边依赖不完全一致。如果只看根依赖,应用可能在某些字体或系统能力上运行到一半才报错。

这一步的目标是让 HAP 内的 runtime package 更接近桌面打包后的真实运行环境,而不是单纯追求依赖数量最少。

5.9 第九步:补齐运行期诊断

适配过程中,一个很有价值的改动是增加运行期诊断。

主进程里加了:

  • did-fail-load
  • did-finish-load
  • console-message
  • render-process-gone
  • crashed

HTML 壳里加了:

  • window.onerror
  • window.onunhandledrejection
  • 页面内错误展示框

这些诊断让资源加载、模块启动、renderer 状态和主进程事件都有明确记录。迁移项目里这种信息密度非常重要,因为鸿蒙设备侧日志不一定能马上给出前端开发者熟悉的报错形态。

在这里插入图片描述


六、问题困难解决

ARDM 适配中最核心的工作是:

把 Electron 主进程、HAP 资源目录、renderer 入口和 Redis 业务依赖全部串成一条稳定的鸿蒙运行链路。

这条链路涉及的层级比较多,需要逐层确认资源、窗口、业务模块和运行时依赖都在正确位置。

6.1 第一层:原生壳与 Electron shell

鸿蒙侧运行时首先要确认:

  • 应用窗口出现
  • 标题显示
  • 图标显示
  • activateWindow 正常输出

这些信息说明 HAP / Ability / Electron shell 已经完成基础启动,应用已经进入 Electron 主进程加载阶段:

electron-main.js -> dist/index.html -> renderer JS -> Vue mount

6.2 第二层:资源路径准确落位

适配中确认了 HAP 内资源实际结构:

resources/app/main.js
resources/app/electron-main.js
resources/app/dist/index.html
resources/app/dist/static/js/...

并在主进程加入:

console.info('[ARDM] loading renderer', rendererUrl);

这样可以确认运行时加载的是 dist/index.html,资源路径和 HAP 内目录结构保持一致。

6.3 第三层:renderer 启动链路重组

静态扫描打包产物时可以看到,renderer 业务中包含:

  • require("electron")
  • require("zlib")
  • require("fs")
  • require("child_process")
  • require("net")
  • require("tls")
  • require("dns")

其中 ioredis/ssh2 被拆到了异步 chunk 中,Redis 和 SSH 能力按使用场景进入运行链路,避免所有重依赖集中在应用初始化阶段。

处理方式是分层组织:

  1. 应用界面先完成初始化
  2. Electron API 访问集中走兼容层
  3. Redis / SSH 能力按连接场景加载
  4. viewer、导入导出、文件选择等能力保留原有业务入口

6.4 第四层:主进程与 renderer 诊断

适配中同时增加两类诊断。

主进程:

  • did-fail-load
  • did-finish-load
  • console-message
  • render-process-gone
  • crashed

HTML 壳:

  • window.onerror
  • window.onunhandledrejection
  • 页面内错误展示框

这样可以明确看到资源加载、Electron API、Vue 入口和 renderer 状态,维护时能更快定位问题。

6.5 最终运行结果

适配完成后,设备上可以看到:

  • ARDM 标题栏
  • ARDM 图标
  • 左侧 New Connection
  • 设置按钮
  • 日志按钮
  • 右侧空白工作区

这个画面是 ARDM 的正常无连接工作区状态。用户可以从这里创建 Redis 连接、进入设置、查看日志,并继续进行 key 浏览、CLI、状态查看等操作。

本次适配已经完成:

原生壳启动 + 主进程加载 + renderer 挂载 + Redis 业务入口承载。

在这里插入图片描述

Redis 连接、SSH 隧道、SSL 证书文件选择、导入导出等能力也已经纳入鸿蒙运行链路。

6.6 运行链路中的关键判断点

ARDM 的运行链路比较长,窗口出现后会继续进入 renderer 和业务模块初始化流程。

窗口、标题、图标能出现,说明 HAP、Ability 和 Electron shell 已经启动。完整运行还包括:

  • electron-main.js 加载了正确的 HTML
  • dist/static/js 资源全部加载成功
  • Vue 入口执行完成
  • Element UI、store、router 初始化成功
  • Redis 相关依赖按业务入口加载

所以适配中把日志分成两层:主进程确认加载路径和 webContents 状态,HTML 壳捕获 renderer 的早期状态。两层配合后,运行链路更清楚。

6.7 为什么不直接删除 Node 相关能力

看到 renderer 里有 fszlibnettlsdns 这些依赖时,一个直觉做法是先删掉或替换掉。但 ARDM 是 Redis 管理工具,这些依赖并不是多余装饰,很多都和真实业务有关。

这次采用的是分层处理:

  1. 应用启动阶段保持轻量
  2. Electron API 访问集中走兼容层
  3. Redis 客户端、SSH、文件相关能力跟随实际使用进入运行链路
  4. 各项桌面能力通过兼容层和运行时依赖保持可用

这样既保留桌面端原有功能,也让鸿蒙适配保持清晰结构和稳定运行。


七、构建与运行方式

生产构建需要注意 webpack 4 和当前 Node/OpenSSL 的兼容问题。构建时使用:

NODE_OPTIONS=--openssl-legacy-provider npm run build

同步到鸿蒙资源目录:

cd /AnotherRedisDesktopManager
npm run ohos:sync

构建 HAP:

cd /AnotherRedisDesktopManager
npm run ohos:build

HAP 输出目录:

ohos_hap/electron/build/default/outputs/default/

当前输出包括:

electron-default-unsigned.hap
electron-default-signed.hap

在这里插入图片描述


八、结语

AnotherRedisDesktopManager 的适配重点,是把传统 Electron 桌面项目完整迁入鸿蒙 Electron runtime:

  • renderer 依赖 Node
  • 业务模块直接使用 Electron API
  • 网络栈和文件能力都在应用内部
  • 启动同步链路很长

这次适配的关键在于把启动链路拆开并重新组织:

  1. HAP 壳加载正确资源
  2. 主进程在鸿蒙下稳定运行
  3. renderer 具备完整运行诊断
  4. Redis / SSH / 文件能力按业务场景加载

最终结果是 ARDM 已经完成鸿蒙化适配,Redis 管理、连接配置、数据浏览、CLI、SSH、SSL、导入导出等核心能力都可以在鸿蒙 Electron runtime 中承载运行。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐