MD 分类:桌面与跨平台UI 更新:2026/5/12

📦 实战评估:Project Toolkit/桌面与跨平台UI/Electron

Electron 架构设计

Electron 是基于 Chromium + Node.js 的跨平台桌面应用框架,用 Web 技术(HTML/CSS/JS)构建原生桌面应用。

🏗️ 整体架构

┌─────────────────────────────────────────────────────┐
│                  Electron 应用                        │
│                                                      │
│  ┌────────────────────────────────────────────────┐  │
│  │              Main Process (Node.js)             │  │
│  │                                                 │  │
│  │  ┌──────────┐ ┌──────────┐ ┌───────────────┐   │  │
│  │  │   app    │ │ Browser  │ │   ipcMain     │   │  │
│  │  │ 生命周期  │ │ Window   │ │  消息处理      │   │  │
│  │  │          │ │ 窗口管理  │ │               │   │  │
│  │  └──────────┘ └──────────┘ └───────┬───────┘   │  │
│  │                                    │            │  │
│  └────────────────────────────────────┼────────────┘  │
│                                       │               │
│                    ┌──────────────────┼────────┐      │
│                    │    Preload Script│        │      │
│                    │  contextBridge   │        │      │
│                    │  (安全桥接层)      │        │      │
│                    └────────┬─────────┘        │      │
│                             │                   │      │
│  ┌──────────────────────────▼───────────────────┐     │
│  │           Renderer Process (Chromium)         │     │
│  │                                               │     │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────────────┐ │     │
│  │  │  HTML   │ │  CSS    │ │   JavaScript    │ │     │
│  │  │  DOM    │ │ Styles  │ │   Web APIs      │ │     │
│  │  └─────────┘ └─────────┘ └─────────────────┘ │     │
│  │                                               │     │
│  └───────────────────────────────────────────────┘     │
│                                                        │
└────────────────────────────────────────────────────────┘

🔑 核心设计思想

1. 继承 Chromium 的多进程模型

Electron 直接继承了 Chrome 浏览器的多进程架构:

进程类型对应 Chrome职责
Main ProcessBrowser Process管理窗口、生命周期、系统 API
Renderer ProcessRenderer Process渲染网页、处理用户交互
Utility ProcessUtility Process运行独立任务(Node.js 子进程)

设计哲学:每个窗口一个独立进程,一个窗口崩溃不影响其他窗口。这直接复用了 Chromium 成熟的进程隔离方案。

代价:每个窗口都运行一个完整的 Chromium 实例,内存开销大。

2. Node.js + Chromium 双引擎捆绑

每个 Electron 应用 = Chromium(渲染引擎)+ Node.js(后端运行时)
组件作用为什么捆绑
Chromium渲染 HTML/CSS/JS,提供 Web API保证跨平台渲染完全一致
Node.js文件系统、网络、子进程等系统 API让前端能调用后端能力
V8JavaScript 引擎Chromium 和 Node.js 共享

权衡:应用体积 100-200MB(每个应用都带一份 Chromium),但换来的是渲染一致性 — 同一应用在 Windows/macOS/Linux 上看起来完全一样。

3. 三层进程安全模型

信任级别:  高 ──────────────────────────────────── 低

Main Process          Preload Script          Renderer Process
(Node.js)             (Isolated World)        (Chromium 沙箱)
完全信任               部分信任                 不信任
可访问所有              contextBridge           只能通过暴露的
系统 API               安全暴露 API             API 通信

安全边界

  • Main Process:完全信任,可访问所有系统资源
  • Preload Script:可访问 Node.js API,但通过 contextBridge 选择性暴露给 Renderer
  • Renderer Process:运行不可信的 Web 代码,无 Node.js 访问权限

4. IPC 消息传递模型

Main Process 和 Renderer Process 不能直接通信,必须通过 IPC(Inter-Process Communication):

Renderer Process                    Main Process
     │                                  │
     │  ipcRenderer.invoke('channel')   │
     │ ───────────────────────────────> │
     │                                  │  ipcMain.handle('channel')
     │                                  │  执行操作
     │  Promise<result>                 │
     │ <─────────────────────────────── │
     │                                  │
     │  ipcRenderer.send('channel')     │
     │ ───────────────────────────────> │  (单向,无返回值)
     │                                  │
     │  webContents.send('channel')     │
     │ <─────────────────────────────── │  (Main → Renderer)

🧩 核心组件

Main Process 模块

模块作用
app应用生命周期(ready/quit/activate 等事件)
BrowserWindow创建和管理应用窗口
ipcMain处理来自 Renderer 的 IPC 消息
Menu原生应用菜单和上下文菜单
Tray系统托盘图标
dialog原生文件选择/消息对话框
Notification系统通知
shell用默认应用打开 URL 或文件
globalShortcut注册全局快捷键
powerMonitor监听电源状态变化
screen获取屏幕信息
session管理 Cookie、缓存、代理
webContents控制 WebView 内容(加载 URL、执行 JS)

Renderer Process 模块

模块作用
ipcRenderer向 Main Process 发送 IPC 消息
webFrame控制当前网页的渲染行为
contextBridge安全地将 API 从 Preload 暴露到 Renderer
desktopCapturer捕获屏幕/窗口内容(屏幕共享)
Web APIs完整的 Chromium Web API(DOM、Fetch、WebGL 等)

Preload Script

Preload 是连接 Main 和 Renderer 的安全桥梁:

// preload.js
const { contextBridge, ipcRenderer } = require('electron');

