Electron 进程架构模型

Electron 的 JS 代码分布在两个独立的进程中:主进程(Node.js Runtime)和渲染进程(Chromium V8 Runtime)。它们不是"一个 JS 环境",而是两个完全隔离的 OS 进程,通过 IPC 协作。


一、Electron 的进程架构模型

scss 复制代码
┌─────────────────────────────────────────────────────────────┐
│                        操作系统                              │
│  ┌─────────────────────┐    ┌─────────────────────────────┐ │
│  │     主进程 (1个)      │    │      渲染进程 (N个)          │ │
│  │   Main Process       │    │    Renderer Process × N     │ │
│  │  ┌───────────────┐   │    │  ┌─────────────────────┐    │ │
│  │  │  Node.js      │   │    │  │   Chromium          │    │ │
│  │  │  Runtime      │   │◄──►│  │   ┌─────────────┐   │    │ │
│  │  │  (V8 + libuv) │   │IPC │  │   │  Blink 引擎  │   │    │ │
│  │  │               │   │    │  │   │  (DOM/CSS/JS)│   │    │ │
│  │  │  • 文件系统    │   │    │  │   └─────────────┘   │    │ │
│  │  │  • 网络请求    │   │    │  │   ┌─────────────┐   │    │ │
│  │  │  • 原生模块    │   │    │  │   │  V8 引擎    │   │    │ │
│  │  │  • 窗口管理    │   │    │  │   │ (隔离沙箱)   │   │    │ │
│  │  │  • 系统API    │   │    │  │   └─────────────┘   │    │ │
│  │  └───────────────┘   │    │  └─────────────────────┘    │ │
│  └─────────────────────┘    └─────────────────────────────┘ │
│         ▲                              ▲                    │
│         │      预加载脚本 (Preload)      │                    │
│         └──────────── 桥梁 ──────────────┘                    │
└─────────────────────────────────────────────────────────────┘

二、每个进程内部的线程模型

主进程(Main Process)

scss 复制代码
┌─────────────────────────────────────┐
│         主进程 (单个进程)             │
│  ┌─────────────────────────────┐   │
│  │      Node.js Event Loop     │   │
│  │         (libuv)             │   │
│  │  ┌─────┐ ┌─────┐ ┌─────┐   │   │
│  │  │ V8  │ │ 网络 │ │ 文件 │   │   │
│  │  │ 主线程│ │ IO  │ │ IO  │   │   │
│  │  └─────┘ └─────┘ └─────┘   │   │
│  │       ↓ 工作线程池 (libuv)   │   │
│  └─────────────────────────────┘   │
│  • 单线程事件循环(同标准 Node.js)   │
│  • 异步 IO 委托给 libuv 线程池      │
│  • 原生模块可能创建自己的线程        │
└─────────────────────────────────────┘

关键:主进程只有一个,是应用的入口和控制器。

渲染进程(Renderer Process)

scss 复制代码
┌─────────────────────────────────────────┐
│         渲染进程 (每个窗口一个)            │
│  ┌─────────────────────────────────┐   │
│  │        Chromium 多线程架构         │   │
│  │                                 │   │
│  │  ┌─────────┐  ┌─────────────┐   │   │
│  │  │ Browser │  │   Renderer  │   │   │
│  │  │ 线程    │  │   线程      │   │   │
│  │  │ (主线程)│  │ (合成/绘制)  │   │   │
│  │  └────┬────┘  └─────────────┘   │   │
│  │       │                          │   │
│  │  ┌────┴────┐  ┌─────────────┐   │   │
│  │  │   V8    │  │   IO 线程    │   │   │
│  │  │ 主线程   │  │ (网络/存储)   │   │   │
│  │  │ (执行JS) │  │             │   │   │
│  │  └─────────┘  └─────────────┘   │   │
│  │                                 │   │
│  │  • 还有 GPU 进程、扩展进程等       │   │
│  │    (Chromium 架构决定)            │   │
│  └─────────────────────────────────┘   │
└─────────────────────────────────────────┘

关键:每个 BrowserWindow 创建一个独立的渲染进程。


三、你的 JS 代码到底跑在哪?

代码位置 运行在哪个 Runtime 能做什么 不能做什么
main.js (入口) Node.js Runtime (主进程) 文件系统、网络、创建窗口、系统API 直接操作 DOM
preload.js 混合环境 (渲染进程,但有 Node.js 上下文) require() 模块、ipcRenderer 不能直接访问页面 DOM(有隔离)
页面 JS (index.html 内) Chromium V8 (渲染进程,纯浏览器环境) DOM 操作、Web API、调用 window.api require()fsos 等 Node 模块

四、预加载脚本(Preload)的关键角色

这是 Electron 架构中最容易被误解的部分:

