Electron IPC 模式

Electron 的 IPC 负责在 main 与 renderer 之间做受控通信,常见模式包括单向通知、请求响应和主进程主动推送。

#tech / dev / desktop #resource / electron #type / concept #status / growing

[!info] related notes

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:readdialog:open),便于维护
  • 参数要校验:主进程收到的参数来自渲染进程,不可信,需做类型和边界检查
  • sender 校验:高权限 IPC(如文件写入)应检查 event.senderFrame 确保调用来源合法
  • 清理监听器:组件卸载时移除 IPC 监听器,避免内存泄漏
  • 性能考量:IPC 有序列化开销,避免传输大对象;高频调用应考虑批量合并
创建于 2026/4/13 更新于 2026/5/27