Electron 理解
Electron 的架构、进程模型和常用 API
问题
尽可能多的说出你对 Electron 的理解。
解答
什么是 Electron
Electron 是一个使用 Web 技术(HTML、CSS、JavaScript)构建跨平台桌面应用的框架。它将 Chromium 和 Node.js 整合到一个运行时中,让 Web 开发者可以开发 Windows、macOS、Linux 桌面应用。
进程模型
Electron 采用多进程架构,分为主进程和渲染进程:
┌─────────────────────────────────────────┐
│ Main Process │
│ (Node.js 环境,管理应用生命周期) │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ BrowserWindow│ │ BrowserWindow│ │
│ └──────┬──────┘ └──────┬──────┘ │
└─────────┼────────────────┼──────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ Renderer Process│ │ Renderer Process│
│ (Chromium 渲染) │ │ (Chromium 渲染) │
└─────────────────┘ └─────────────────┘
主进程(Main Process):
- 每个应用只有一个主进程
- 运行在 Node.js 环境,可以使用所有 Node.js API
- 负责创建和管理窗口(BrowserWindow)
- 处理系统级操作:菜单、托盘、快捷键等
渲染进程(Renderer Process):
- 每个窗口对应一个渲染进程
- 运行在 Chromium 环境,负责渲染页面
- 默认情况下无法直接访问 Node.js API(出于安全考虑)
基本项目结构
// main.js - 主进程入口
const { app, BrowserWindow } = require('electron')
const path = require('path')
function createWindow() {
// 创建浏览器窗口
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// 预加载脚本,在渲染进程中运行但可访问 Node.js API
preload: path.join(__dirname, 'preload.js'),
// 出于安全考虑,建议关闭 nodeIntegration
nodeIntegration: false,
// 启用上下文隔离
contextIsolation: true
}
})
// 加载页面
win.loadFile('index.html')
}
// 应用就绪后创建窗口
app.whenReady().then(createWindow)
// 所有窗口关闭时退出应用(macOS 除外)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
进程间通信(IPC)
主进程和渲染进程之间通过 IPC 通信:
// preload.js - 预加载脚本
const { contextBridge, ipcRenderer } = require('electron')
// 通过 contextBridge 安全地暴露 API 给渲染进程
contextBridge.exposeInMainWorld('electronAPI', {
// 渲染进程 -> 主进程(单向)
sendMessage: (message) => ipcRenderer.send('message', message),
// 渲染进程 -> 主进程 -> 渲染进程(双向)
invoke: (channel, data) => ipcRenderer.invoke(channel, data),
// 监听主进程消息
onUpdate: (callback) => ipcRenderer.on('update', (event, value) => callback(value))
})
// main.js - 主进程处理 IPC
const { ipcMain } = require('electron')
// 处理单向消息
ipcMain.on('message', (event, message) => {
console.log('收到消息:', message)
})
// 处理双向调用
ipcMain.handle('invoke', async (event, data) => {
// 处理请求并返回结果
return { success: true, data: '处理结果' }
})
// 主进程向渲染进程发送消息
win.webContents.send('update', { version: '1.0.0' })
// renderer.js - 渲染进程使用
// 发送消息
window.electronAPI.sendMessage('Hello from renderer')
// 调用并等待结果
const result = await window.electronAPI.invoke('invoke', { id: 1 })
// 监听主进程消息
window.electronAPI.onUpdate((data) => {
console.log('收到更新:', data)
})
常用模块
const {
app, // 控制应用生命周期
BrowserWindow, // 创建和管理窗口
Menu, // 创建原生菜单
Tray, // 系统托盘
dialog, // 原生对话框(打开文件、保存文件等)
globalShortcut,// 全局快捷键
clipboard, // 剪贴板
shell, // 使用默认程序打开文件/URL
nativeImage, // 处理图片
Notification, // 系统通知
screen, // 获取屏幕信息
powerMonitor, // 监控电源状态
autoUpdater // 自动更新
} = require('electron')
打包与分发
常用打包工具:
// package.json
{
"scripts": {
"build": "electron-builder"
},
"build": {
"appId": "com.example.app",
"mac": {
"target": "dmg"
},
"win": {
"target": "nsis"
},
"linux": {
"target": "AppImage"
}
}
}
优缺点
优点:
- 跨平台:一套代码运行在 Windows、macOS、Linux
- 开发效率高:使用熟悉的 Web 技术栈
- 生态丰富:可使用 npm 生态和 Node.js 能力
- 功能完整:可访问系统 API,实现原生应用功能
缺点:
- 包体积大:内置 Chromium,最小约 50MB+
- 内存占用高:每个窗口都是独立进程
- 性能不如原生:复杂场景可能有性能瓶颈
- 安全性需注意:需要正确配置防止 XSS 等攻击
知名应用
VS Code、Slack、Discord、Notion、Figma Desktop、Postman 等都使用 Electron 构建。
关键点
- 双进程架构:主进程管理应用和窗口,渲染进程负责页面渲染,通过 IPC 通信
- 安全实践:使用 preload + contextBridge,关闭 nodeIntegration,启用 contextIsolation
- 技术栈:Chromium(渲染)+ Node.js(系统能力)+ Web 技术(开发)
- 适用场景:对包体积不敏感、需要快速开发跨平台桌面应用的项目
- 性能权衡:开发效率高但资源占用大,需根据项目需求选择
目录