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 接收主进程推送
相关推荐
卸任2 天前
Electron自制翻译工具:增加中英互译
前端·react.js·electron
皓子3 天前
海狸IM桌面端:AI辅助开发的技术架构实践
前端·electron·ai编程
xiaobangsky5 天前
Electron桌面应用下,在拍照、展示pdf等模块时,容易导致应用白屏
javascript·electron
就是我5 天前
Electron多窗口应用实战
前端·javascript·electron
我怎么能这么帅气5 天前
从“文件失踪案”说起:Electron 中 getAppPath 和 getPath 的妙用
前端·javascript·electron
集成显卡8 天前
图片压缩工具 | Electron+Vue3+Rsbuild开发桌面应用
前端·javascript·electron·vue
朝阳398 天前
Electron-vite【实战】MD 编辑器 -- 系统菜单(含菜单封装,新建文件,打开文件,打开文件夹,保存文件,退出系统)
electron·编辑器
朝阳399 天前
Electron-vite【实战】MD 编辑器 -- 文件列表(含右键快捷菜单,重命名文件,删除本地文件,打开本地目录等)
electron·编辑器
HCl+NaOH=NaCl+H_2O9 天前
quasar electron mode如何打包无边框桌面应用程序
前端·javascript·electron
屋昂仼9 天前
Electron 桌面程序读取dll动态库
前端·javascript·electron