Electron 移植到鸿蒙平台的架构实现:一次跨平台的技术探索
将 Electron 移植到鸿蒙平台是一个极具挑战性的工程,涉及跨平台、跨语言、跨架构的多重技术难题。适配器模式: 40+ 系统适配器桥接两个生态原生桥接: libadapter.so 实现 ArkTS 与 C++ 的双向调用依赖注入: InversifyJS 构建松耦合的模块系统XComponent 渲染: 原生渲染管道支持 Chromium 内容多进程架构: 保持 Electron 的进程隔离
Electron 移植到鸿蒙平台的架构实现:一次跨平台的技术探索
项目概述
本文将深入剖析一个将 Electron 框架移植到鸿蒙操作系统的项目实现。这个项目的核心目标是让基于 Electron 开发的桌面应用能够在鸿蒙生态系统中运行,为开发者提供一条快速将现有 Electron 应用迁移到鸿蒙平台的路径。
技术背景
Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用的框架,广泛应用于 VSCode、Slack 等知名应用。而鸿蒙作为华为推出的新一代操作系统,拥有独特的分布式架构和 ArkTS/ETS 开发语言体系。将 Electron 移植到鸿蒙平台,需要解决两个生态系统之间的巨大差异。
项目架构设计
1. 双模块架构
项目采用了清晰的双模块架构:
ohos_hap/
├── electron/ # Electron 应用主模块
│ ├── libs/ # 原生 C++ 库
│ │ ├── libelectron.so # Electron 核心库
│ │ ├── libadapter.so # 适配器桥接库
│ │ ├── libffmpeg.so # 多媒体支持
│ │ └── libc++_shared.so
│ └── src/main/ets/ # ArkTS 代码
│ ├── entryability/ # 各种 Ability 入口
│ └── pages/ # UI 页面
│
└── web_engine/ # Web 引擎适配层(HAR 库)
└── src/main/ets/
├── adapter/ # 40+ 系统适配器
├── jsbindings/ # JS 绑定层
├── components/ # UI 组件
└── ability/ # 基础 Ability 类
Electron 模块
- 作用: 应用的入口模块,负责启动和管理 Electron 应用实例
- 核心组件:
BrowserAbility: 浏览器窗口能力EntryAbility: 主入口能力StatelessAbility: 无状态能力- 原生动态库(.so 文件)
Web Engine 模块
- 作用: 可复用的 HAR 库,封装了 Electron 运行所需的所有适配逻辑
- 设计理念: 通过适配器模式将鸿蒙 API 映射到 Electron API
2. 适配器模式:系统能力的桥接
项目的核心创新在于使用了适配器模式来桥接 Electron API 和鸿蒙系统能力。在 web_engine/src/main/ets/adapter/ 目录下,实现了 40+ 个适配器类,覆盖了 Electron 应用所需的各种系统能力:
核心适配器类别
// 1. 窗口管理适配器
AppWindowAdapter // 应用窗口管理
SubWindowAdapter // 子窗口管理
PopupWindowAdapter // 弹窗管理
SystemFloatingWindowAdapter // 系统悬浮窗
// 2. 输入输出适配器
MultiInputAdapter // 多点触控和手势
DragDropAdapter // 拖拽功能
IMFAdapter // 输入法框架
PasteBoardAdapter // 剪贴板
// 3. 设备能力适配器
CameraAdapter // 相机
BluetoothAdapter // 蓝牙
DeviceAdapter // USB 设备
MediaAdapter // 媒体播放
// 4. 系统集成适配器
NotificationAdapter // 系统通知
PermissionManagerAdapter // 权限管理
FileManagerAdapter // 文件管理
PrintAdapter // 打印功能
// 5. UI 与显示适配器
DisplayAdapter // 显示屏幕信息
NativeThemeAdapter // 系统主题(深色/浅色模式)
CursorAdapter // 鼠标光标
FontAdapter // 字体管理
适配器实现示例
以 PermissionManagerAdapter 为例,展示了如何将鸿蒙的权限系统映射到 Electron:
@injectable()
export class PermissionManagerAdapter extends BaseAdapter {
private readonly needPermissions: Map<string, Array<Permissions>> = new Map([
['location', ['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION']],
['microphone', ['ohos.permission.MICROPHONE']],
['camera', ['ohos.permission.CAMERA']],
// ... 更多权限映射
]);
requestPermissions(permissionType: string, callback: (granted: number) => void) {
// 将 Electron 风格的权限请求转换为鸿蒙 API 调用
}
}
3. 依赖注入架构
项目使用 InversifyJS 实现了完整的依赖注入(DI)系统,这是一个企业级的设计模式:
// AdapterModule.ets - 注册所有适配器
export const adapterModule = new ContainerModule((bind) => {
bind(AppLifecycleAdapter).toSelf();
bind(ContextAdapter).toSelf();
bind(DisplayAdapter).toSelf();
bind(DragDropAdapter).toSelf();
// ... 40+ 适配器注册
});
// 使用时通过 Inject 获取
private displayAdapter: DisplayAdapter = Inject.get(DisplayAdapter);
优势:
- 松耦合:模块之间通过接口交互
- 易测试:可以轻松注入 Mock 对象
- 可维护:依赖关系清晰可控
核心技术实现
1. 原生桥接层:libadapter.so
这是整个架构中最关键的一环,负责 ArkTS/ETS 代码与 C++ Electron 引擎之间的通信。
JS Binding 机制
// JsBindingUtils.ets
import adapter from 'libadapter.so';
export default class JsBindingUtils {
static getNativeContext(contextType: number): NativeContext {
return adapter.getNativeContext(contextType);
}
static bindFunction(name: string, func: Function) {
this.currentContext.JSBind.bindFunction(name, func);
}
}
双向调用流程
ArkTS Layer (ETS)
↕ [JSBind]
Native Bridge (libadapter.so)
↕ [C++ Binding]
Electron Engine (libelectron.so)
工作原理:
- ETS → C++: 通过
adapter.getNativeContext()获取原生上下文对象,调用 C++ 方法 - C++ → ETS: 通过
JSBind.bindFunction()将 ETS 函数注册给 C++ 层回调
2. XComponent 渲染管道
Electron 的渲染输出通过鸿蒙的 XComponent 组件实现:
// WebWindow.ets
class WindowNodeController extends NodeController {
makeNode(uiContext: UIContext): FrameNode | null {
this.xComponent = TypedNode.createNode(uiContext, "XComponent", {
type: XComponentType.SURFACE,
controller: this.xComponentController
});
this.xComponent.initialize({
id: this.config.moduleName,
type: XComponentType.SURFACE,
libraryname: "adapter" // 关联 libadapter.so
});
this.xComponent.attribute
.onLoad(() => {
// 初始化窗口边界
this.setDefaultBounds();
// 启动 Electron 浏览器
let vec_args = this.buildArgs();
this.config.nativeContext.runBrowser(vec_args);
})
}
}
关键特性:
XComponentType.SURFACE: 直接渲染原生内容libraryname: "adapter": 加载 libadapter.so 进行原生渲染- 支持手势识别(Pan、Pinch、Tap)和拖拽事件
3. 多进程架构
项目实现了类似 Electron 的多进程模型:
// module.json5
{
"abilities": [
{
"name": "EntryAbility",
"launchType": "specified" // 主进程
},
{
"name": "BrowserAbility",
"process": ":browser" // 浏览器进程
},
{
"name": "StatelessAbility",
"process": ":browser" // 渲染进程
}
]
}
进程隔离优势:
- 主进程崩溃不影响浏览器窗口
- 独立的内存空间提高稳定性
- 符合 Electron 原有的进程模型
4. 窗口生命周期管理
WebAbility 类实现了完整的窗口生命周期管理:
export class WebAbility extends WebBaseAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
super.onCreate(want, launchParam);
// 初始化 KV 存储、更新 WebApp 图标
kvManager.init(this.context);
this.updateWebAppIcon();
// 注入各种适配器
this.displayAdapter = Inject.get(DisplayAdapter);
this.nativeThemeAdapter = Inject.get(NativeThemeAdapter);
Inject.get(PermissionManagerAdapter).initPermissions();
}
onWindowStageCreate(windowStage: window.WindowStage) {
// 监听窗口事件
windowStage.getMainWindow((err, data) => {
data.on('windowStatusChange', (status) => {
this.nativeContext.OnWindowStatusChange(this.xcomponentId, status);
});
data.on('windowSizeChange', (size) => {
let windowBound = this.calculateBounds(data, size);
this.nativeContext.OnWindowSizeChange(this.xcomponentId, windowBound);
});
// ... 更多事件监听
});
// 加载 UI 内容
windowStage.loadContent(this.getContentPath(), storage);
}
async onPrepareToTerminateAsync(): Promise<boolean> {
// 优雅关闭:等待浏览器响应
this.nativeContext.OnWindowEvent(this.xcomponentId, WebAbility.WINDOW_CLOSE);
for (let i = 0; i < MAXIMUM_NUM_OF_SLEEP_CYCLES; i++) {
await this.sleep(SLEEP_INTERVAL_MS);
let response = this.nativeContext.GetBrowserCloseResponse(id);
if (response !== BrowserCloseResponse.kUndetermined) {
break;
}
}
return response === BrowserCloseResponse.kClosingContinue;
}
}
生命周期特点:
- 完整的创建、激活、后台、销毁流程
- 支持异步关闭确认(处理未保存数据)
- 窗口事件实时同步到 Electron 层
技术亮点与创新
1. 适配器自动绑定机制
通过 JsBindingMethod 类统一管理所有适配器的绑定:
export class JsBindingMethod {
static bind() {
AccessibilityAdapterBind.bind();
AppLifecycleAdapterBind.bind();
BluetoothAdapterBind.bind();
// ... 40+ 适配器自动绑定
WebAppAdapterBind.bind();
}
}
每个 AdapterBind 类将鸿蒙 API 函数注册到 C++ 层,实现透明调用。
2. 深色模式与主题适配
完整支持鸿蒙的深色模式和系统主题切换:
onConfigurationUpdate(config: Configuration) {
if (config.colorMode !== undefined) {
this.nativeThemeAdapter?.setSystemNativeTheme(config.colorMode);
}
if (config.fontSizeScale !== undefined) {
this.displayAdapter?.onSystemFontSizeChange(config.fontSizeScale);
}
}
3. 设备模式自适应
支持鸿蒙的 2in1 设备(平板电脑模式)和普通平板模式:
private onPadWindowStageCreate(windowClass: window.Window, storage: LocalStorage) {
// 设置避让区域(状态栏、导航栏)
this.updateAvoidAreaStatus(false);
// 注册设备模式切换监听
this.deviceInfoAdapter?.registerDeviceModeChange(context);
windowClass.on('avoidAreaChange', (data) => {
// 动态调整窗口布局
let statusBarHeight = data.area.topRect.height;
storage.setOrCreate('statusBarHeight', statusBarHeight);
});
}
4. 拖拽与手势支持
实现了完整的拖拽功能,包括从外部应用拖入文件:
.onDragEnter((event?: DragEvent) => {
this.dragDropAdapter.dragEnterData(this.xComponentId, event.getSummary());
})
.onDragMove((event?: DragEvent) => {
let windowX = vp2px(event?.getWindowX());
let windowY = vp2px(event?.getWindowY());
this.dragDropAdapter.dragMove(this.xComponentId, windowX, windowY);
})
.onDrop((event?: DragEvent) => {
let dragData: UnifiedData = event.getData();
this.dragDropAdapter.dropData(this.xComponentId, dragData);
})
5. 权限管理透明化
将 Electron 的权限模型映射到鸿蒙:
private readonly needPermissions: Map<string, Array<Permissions>> = new Map([
['location', ['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION']],
['microphone', ['ohos.permission.MICROPHONE']],
['camera', ['ohos.permission.CAMERA']],
['bluetooth', ['ohos.permission.ACCESS_BLUETOOTH']],
['screen_capture', ['ohos.permission.CUSTOM_SCREEN_CAPTURE']]
]);
requestPermissions(permissionType: string, callback: (granted: number) => void) {
let permissions = this.needPermissions.get(permissionType);
// 调用鸿蒙权限请求 API
this.atManager.requestPermissionsFromUser(this.context, permissions)
.then((data) => {
callback(data.authResults[0]);
});
}
技术挑战与解决方案
挑战 1: 渲染差异
问题: Electron 使用 Chromium 渲染,鸿蒙需要通过 XComponent 接入原生渲染。
解决:
- 使用
XComponentType.SURFACE直接渲染原生内容 - 通过
libadapter.so将 Chromium 的渲染输出映射到 XComponent Surface
挑战 2: API 差异
问题: Electron Node.js API 与鸿蒙 ArkTS API 体系完全不同。
解决:
- 适配器模式:每个 Electron API 对应一个鸿蒙适配器
- 统一接口:所有适配器继承
BaseAdapter - 依赖注入:通过 InversifyJS 管理依赖关系
挑战 3: 多进程通信
问题: Electron 的 IPC 机制需要在鸿蒙上重新实现。
解决:
- 利用鸿蒙的
process属性实现进程隔离 - 通过
AbilityManager管理多个 Ability 实例 - 使用 KV 存储(
kvManager)实现进程间数据共享
挑战 4: 窗口管理复杂性
问题: 鸿蒙的窗口系统与桌面操作系统差异很大。
解决:
- 实现
WindowStyle管理类统一窗口样式 - 监听所有窗口事件并同步到 Electron 层
- 适配平板的自由窗口模式和普通模式
构建与部署
依赖库
// web_engine/oh-package.json5
{
"dependencies": {
"inversify": "^6.0.1", // 依赖注入框架
"reflect-metadata": "^0.1.13" // 元数据反射
},
"devDependencies": {
'libadapter.so': 'file:./src/main/cpp/types/libadapter'
}
}
原生库
项目包含多个关键的 C++ 动态库:
libelectron.so: Electron 引擎核心(约 200MB+)libadapter.so: 适配器桥接层libffmpeg.so: 多媒体编解码支持libc++_shared.so: C++ 标准库
构建配置
// build-profile.json5
{
"app": {
"products": [{
"name": "default",
"compatibleSdkVersion": "6.0.0(20)", // HarmonyOS NEXT
"runtimeOS": "HarmonyOS",
"buildOption": {
"nativeLib": {
"collectAllLibs": true // 自动收集所有 .so 文件
}
}
}]
}
}
性能优化
1. 懒加载策略
使用 ArkTS 的 lazy 关键字延迟加载非关键模块:
import lazy { DragDropAdapter } from '../adapter/DragDropAdapter';
import lazy { DeviceInfoAdapter } from '../adapter/DeviceInfoAdapter';
2. 内存管理
- 及时释放 Ability 资源
- 使用
aboutToDisappear清理事件监听 - 分进程隔离内存空间
3. 渲染优化
- 使用
NodeController代替传统组件渲染 RenderFit.TOP_LEFT避免不必要的布局计算- 背景色预设减少闪烁
应用场景
这个项目适用于以下场景:
- 现有 Electron 应用迁移: 快速将桌面应用迁移到鸿蒙平台
- 跨平台开发: 使用相同的代码库支持 Windows、macOS、Linux 和 HarmonyOS
- 企业应用: 利用 Electron 生态的丰富库和工具链
- Web 技术栈开发者: 使用熟悉的 HTML/CSS/JS 开发鸿蒙应用
未来展望
可能的改进方向
- 性能优化: 进一步减少渲染延迟和内存占用
- API 完善: 补充更多 Electron API 的适配实现
- 开发工具: 提供调试工具和性能分析工具
- 文档完善: 提供详细的迁移指南和最佳实践
生态建设
- 建立社区支持 Electron on HarmonyOS
- 提供示例应用和模板项目
- 集成鸿蒙特有能力(如分布式任务)
总结
将 Electron 移植到鸿蒙平台是一个极具挑战性的工程,涉及跨平台、跨语言、跨架构的多重技术难题。本项目通过以下核心技术实现了这一目标:
- 适配器模式: 40+ 系统适配器桥接两个生态
- 原生桥接: libadapter.so 实现 ArkTS 与 C++ 的双向调用
- 依赖注入: InversifyJS 构建松耦合的模块系统
- XComponent 渲染: 原生渲染管道支持 Chromium 内容
- 多进程架构: 保持 Electron 的进程隔离模型
这个项目不仅是技术移植,更是对跨平台开发理念的一次深入实践。它证明了通过合理的架构设计和技术选型,可以在保持应用原有特性的同时,让其在全新的平台上焕发生机。
对于想要进入鸿蒙生态的开发者,这个项目提供了一个极好的参考案例,展示了如何系统性地解决平台差异问题,实现真正的跨平台兼容。
项目关键指标:
- 🏗️ 架构模块: 2 个(electron + web_engine)
- 🔌 适配器数量: 40+ 个系统适配器
- 📦 原生库: 4 个 .so 文件
- 🎯 支持设备: 平板和 2in1 设备
- 💡 核心技术: ArkTS + C++ + Electron
本文基于实际项目代码分析撰写,涵盖架构设计、核心技术实现和工程实践经验。希望对从事跨平台开发和鸿蒙生态建设的开发者有所启发。
更多推荐


所有评论(0)