ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Electron 进程与 IPC 通信详解:主进程、渲染进程与 Preload

2026/9/16 9:19:42 拓冰建站 浏览量
Electron 进程与 IPC 通信详解:主进程、渲染进程与 Preload 一、前言在使用 Electron 开发桌面应用时经常会接触到Main Process主进程Renderer Process渲染进程Preload Script预加载脚本IPCInter-Process Communication进程间通信很多刚开始学习 Electron 的开发者容易把它们理解成普通的前端线程但实际上 Electron 的核心架构是多进程模型。例如我们正在开发一个 Electron Vue 桌面应用Electron │ ├── Main Process │ │ │ ├── 创建窗口 │ ├── 文件系统 │ ├── SQLite │ ├── Node.js │ └── 系统级能力 │ ├── Preload Script │ │ │ └── 安全暴露 API │ └── Renderer Process │ ├── Vue ├── HTML ├── CSS └── 页面交互那么Vue 页面如果需要访问 SQLite、读取文件或者启动 Python 服务就不能直接操作而是需要通过 IPC 与主进程进行通信。本文就详细介绍 Electron 的进程模型以及 IPC 通信方式。二、Electron 的进程模型Electron 主要由以下几个部分组成名称作用常用 API主进程Main Process创建和管理窗口、执行系统级操作、访问 Node.js APIapp、BrowserWindow、ipcMain、globalShortcut渲染进程Renderer Process负责页面 UI 渲染和用户交互DOM、Vue、浏览器 API预加载脚本Preload Script连接主进程和渲染进程在安全环境下暴露 APIcontextBridge、ipcRenderer需要特别注意Preload 是一个脚本而不是独立的 Electron 进程。因此更准确的理解应该是┌────────────────────────────────────────────┐ │ Electron Application │ │ │ │ ┌──────────────┐ │ │ │ Main Process │ │ │ │ │ │ │ │ Node.js │ │ │ │ SQLite │ │ │ │ File System │ │ │ └──────┬───────┘ │ │ │ IPC │ │ │ │ │ ┌──────▼────────┐ │ │ │ Preload │ │ │ │ contextBridge │ │ │ └──────┬────────┘ │ │ │ │ │ ┌──────▼──────────────┐ │ │ │ Renderer Process │ │ │ │ │ │ │ │ Vue │ │ │ │ HTML / CSS / DOM │ │ │ └─────────────────────┘ │ └────────────────────────────────────────────┘三、主进程Main Process主进程是 Electron 应用的核心进程。通常一个 Electron 应用只有一个主进程。主进程主要负责创建 BrowserWindow管理应用生命周期访问 Node.js API操作文件系统操作 SQLite启动和管理 Python 服务创建系统托盘注册全局快捷键处理 IPC管理应用级状态例如import{app,BrowserWindow}fromelectronletmainWindow:BrowserWindow|nullnullfunctioncreateWindow(){mainWindownewBrowserWindow({width:1400,height:900,webPreferences:{preload:/path/to/preload.js}})}app.whenReady().then((){createWindow()})主进程可以访问 Node.jsimportfsfromnode:fsimportpathfromnode:path因此类似下面这些操作通常应该放在主进程读取文件 ↓ SQLite ↓ 启动 Python ↓ 操作系统 API ↓ 创建窗口四、渲染进程Renderer Process渲染进程主要负责 UI。如果我们使用Electron Vue 3 TypeScript那么 Vue 应用基本就是运行在渲染进程中。例如script setup langtsconsthandleClick(){console.log(点击按钮)}/scripttemplatebutton clickhandleClick保存文章/button/template渲染进程可以使用VueHTMLCSSDOMwindowlocalStorage浏览器 API但是在安全配置下不应该直接使用 Node.js API。例如不建议在 Vue 页面中直接importfsfromfs也不要让页面直接拥有完整的 Node.js 能力。原因很简单如果网页代码可以直接访问 Node.js那么一旦页面存在 XSS 等安全问题攻击者可能获得文件系统等更高权限。因此 Electron 提供了 Preload Script。五、Preload ScriptPreload 可以理解为渲染进程与主进程之间的安全桥梁。Preload 通常运行在页面加载之前并通过 contextBridge 向 Vue 暴露有限的 API。例如import{contextBridge,ipcRenderer}fromelectroncontextBridge.exposeInMainWorld(electronAPI,{getAppInfo:(){returnipcRenderer.invoke(app:getInfo)}})这样 Vue 页面就可以使用window.electronAPI.getAppInfo()但是 Vue 并没有直接获得ipcRenderer或者fs这样的底层能力。整个调用关系Vue │ │ window.electronAPI.getAppInfo() ↓ Preload │ │ ipcRenderer.invoke() ↓ Main Process │ │ ipcMain.handle() ↓ 执行具体业务六、什么是 IPCIPC 全称Inter-Process Communication也就是进程间通信。因为 Electron 的主进程和渲染进程是不同的进程所以它们不能像普通 JavaScript 函数一样直接调用。例如Vue ↓ 我要读取一个 Markdown 文件 ↓ Main Process ↓ fs.readFile() ↓ 返回 Markdown 内容 ↓ Vue中间就需要通过 IPC 传递消息。七、Electron 常见 IPC 通信方式Electron 中最常见的 IPC 通信方式主要有类型渲染进程主进程特点请求-响应ipcRenderer.invoke()ipcMain.handle()推荐单向消息ipcRenderer.send()ipcMain.on()无返回值主进程主动推送ipcRenderer.on()webContents.send()主进程主动通知八、渲染进程 → 主进程invoke / handle这是开发桌面应用时最推荐的一种方式。例如Vue ↓ invoke() ↓ Preload ↓ ipcRenderer.invoke() ↓ Main ↓ ipcMain.handle() ↓ 返回结果8.1 Main Processimport{ipcMain}fromelectronipcMain.handle(app:getInfo,async(){return{name:CSDN Auto,version:1.0.0}})8.2 Preloadimport{contextBridge,ipcRenderer}fromelectroncontextBridge.exposeInMainWorld(electronAPI,{getAppInfo:(){returnipcRenderer.invoke(app:getInfo)}})8.3 VueconstappInfoawaitwindow.electronAPI.getAppInfo()console.log(appInfo)最终得到{name:CSDN Auto,version:1.0.0}这种方式特别适合获取文章保存文章删除文章查询 SQLite创建任务获取账号读取配置因为它具有明确的请求 ↓ 处理 ↓ 返回 关系。九、渲染进程 → 主进程send / on如果不需要返回结果可以使用ipcRenderer.send()配合ipcMain.on()例如PreloadcontextBridge.exposeInMainWorld(electronAPI,{writeLog:(message:string){ipcRenderer.send(log:write,message)}})MainipcMain.on(log:write,(_event,message){console.log([Renderer],message)})Vuewindow.electronAPI.writeLog(用户点击了发布按钮)这种方式适合日志 埋点 通知 不需要返回值的操作不过对于大多数业务请求还是更推荐invoke / handle十、主进程 → 渲染进程有些时候不是 Vue 主动请求而是主进程产生了新的状态需要主动通知 Vue。例如Python 自动发布文章 ↓ 任务进度发生变化 ↓ Electron Main ↓ 通知 Vue ↓ 进度条更新这时候可以使用webContents.send()配合ipcRenderer.on()10.1 Main ProcessmainWindow.webContents.send(task:progress,{taskId:task_001,progress:60})10.2 PreloadcontextBridge.exposeInMainWorld(electronAPI,{onTaskProgress:(callback){ipcRenderer.on(task:progress,(_event,data){callback(data)})}})10.3 Vuewindow.electronAPI.onTaskProgress((data){console.log(任务进度:,data.progress)})页面就可以实时更新正在发布文章... ████████████░░░░░░░░ 60%十一、推荐的 IPC 使用原则实际开发中可以按照下面的原则设计。默认使用 invoke / handle例如查询文章 保存文章 删除文章 创建任务 查询账号 读取配置统一ipcRenderer.invoke() ↓ ipcMain.handle()主进程主动推送使用 send / on例如任务进度 Python 状态 发布日志 下载进度 窗口状态使用webContents.send() ↓ ipcRenderer.on()send / on 只用于真正的单向通知例如记录日志 发送统计信息 通知主进程刷新不要所有东西都使用send / on否则后期很容易出现发送了消息 但是不知道什么时候结束 也不知道有没有执行成功业务代码会越来越难维护。十二、推荐封装 IPC随着项目越来越大不建议把ipcMain.handle(...)全部写在main.ts里面。例如electron/ ├── ipc/ │ ├── app.ipc.ts │ ├── window.ipc.ts │ ├── article.ipc.ts │ ├── task.ipc.ts │ ├── account.ipc.ts │ └── system.ipc.ts │ ├── services/ │ ├── article.service.ts │ ├── task.service.ts │ └── account.service.ts │ └── main.ts这样main.ts │ ├── 注册 app IPC ├── 注册 article IPC ├── 注册 task IPC └── 注册 account IPC十四、最终推荐的通信架构对于一个中大型 Electron 项目我比较推荐Vue Renderer │ │ window.api │ ↓ Preload │ │ IPC ↓ Electron Main │ │ │ │ SQLite WebSocket │ │ │ ↓ │ Python Engine │ │ │ Playwright │ │ │ ↓ │ CSDN │ ↓ 本地数据其中每一层只负责自己的事情层级主要职责VueRenderer UI、交互、页面状态Preload安全暴露 APIElectron Main系统能力、数据库、进程管理Python Engine浏览器自动化、CSDN 操作SQLite本地业务数据WebSocketElectron 与 Python 双向通信十六、总结Electron 的核心并不是简单地把一个网页套进桌面窗口而是一个基于多进程架构的桌面应用框架。开发 Electron 应用时可以简单记住Renderer负责 UIPreload负责安全桥接Main负责系统能力IPC负责 Renderer ↔ Main 通信WebSocket负责 Electron ↔ Python Engine 通信业务请求优先使用ipcRenderer.invoke() ↓ ipcMain.handle()主进程主动推送状态使用webContents.send() ↓ ipcRenderer.on()而对于 CSDN Auto 这样的桌面自动化软件可以进一步采用Vue ↓ Preload ↓ IPC ↓ Electron Main ↓ WebSocket ↓ Python Engine ↓ Playwright ↓ CSDN这种架构能够很好地将 UI、桌面能力、数据存储以及自动化能力 分离开来也方便后续继续扩展 AI 写作、定时发布、多账号管理、任务队列等功能。