Electron IPC 模式
Electron 的 IPC 负责在 main 与 renderer 之间做受控通信,常见模式包括单向通知、请求响应和主进程主动推送。
#tech / dev / desktop
#resource / electron
#type / concept
#status / growing
[!info] related notes
- 所属 MOC: Electron MOC
- 前置概念: IPC, Electron preload 脚本
- 并列概念: Electron 主进程, Electron 渲染进程
- 易混淆概念: IPC
- 关系笔记: Electron
Electron IPC 模式
一句话定义
Electron IPC 是主进程(main)与渲染进程(renderer)之间的受控通信机制,通过 preload 脚本和 contextBridge 安全地暴露能力,是多进程桌面应用协作的核心。
核心机制 / 工作原理
为什么需要 IPC
Electron 的多进程架构决定了 UI 和系统能力不在同一个进程:
- 渲染进程:运行网页代码,沙箱环境,无 Node.js 权限
- 主进程:可访问文件系统、原生对话框、系统 API
- 渲染进程想做高权限操作,必须通过 IPC 向主进程发请求
- 主进程想通知窗口状态变化,也必须通过 IPC 向目标渲染进程发消息
三种通信模式
1. invoke / handle(请求-响应,推荐)
渲染进程发起请求,主进程处理并返回结果。异步,基于 Promise。
// preload.js — 暴露安全 API
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('api', {
readFile: (path) => ipcRenderer.invoke('file:read', path),
});
// main.js — 处理请求
const { ipcMain } = require('electron');
ipcMain.handle('file:read', async (event, path) => {
return await fs.promises.readFile(path, 'utf-8');
});
// renderer.js — 调用
const content = await window.api.readFile('/etc/hosts');
2. send / on(单向通知)
渲染进程发送消息,主进程监听处理,无返回值。
// preload.js
contextBridge.exposeInMainWorld('api', {
logEvent: (name) => ipcRenderer.send('analytics:event', name),
});
// main.js
ipcMain.on('analytics:event', (event, name) => {
trackEvent(name);
});
3. 主进程主动推送
主进程通过 webContents.send 向指定窗口发消息。
// main.js
win.webContents.send('update:available', { version: '2.0.0' });
// preload.js
ipcRenderer.on('update:available', (event, data) => {
// 通知渲染进程
});
sendSync(同步调用,不推荐)
ipcRenderer.sendSync 会阻塞渲染进程直到主进程返回,容易导致 UI 卡顿。仅在极少数需要同步结果的场景使用。
双向通信模式
组合使用上述模式实现完整双向通信:
renderer --invoke--> main (请求数据)
renderer <--send---- main (推送通知)
renderer --send----> main (发送事件)
最小例子
完整的安全 IPC 模式:
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
// 请求-响应
getAppVersion: () => ipcRenderer.invoke('app:version'),
// 单向通知
openExternal: (url) => ipcRenderer.send('shell:openExternal', url),
// 监听主进程推送
onUpdateAvailable: (callback) => {
ipcRenderer.on('update:available', (_, data) => callback(data));
return () => ipcRenderer.removeAllListeners('update:available');
},
});
边界与常见误解
- 不要设置
nodeIntegration: true:这会将完整的 Node.js 暴露给网页,任何 XSS 都能执行任意代码 - 不要设置
contextIsolation: false:关闭上下文隔离意味着网页代码可篡改 preload 暴露的 API - IPC 不是万能 RPC:不应把所有后端能力都通过一个 channel 暴露,应按职责拆分 channel
- channel 命名要稳定:使用
domain:action格式(如file:read、dialog:open),便于维护 - 参数要校验:主进程收到的参数来自渲染进程,不可信,需做类型和边界检查
- sender 校验:高权限 IPC(如文件写入)应检查
event.senderFrame确保调用来源合法 - 清理监听器:组件卸载时移除 IPC 监听器,避免内存泄漏
- 性能考量:IPC 有序列化开销,避免传输大对象;高频调用应考虑批量合并