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 接收主进程推送
相关推荐
Rachel_wang2 小时前
如何安装并启动 electron-prokit(react+ts) 项目
react.js·electron
日升5 天前
Electron 开发:获取当前客户端真实 IP
前端·javascript·electron
阿廖沙10245 天前
Electron 主进程和渲染进程通信
electron
A_ugust__7 天前
Vue3.2 项目打包成 Electron 桌面应用
javascript·vue.js·electron
森叶8 天前
利用本地 Express Web 服务解决复杂的 Electron 通信链路的问题
前端·electron·express
土豆丶杨8 天前
vue3+electron 桌面应用初始化
javascript·vue.js·electron
PegasusYu8 天前
Electron使用WebAssembly实现CRC-32 STM32校验
stm32·electron·nodejs·wasm·webassembly·crc32·crc-32
Substitute10 天前
换个思路!在 Electron 主进程中流畅驱动你的自定义窗口动画
electron
Python私教10 天前
安装electron项目是为什么要执行postinstall script
前端·javascript·electron