// 暴露安全的 API 给 Renderer
contextBridge.exposeInMainWorld('electronAPI', {
  // 方法一:invoke(请求-响应)
  getVersion: () => ipcRenderer.invoke('get-version'),

  // 方法二:send + on(事件)
  onUpdateReady: (callback) => {
    ipcRenderer.on('update-ready', (_event, data) => callback(data));
  },

  // 方法三:暴露只读数据
  platform: process.platform,
  isDev: !app.isPackaged
});

关键安全规则

  • 永远不要暴露 ipcRenderer 本身给 Renderer
  • 永远不要暴露 requirefschild_process 等原始 API
  • 只暴露最小必要的功能

🔄 IPC 通信详解

invoke / handle(推荐,请求-响应)

// Main Process
const { ipcMain } = require('electron');

ipcMain.handle('read-file', async (_event, filePath) => {
  const content = await fs.promises.readFile(filePath, 'utf-8');
  return content;
});

// Renderer Process (通过 Preload 暴露)
const content = await window.electronAPI.readFile('/path/to/file');

send / on(单向,Renderer → Main)

// Main Process
ipcMain.on('open-settings', (_event) => {
  createSettingsWindow();
});

// Renderer Process
window.electronAPI.openSettings();

webContents.send(单向,Main → Renderer)

// Main Process
mainWindow.webContents.send('download-progress', { percent: 75 });

// Renderer Process (通过 Preload 监听)
window.electronAPI.onDownloadProgress((data) => {
  progressBar.style.width = `${data.percent}%`;
});

📐 进程模型详解

窗口进程隔离

┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│   Main Process  │  │  Renderer #1    │  │  Renderer #2    │
│   (1个,共享)    │  │  (窗口A)        │  │  (窗口B)         │
│                 │  │  独立进程        │  │  独立进程        │
│  app            │  │  HTML/CSS/JS    │  │  HTML/CSS/JS    │
│  BrowserWindow  │  │  Preload        │  │  Preload        │
│  ipcMain        │  │  ipcRenderer    │  │  ipcRenderer    │
└─────────────────┘  └─────────────────┘  └─────────────────┘
  • Main Process 始终只有 1 个
  • 每个 BrowserWindow 有独立的 Renderer Process
  • 窗口间通信必须经过 Main Process 中转

Utility Process

Electron v24+ 引入的 Node.js 子进程,用于 CPU 密集型任务:

const { utilityProcess } = require('electron');

const child = utilityProcess.fork('worker.js');
child.postMessage({ task: 'heavy-computation' });
child.on('message', (result) => {
  console.log('Result:', result);
});

🛡️ 安全架构

安全最佳实践(20 条规则)

#规则原因
1只加载 HTTPS 内容防止中间人攻击
2启用 contextIsolation: true隔离 Preload 和 Renderer
3禁用 nodeIntegration: true防止 Renderer 访问 Node.js
4设置 CSP限制资源加载来源
5使用 Preload + contextBridge安全暴露 API
6验证所有 IPC sender防止伪造消息
7不要暴露 ipcRenderer 原始对象防止任意 IPC 调用
8使用 setWindowOpenHandler控制新窗口行为
9禁用 remote 模块已弃用,不安全
10验证 webview 标签防止嵌入恶意内容

Context Isolation(上下文隔离)

┌──────────────────────────────────────────┐
│           Renderer Process               │
│                                          │
│  ┌────────────────┐  ┌────────────────┐  │
│  │  Main World    │  │  Isolated World│  │
│  │  (网页代码)    │  │  (Preload)     │  │
│  │                │  │                │  │
│  │  window.electronAPI  ← contextBridge  │
│  │  (只能调用暴露的API)  (可访问Node.js)│  │
│  │                │  │                │  │
│  │  ✗ require     │  │  ✓ require     │  │
│  │  ✗ fs          │  │  ✓ fs          │  │
│  │  ✗ child_process│  │  ✓ child_process│ │
│  └────────────────┘  └────────────────┘  │
└──────────────────────────────────────────┘

🔧 打包与分发

electron-builder vs Electron Forge

工具特点适用场景
electron-builder成熟稳定,功能丰富,支持自动更新生产级应用,需要自动更新
Electron Forge官方推荐,集成 Webpack/Vite新项目,标准化流程

支持的打包格式

平台格式
macOS.dmg, .pkg, .app(MAS)
Windows.exe(NSIS), .msi
Linux.AppImage, .deb, .rpm, .snap

自动更新机制

┌──────────┐     ┌──────────────┐     ┌──────────┐
│ 用户设备 │     │ 更新服务器    │     │ 发布渠道  │
│          │     │ (GitHub/S3)  │     │          │
│ 启动应用 │ ──> │ 检查版本     │ <── │ 推送新版本│
│          │     │              │     │          │
│ 下载更新 │ <── │ 返回更新信息 │     │          │
│          │     │              │     │          │
│ 重启应用 │     │              │     │          │
└──────────┘     └──────────────┘     └──────────┘

🆚 与 Tauri 架构对比

维度ElectronTauri
渲染引擎捆绑 Chromium系统 WebView
后端语言Node.js (JS)Rust
进程模型Main + Renderer + UtilityCore + WebView
IPCipcMain/ipcRendererinvoke() + Events
安全模型需手动配置(默认开放)Capability-based(默认安全)
二进制体积100-200MB3-10MB
内存占用150-300MB30-50MB
渲染一致性完全一致(同一 Chromium)跨平台有差异
构建速度快(JS 工具链)慢(Rust 编译)
移动端iOS + Android
生态成熟度极成熟(10 年+)成长期
学习曲线低(纯 JS/TS)中(需 Rust)

🔗 相关链接

📝 个人备注

(留白,供后续补充学习心得)