Electron进程之间的通信方式以及几个核心之间的关系

一、主进程 vs 渲染进程:核心对比

特性 主进程 (Main Process) 渲染进程 (Renderer Process)
运行环境 Node.js 环境 Chromium 浏览器环境
数量 唯一(整个应用只有一个) 多个(每个窗口对应一个)
权限 可调用所有 Node.js API 默认无法直接访问 Node.js(需 IPC 代理)
典型职责 创建窗口、系统菜单、托盘图标、文件操作 渲染界面、处理用户交互、前端逻辑
生命周期 控制应用启动/退出 窗口关闭时自动销毁

二、IPC 通信机制详解

1. 通信模式示意图

csharp 复制代码
[渲染进程]                            [主进程]
   │                                      │
   │   ipcRenderer.send('event', data)    │
   ├─────────────────────────────────────>│
   │                                      │
   │   ipcMain.on('event', handler)       │
   │<─────────────────────────────────────┤
   │   event.reply('reply-event', result) │
   │                                      │
   │   ipcRenderer.on('reply-event')      │
   │                                      │

2. 三种核心通信方式

方式 1:渲染进程 → 主进程(异步)

javascript 复制代码
// 渲染进程(通过预加载脚本暴露的方法)
window.electronAPI.sendMessage('Hello Main!');

// 主进程
ipcMain.on('send-message', (event, data) => {
  console.log(data); // 输出: Hello Main!
  event.reply('reply-message', 'Received!');
});

// 渲染进程接收回复
window.electronAPI.onReply((data) => {
  console.log(data); // 输出: Received!
});

方式 2:渲染进程 → 主进程(同步)

javascript 复制代码
// 渲染进程(谨慎使用,会阻塞界面!)
const result = window.electronAPI.syncMessage('Sync request');

// 主进程
ipcMain.on('sync-message', (event, data) => {
  event.returnValue = 'Sync response';
});

方式 3:主进程 → 渲染进程(主动推送)

javascript 复制代码
// 主进程
const win = new BrowserWindow(...);
win.webContents.send('update-data', { value: 42 });

// 渲染进程
window.electronAPI.onUpdateData((data) => {
  console.log(data.value); // 输出: 42
});

三、预加载脚本(Preload Script):安全桥梁

1. 核心作用图解

scss 复制代码
[Node.js 环境]                   [隔离的浏览器环境]
    主进程 <── IPC ──> 预加载脚本 <──> 渲染进程
                    (暴露有限 API)

2. 安全配置代码

javascript 复制代码
// 创建窗口时配置
new BrowserWindow({
  webPreferences: {
    preload: path.join(__dirname, 'preload.js'),
    contextIsolation: true, // 启用上下文隔离
    nodeIntegration: false  // 禁止直接访问 Node.js
  }
});

// preload.js
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  sendMessage: (data) => ipcRenderer.send('send-message', data),
  onReply: (callback) => ipcRenderer.on('reply-message', callback)
});

四、核心关系与通信场景

1. 典型场景示例

场景 1:文件读取

javascript 复制代码
// 预加载脚本暴露方法
contextBridge.exposeInMainWorld('electronAPI', {
  readFile: (path) => ipcRenderer.invoke('read-file', path)
});

// 主进程处理
ipcMain.handle('read-file', async (event, path) => {
  return await fs.promises.readFile(path, 'utf-8');
});

// 渲染进程调用
const content = await window.electronAPI.readFile('data.txt');

场景 2:多窗口通信

javascript 复制代码
// 主进程维护窗口引用
const wins = new Map();

ipcMain.on('create-window', (event, id) => {
  const win = new BrowserWindow();
  wins.set(id, win);
});

ipcMain.on('send-to-window', (event, id, message) => {
  const targetWin = wins.get(id);
  targetWin.webContents.send('receive-message', message);
});

五、关键安全原则

  1. 永远不要这样做 ❌:

    html 复制代码
    <!-- 禁用安全配置的危险写法 -->
    <webview nodeIntegration></webview>
    <script>
      require('child_process').exec('rm -rf /'); // 恶意代码可执行系统命令!
    </script>

    运行 HTML

  2. 必须遵循的安全实践 ✅:

    • 始终启用 contextIsolation: true
    • 始终禁用 nodeIntegration: false
    • 通过预加载脚本白名单式暴露 API
    • 验证渲染进程发送的所有数据

六、性能优化建议

  1. 减少 IPC 调用频率

    合并多次操作为单次批处理:

    javascript 复制代码
    // 避免
    for (let i = 0; i < 100; i++) {
      window.electronAPI.updateItem(i);
    }
    
    // 推荐
    window.electronAPI.batchUpdate(items);
  2. 使用 SharedArrayBuffer 传递大数据

    适用于需要高频更新的大量数据(如图像处理):

    javascript 复制代码
    // 主进程
    const sharedBuffer = new SharedArrayBuffer(1024);
    win.webContents.send('shared-data', sharedBuffer);
    
    // 渲染进程
    const sameBuffer = receivedBuffer;

七、总结:核心关系图谱

css 复制代码
[主进程] 
  ├── 通过 BrowserWindow 创建 → [渲染进程]
  ├── 通过 ipcMain 监听 ←→ ipcRenderer 发送(IPC 通信) 
  └── 通过预加载脚本 → 安全暴露 API

[渲染进程]
  ├── 通过 window.electronAPI 调用受限功能
  └── 通过 webContents.send 接收主进程推送
相关推荐
大蓝头4 天前
安装包UI美化之路-nsNiuniuSkin全新UI调试与预览方法
ui·electron·安装包·截图控件·截屏控件
flash俊杰5 天前
Electron 打包后窗口 30 秒不出现:一个 ABI 不匹配的血案
electron·node.js
flash俊杰7 天前
Electron 安全纵深:contextIsolation、最小暴露面与 CSP 防线
electron
凤城老人8 天前
从零手写开源私有云盘|Flask+Vue3+Electron全栈网盘,单容器一键部署
python·docker·electron·vue
flash俊杰8 天前
Electron 自定义协议与视频流式加载:从 moov atom 到 Range 请求的工程化实践
electron·前端框架
愛芳芳8 天前
基于 Electron + Vue3 的仿 PC 微信客户端项目实战
前端·javascript·css·elementui·typescript·electron·vue
Patrick_Wilson11 天前
桌面端发布的真实成本:签名、公证和那支不能共享的 USB Key
ci/cd·electron·客户端
爱丶不疚11 天前
Electron: 你是否需要对 Preload 开启 nodeIntegration?
安全·性能优化·electron
爱丶不疚11 天前
Electron:Module 与 Service 的职责边界与加载时序编排
前端·electron·nestjs
爱丶不疚11 天前
Electron: 缓存机制有哪些?能控制的又有哪些
前端·electron·v8