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

相关推荐
谙忆10241 小时前
前端图片直传对象存储:OSS/S3 预签名 URL、STS 临时凭证与回调校验
前端
CHNE_TAO_EMSM2 小时前
Android studio 打开文件时自动下载源码
前端·javascript·android studio
一孤程3 小时前
Airtest自动化测试第五篇:小程序与Web测试——跨平台自动化全覆盖
前端·自动化测试·小程序·自动化·测试·airtest
IT_陈寒3 小时前
SpringBoot自动配置不是你以为的那样的智能
前端·人工智能·后端
yume_sibai4 小时前
大屏数据可视化 - 边框红绿呼吸灯实现详解
前端·信息可视化·typescript
Hyyy4 小时前
很多Desktop都在上的Computer Use是什么
前端·llm
慢功夫4 小时前
开篇:VS Code 为什么不是一个普通 React App
前端·visual studio code
你挚爱的强哥5 小时前
Vue2 实现 1.5s 十连击监听(连续点击若干次),封装通用可复用点击检测工具,不用 data!Vue 封装通用连击监听方法,支持自定义时长与点击次数
前端·javascript·vue.js
huashengzsj5 小时前
Shopify个人建站如何搭建独立站:从零开始的完整指南
前端·网络·人工智能
程序猿小泓5 小时前
从 Claude Code 学 Agent Harness:一个前端工程师的 AI Agent 学习笔记
前端·人工智能·学习