架构
Renderer、Preload 与 Electron Main 之间的通信链路。
Desktop IPC 将 Renderer 和 Electron Main 隔离成两个运行时。Renderer 只依赖意图明确的 Runtime 接口,Preload 是唯一的桥接面,Main 再把请求交给对应的桌面领域模块。
请求链路
业务组件 / Hook
│
▼
@/lib/runtime
│ createElectronRuntime()
▼
window.electronAPI
│ contextBridge
▼
apps/desktop/electron/preload/index.ts
│ invoke / send / postMessage
▼
apps/desktop/electron/main/ipc/<capability>.ts
│
▼
Electron Main 的桌面领域模块
│
▼
Promise、事件或 MessagePort 回传 Renderer三个边界
Renderer:表达意图
页面和组件只调用类似 runtime.window.setFullscreen(true)、runtime.cache.get(key) 或 runtime.updates.check() 的意图接口,不拼接 IPC channel,也不处理 Electron 对象。
Preload:暴露最小桥面
preload.ts 使用 contextBridge.exposeInMainWorld("electronAPI", electronAPI) 暴露 DesktopBridge 的实现。每个方法只负责把已定义的参数转成 IPC 调用,并把返回值映射回类型化结果。
Main:执行受保护操作
main/ipc/ 按业务能力注册 ipcMain.handle / ipcMain.on,检查发送者、验证 payload,然后调用 window/、services/ 或 capabilities/ 中的 Main 模块。
传输方式
| 方式 | 适合场景 | 当前示例 |
|---|---|---|
invoke / handle | 需要返回值的请求-响应操作 | 获取配置、缓存、更新状态、选择文件 |
send / on | 不需要等待结果的命令或通知 | 退出应用、导航、歌词命令、播放状态 |
sendSync | 仅保留的旧版迁移兼容 | 读取旧版加密音乐凭据 |
MessageChannel | 高频、连续、可独立关闭的数据流 | 音频特征帧、播放传输 payload |
高频传输不能退化成大量普通 IPC 请求。音频特征和播放传输使用 MessagePort,并通过 connect 返回取消函数;音频帧发布失败时返回 false,由调用方决定是否丢帧或重连。
返回值与事件
请求方法通常返回 Promise<T>,例如 getHostConfig();命令方法明确返回 void 或 boolean,例如 exitApp()、toggleDeveloperTools()。订阅方法统一返回 Unsubscribe,组件卸载时必须调用它移除监听器。
事件从 Main 发往 Renderer 时,应使用契约中的事件类型,并在 Preload 中隐藏 Electron event 对象,只把业务 payload 传给回调。