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 环境",而是"两个独立运行时通过消息协议协作"的分布式架构。

相关推荐
kyriewen几秒前
2026 年了,这 6 个 npm 包可以卸载了——浏览器原生 API 已经能替代
前端·javascript·npm
Csvn3 小时前
Monorepo 迁移血泪史:从 Multi-Repo 到 Turborepo,这 3 个坑我帮你踩完了
前端
星栈3 小时前
Dioxus 多页面怎么做:`dioxus-router`、嵌套路由、`Outlet` 和页面组织,一篇给你讲顺
前端·rust·前端框架
用户987409238873 小时前
用 Remotion + edge-tts 打造中文教学视频全自动流水线
前端
风骏时光牛马3 小时前
Less前端工程化实战:变量混合器与项目样式分层落地
前端
假如让我当三天老蒯3 小时前
Options API(选项式 API) 和 Composition API(组合式 API)
前端·vue.js·面试
SameX3 小时前
iOS 独立开发实践:用 MapKit + 像素渲染实现 Citywalk 轨迹地图 App「雁过留痕」
前端
skyey3 小时前
页面加载时,深色模式闪白的问题解决
前端
IT_陈寒4 小时前
Java 并行流把我坑惨了,这6小时加班值了
前端·人工智能·后端
anOnion13 小时前
构建无障碍组件之Menu Button pattern
前端·html·交互设计