Electron
用 JavaScript、HTML、CSS 构建跨平台桌面应用的最成熟框架,基于 Chromium + Node.js,VS Code、Slack、Discord 都用它。
🎯 为什么需要它
如果你想用已有的 Web 技术栈(React/Vue/Svelte)开发桌面应用,Electron 是最成熟、生态最完善的选择。它让前端开发者无需学习新语言就能构建原生桌面应用,且跨平台渲染完全一致。
✅ 核心优势
- 极成熟的生态:10 年+ 生产验证,VS Code/Slack/Discord/Notion/Figma 桌面端都基于 Electron
- 渲染一致性:捆绑 Chromium,Windows/macOS/Linux 上表现完全一致,无 WebView 兼容问题
- 全 Node.js 生态:可直接使用 npm 上所有包(better-sqlite3、node-pty、ffi-napi 等原生模块)
- 开发体验极佳:Hot Reload、DevTools、丰富的调试工具,构建速度快(JS 工具链)
- 零语言门槛:纯 JavaScript/TypeScript,无需学习 Rust 或 Swift
- 自动更新成熟:electron-updater 支持 GitHub Releases/S3/自定义服务器,支持增量更新
⚡ 性能表现
| 指标 | Electron | Tauri | 说明 |
|---|---|---|---|
| 安装包 | 100-200MB | 3-10MB | Chromium 体积大 |
| 空闲内存 | 150-300MB | 30-50MB | 每窗口一个 Chromium 实例 |
| 工作内存 | 320-520MB | 85-120MB | 复杂应用差距更大 |
| 冷启动 | 1-3s | 0.3-1s | Chromium 初始化耗时 |
| 构建速度 | 快 | 慢 | JS 工具链 vs Rust 编译 |
| CPU 使用 | 正常 | 正常 | 差距不大 |
适用规模:中小型桌面应用表现良好,超大型应用(数百个窗口)需注意内存管理。
🚀 快速上手
环境准备
- Node.js 18+
- npm / yarn / pnpm
创建项目
# 方式一:手动创建
mkdir my-electron-app && cd my-electron-app
npm init -y
npm install electron --save-dev
# 方式二:使用 Electron Forge(推荐)
npm create electron-app@latest my-app -- --template=webpack-typescript
# 方式三:使用 electron-vite
npm create @quick-start/electron my-app -- --template react-ts
项目结构
my-electron-app/
├── package.json # "main": "main.js"
├── main.js # Main Process(Node.js 后端)
├── preload.js # Preload Script(安全桥接)
├── index.html # Renderer(前端页面)
├── renderer.js # Renderer 逻辑
└── src-tauri/ # (如果用 electron-builder)
└── icon.png
最小可运行示例
package.json:
{
"name": "my-electron-app",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^42.0.0"
}
}
main.js(Main Process):
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const path = require('path');
function createWindow() {
const win = new BrowserWindow({
width: 1024,
height: 768,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // 必须开启
nodeIntegration: false // 必须关闭
}
});
win.loadFile('index.html');
}
// IPC 处理
ipcMain.handle('get-version', () => app.getVersion());
ipcMain.handle('show-dialog', async () => {
const result = await dialog.showMessageBox({
message: 'Hello from Electron!',
type: 'info'
});
return result.response;
});
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
preload.js(安全桥接):
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
getVersion: () => ipcRenderer.invoke('get-version'),
showDialog: () => ipcRenderer.invoke('show-dialog'),
platform: process.platform
});
index.html(Renderer):
<!DOCTYPE html>
<html>
<body>
<h1>My Electron App</h1>
<button id="version">获取版本</button>
<button id="dialog">弹出对话框</button>
<p id="output"></p>
<script>
document.getElementById('version').addEventListener('click', async () => {
const version = await window.electronAPI.getVersion();
document.getElementById('output').textContent = `Electron v${version}`;
});
document.getElementById('dialog').addEventListener('click', async () => {
await window.electronAPI.showDialog();
});
</script>
</body>
</html>
运行
npm start
📦 常用功能速查
窗口管理
const { BrowserWindow, BrowserView } = require('electron');
// 创建窗口
const win = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
title: 'My App',
icon: './icon.png',
frame: false, // 无边框窗口
transparent: true, // 透明窗口
alwaysOnTop: true, // 置顶
fullscreenable: true,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false
}
});
// 加载内容
win.loadFile('index.html');
win.loadURL('https://example.com');
// 窗口操作
win.minimize();
win.maximize();
win.hide();
win.show();
win.focus();
win.setFullScreen(true);
// 无边框窗口拖拽(CSS)
// <div style="-webkit-app-region: drag;">可拖拽区域</div>
应用菜单
const { Menu } = require('electron');
const template = [
{
label: '文件',
submenu: [
{ label: '新建', accelerator: 'CmdOrCtrl+N', click: () => {} },
{ label: '打开', accelerator: 'CmdOrCtrl+O', click: () => {} },
{ type: 'separator' },
{ role: 'quit' }
]
},
{
label: '编辑',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' }
]
},
{
label: '视图',
submenu: [
{ role: 'reload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ role: 'resetZoom' }
]
}
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
系统托盘
const { Tray, Menu, nativeImage } = require('electron');
let tray;
app.whenReady().then(() => {
const icon = nativeImage.createFromPath('./tray-icon.png');
tray = new Tray(icon);
tray.setToolTip('My App');
const contextMenu = Menu.buildFromTemplate([
{ label: '打开主窗口', click: () => mainWindow.show() },
{ type: 'separator' },
{ label: '退出', role: 'quit' }
]);
tray.setContextMenu(contextMenu);
tray.on('click', () => {
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
});
});
文件对话框
const { dialog } = require('electron');
// 打开文件
const result = await dialog.showOpenDialog({
properties: ['openFile', 'multiSelections'],
filters: [
{ name: 'Images', extensions: ['png', 'jpg', 'gif'] },
{ name: 'All Files', extensions: ['*'] }
]
});
if (!result.canceled) {
console.log(result.filePaths);
}
// 保存文件
const saveResult = await dialog.showSaveDialog({
defaultPath: 'document.txt',
filters: [{ name: 'Text', extensions: ['txt'] }]
});
// 消息框
await dialog.showMessageBox({
type: 'info',
title: '提示',
message: '操作完成',
buttons: ['确定']
});
通知
const { Notification } = require('electron');
new Notification({
title: '任务完成',
body: '文件已成功下载',
icon: './icon.png'
}).show();
全局快捷键
const { globalShortcut } = require('electron');
app.whenReady().then(() => {
globalShortcut.register('CommandOrControl+Shift+X', () => {
console.log('快捷键触发');
});
});
app.on('will-quit', () => {
globalShortcut.unregisterAll();
});
自动更新(electron-updater)
const { autoUpdater } = require('electron-updater');
autoUpdater.autoDownload = true;
autoUpdater.autoInstallOnAppQuit = true;
autoUpdater.on('update-available', (info) => {
console.log(`新版本: ${info.version}`);
});
autoUpdater.on('update-downloaded', (info) => {
dialog.showMessageBox({
type: 'info',
title: '更新就绪',
message: `版本 ${info.version} 已下载,重启应用以完成更新`,
buttons: ['立即重启', '稍后']
}).then(({ response }) => {
if (response === 0) autoUpdater.quitAndInstall();
});
});
// 启动时检查更新
app.whenReady().then(() => {
autoUpdater.checkForUpdatesAndNotify();
});
electron-builder 配置(package.json):
{
"build": {
"appId": "com.example.myapp",
"productName": "My App",
"mac": {
"category": "public.app-category.developer-tools",
"target": ["dmg", "zip"]
},
"win": {
"target": ["nsis"]
},
"linux": {
"target": ["AppImage", "deb"]
},
"publish": {
"provider": "github",
"owner": "your-org",
"repo": "your-app"
}
}
}
数据持久化
// 方式一:electron-store(推荐)
const Store = require('electron-store');
const store = new Store();
store.set('settings.theme', 'dark');
store.get('settings.theme'); // 'dark'
// 方式二:SQLite
const Database = require('better-sqlite3');
const db = new Database('app.db');
db.exec('CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, content TEXT)');
原生模块使用
# 安装原生模块(需要编译环境)
npm install better-sqlite3 keytar node-pty
// 在 Main Process 中使用
const Database = require('better-sqlite3');
const db = new Database('my.db');
// 在 Preload 中安全暴露
contextBridge.exposeInMainWorld('dbAPI', {
getNotes: () => ipcRenderer.invoke('get-notes'),
addNote: (content) => ipcRenderer.invoke('add-note', content)
});
📋 关键配置项
BrowserWindow webPreferences
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // 安全隔离(默认 true)
nodeIntegration: false, // 禁用 Node.js(默认 false)
sandbox: true, // 启用沙箱(推荐)
webSecurity: true, // 启用同源策略(默认 true)
allowRunningInsecureContent: false,
experimentalFeatures: false,
webviewTag: false // 禁用 webview 标签(安全)
}
📦 适用场景
适合:
- 已有 Web 前端的团队想快速出桌面应用
- 需要完全一致的跨平台渲染表现
- 重度依赖 Node.js 原生模块(better-sqlite3、node-pty 等)
- IDE/编辑器类应用(VS Code 就是 Electron)
- 团队纯 JS/TS 技术栈,无 Rust/Swift 经验
- 需要成熟的自动更新和分发方案
不适合:
- 对安装包大小极度敏感(>100MB 起步)
- 内存受限环境(低配设备、嵌入式)
- 需要移动端支持(Electron 无移动端)
- 安全敏感应用(攻击面较大,需严格配置)
⚠️ 已知坑 & 注意事项
- 体积大:捆绑 Chromium 导致安装包 100-200MB,多应用共存时每个都带一份 Chromium
- 内存占用高:每个窗口一个 Chromium 进程,开 5 个窗口轻松吃 1GB+ 内存
- 安全配置必须严格:
contextIsolation: true+nodeIntegration: false是底线,否则 XSS 可直接 RCE - 原生模块兼容性:每个 Electron 大版本升级可能导致原生模块(better-sqlite3 等)需要重新编译
- macOS 签名和公证:分发给非开发者需要 Apple 开发者账号(99 EUR/年),否则用户会看到”未验证开发者”警告
- 自动更新边界情况:Windows 需管理员权限、macOS 需签名公证、Linux AppImage 自更新有坑
- CVE 安全漏洞:2026 年 4 月发现 CVE-2026-34779(macOS moveToApplicationsFolder RCE)和 CVE-2026-34765(window.open 隔离绕过),必须及时更新
- BrowserWindow 泄漏:未正确关闭窗口会导致内存泄漏,务必在
window-all-closed事件中清理
🆚 竞品对比
| 维度 | Electron | Tauri | Flutter Desktop | Neutralino |
|---|---|---|---|---|
| 语言 | JS/TS | Rust + JS/TS | Dart | JS/TS |
| 渲染 | Chromium 捆绑 | 系统 WebView | 自绘引擎 | 系统 WebView |
| 安装包 | 100-200MB | 3-10MB | 20-50MB | 1-2MB |
| 内存 | 150-300MB | 30-50MB | 100-200MB | 20MB |
| 渲染一致性 | 完全一致 | 有差异 | 完全一致 | 有差异 |
| 生态 | 极成熟 | 成长期 | 成熟 | 早期 |
| 移动端 | 无 | iOS+Android | iOS+Android | 无 |
| 学习曲线 | 低 | 中(需 Rust) | 中(需 Dart) | 低 |
| 原生模块 | npm 全支持 | 有限 | 有限 | 有限 |
选择建议:
- 已有 Web 团队 + 需要最大兼容性 + 不关心体积 → Electron
- 新项目 + 能接受 Rust + 要小体积 → Tauri
- 已有 Flutter 移动端 → Flutter Desktop
- 极致轻量 + 简单应用 → Neutralino
🌍 生态 & 社区
- 维护状态:极活跃,跟随 Chromium 每 8 周发布大版本,当前最新 v42(Chromium 148, Node v24.15.0)
- 文档质量:优秀,官方文档详尽,教程和示例丰富
- 周边生态:
- electron-builder — 最流行的打包工具
- Electron Forge — 官方推荐的构建工具链
- electron-vite — Vite 集成,启动更快
- electron-store — 简单的持久化存储
- electron-updater — 自动更新
- electron-log — 日志记录
- @electron/fuses — 安全开关配置
- 社区活跃度:115k+ Stars,Discord 社区活跃,StackOverflow 问题丰富
💡 引入评估
| 维度 | 评分(/5) | 备注 |
|---|---|---|
| 上手难度 | ⭐⭐⭐⭐⭐ | 前端开发者零门槛 |
| 文档完善度 | ⭐⭐⭐⭐⭐ | 10 年积累,极其完善 |
| 社区活跃 | ⭐⭐⭐⭐⭐ | 115k Stars,最大桌面框架社区 |
| 性能 | ⭐⭐⭐ | 体积大、内存高是硬伤 |
| 稳定性 | ⭐⭐⭐⭐ | 成熟稳定,但需关注安全更新 |
| 综合 | ⭐⭐⭐⭐ | 成熟可靠,但有性能代价 |
结论:推荐使用 — Electron 是 Web 技术栈构建桌面应用的最成熟选择。如果你的团队是纯 JS/TS 技术栈,且对应用体积和内存不是极度敏感,Electron 是最安全的选择。如果追求极致性能和小体积,建议评估 Tauri。
推荐引入版本:v42.x(Chromium 148, Node v24.15.0,避免使用 latest)
🔗 相关链接
- JavaScript Node.js Chromium 跨平台开发 桌面应用 Tauri
- 官方文档
- GitHub 仓库
- Releases
- electron-builder
- Electron Forge
- electron-vite
- Discord
📝 个人备注
(留白,供后续补充实际使用心得)