javascript 复制代码
┌─────────────────────────────────────────────┐
│              渲染进程                         │
│  ┌─────────────────────────────────────┐   │
│  │         上下文隔离 (ContextIsolation)  │   │
│  │  ┌─────────────┐  ┌─────────────┐   │   │
│  │  │  Preload    │  │   页面 JS    │   │   │
│  │  │  上下文      │  │   上下文     │   │   │
│  │  │             │  │             │   │   │
│  │  │ • 有 Node.js│  │ • 纯浏览器   │   │   │
│  │  │ • 可 require│  │ • 无 require │   │   │
│  │  │ • 可 IPC    │  │ • 只能 Web API│   │   │
│  │  └──────┬──────┘  └──────┬──────┘   │   │
│  │         │                │           │   │
│  │         └──── contextBridge ────────┘   │   │
│  │              (安全暴露 API)               │   │
│  └─────────────────────────────────────┘   │
└─────────────────────────────────────────────┘
javascript 复制代码
// preload.js --- 运行在渲染进程,但有 Node.js 能力
const { contextBridge, ipcRenderer } = require('electron')

// 把 ipcRenderer 的能力安全地暴露给页面 JS
contextBridge.exposeInMainWorld('electronAPI', {
  readFile: (path) => ipcRenderer.invoke('fs:readFile', path),
  onUpdate: (callback) => ipcRenderer.on('update', callback)
})

// 页面 JS 中:
// window.electronAPI.readFile('/path') → 发 IPC → 主进程处理 → 返回结果

关键洞察:

  • Preload 和页面 JS 不在同一个 V8 上下文 ,但通过 contextBridge 可以安全通信。
  • 这是 Electron 的安全架构核心------防止不受信任的页面代码直接访问系统能力。

五、协作模型:消息流示例

javascript 复制代码
用户点击按钮 (渲染进程)
    │
    ▼
页面 JS: window.electronAPI.saveFile(data)
    │
    ▼
Preload: ipcRenderer.invoke('dialog:save', data) ──┐
    │                                               │
    ▼                                               │
V8 序列化消息 ──────► Chromium IPC 管道 ────────────┤
    │                                               │
    ▼                                               │
操作系统内核 IPC ─────► 主进程接收                   │
    │                                               │
    ▼                                               │
主进程: ipcMain.handle('dialog:save', async (e, data) => {
    const { filePath } = await dialog.showSaveDialog()
    await fs.writeFile(filePath, data)
    return { success: true }
})
    │
    ▼
结果反向通过 IPC 返回 ──► Preload ──► 页面 JS Promise resolve

六、与 React Native 的对比(回应你之前的类比)

维度 React Native Electron
JS 运行位置 单个进程内的 JS 引擎(Hermes/JSC) 两个独立进程(主进程 Node.js + 渲染进程 Chromium V8)
原生通信 JSI / Bridge(同进程内存共享或异步) IPC(跨进程消息,必然序列化)
JS 线程数 1 个 JS 线程 + 原生模块线程 主进程 1 个 V8 + 每个窗口 1 个 V8
渲染 Yoga 布局 + 平台原生组件 Chromium Blink 引擎直接渲染
安全模型 相对宽松(同进程) 严格进程隔离 + ContextIsolation

七、一句话总结

Electron 的 JS 代码"分身"运行在两个世界:主进程是"拥有系统权限的 Node.js 后端",渲染进程是"被沙箱隔离的 Chromium 前端"。它们通过 IPC 像微服务一样协作,预加载脚本是两者之间的安全网关。这不是"一个 JS 环境",而是"两个独立运行时通过消息协议协作"的分布式架构。

相关推荐
greenbbLV几秒前
中小公司积分商城选型:SaaS与私有化方案对比解析
大数据·前端·小程序
NutShell Wang1 小时前
Vite 8.1 深度拆解:Rolldown 统一打包器如何终结前端构建的「双引擎时代」
前端·rust·开源·vite·开发者工具·vibe coding
朱容zr3331331 小时前
请解释“回表”的概念。
java·前端·数据库
leslie1182 小时前
webpack笔记
前端·webpack
宁风NF2 小时前
JavaScript:内存、垃圾回收、性能优化
开发语言·前端·javascript·学习·性能优化·es6
勾勾圈圈蛋蛋2 小时前
DOM、BOM、DOM操作详解 + 结合Vue响应式关联梳理
前端
打妖妖灵滴哪吒2 小时前
IOS模态窗口的作用与设计原则
前端·ui
午安~婉2 小时前
挑战二:博客预览卡片
前端·javascript·html
环境栈笔记3 小时前
指纹浏览器安全评测方法:核对环境、数据与权限后再选型
前端·人工智能·后端·自动化
打妖妖灵滴哪吒3 小时前
前端开发/UI设计师-APP中如何进行可发现性设计
前端·ui