文档
Electron 入门教程:构建生产力工具
一、Electron 是什么?
Electron 将 Chromium 和 Node.js 整合到一个运行时中,让 Web 开发者能构建跨平台桌面应用。知名项目包括 VS Code、Slack、Figma、Notion、Discord 等都基于 Electron。
架构理解
┌─────────────────────────────────┐
│ Main Process │
│ (Node.js, 系统级API, 窗口管理) │
│ main.js │
├─────────────────────────────────┤
│ Renderer Process x N │
│ (Chromium, HTML/CSS/JS, 不能 │
│ 直接访问Node, 需preload桥接) │
└─────────────────────────────────┘
- 主进程:每个应用只有一个,负责管理窗口、系统托盘、菜单等
- 渲染进程:每个窗口一个,运行网页内容,与主进程通过 IPC 通信
二、分步构建一个任务管理器
第一步:项目初始化
npm init -y
npm install electron --save-dev
第二步:主进程(窗口管理 + 系统托盘)
// main.js
const { app, BrowserWindow, Tray, Menu, ipcMain, Notification } = require('electron');
const path = require('path');
let mainWindow, tray;
function createWindow() {
mainWindow = new BrowserWindow({
width: 1000,
height: 700,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
},
titleBarStyle: 'hiddenInset', // macOS 风格
});
mainWindow.loadFile('index.html');
}
// 系统托盘
function createTray() {
tray = new Tray(path.join(__dirname, 'icon.png'));
const contextMenu = Menu.buildFromTemplate([
{ label: '显示窗口', click: () => mainWindow.show() },
{ label: '退出', click: () => app.quit() },
]);
tray.setToolTip('我的任务管理器');
tray.setContextMenu(contextMenu);
}
第三步:数据持久化(主进程)
const fs = require('fs').promises;
const DATA_PATH = path.join(app.getPath('userData'), 'tasks.json');
ipcMain.handle('load-tasks', async () => {
try {
const data = await fs.readFile(DATA_PATH, 'utf-8');
return JSON.parse(data);
} catch {
return []; // 文件不存在时返回空数组
}
});
ipcMain.handle('save-tasks', async (event, tasks) => {
await fs.writeFile(DATA_PATH, JSON.stringify(tasks, null, 2));
return true;
});
第四步:Preload 安全桥
// preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('app', {
loadTasks: () => ipcRenderer.invoke('load-tasks'),
saveTasks: (tasks) => ipcRenderer.invoke('save-tasks', tasks),
onReminder: (callback) => ipcRenderer.on('reminder', callback),
});
第五步:渲染进程 UI
<!-- index.html 核心结构 -->
<div id="app">
<input id="task-input" placeholder="添加新任务..." />
<button id="add-btn">添加</button>
<ul id="task-list"></ul>
</div>
<script src="renderer.js"></script>
第六步:打包分发
使用 Electron Forge:
npm install --save-dev @electron-forge/cli
npx electron-forge import
npm run make # 生成 .exe / .dmg / .deb
三、常见陷阱与最佳实践
- 永远不要禁用
contextIsolation——这是最重要的安全防线 - 大文件操作用 Worker 线程,避免阻塞主进程
- 自动更新使用
electron-updater实现 - 内存泄漏:每个窗口都是独立进程,及时释放关闭窗口的引用
- IPC 通信数据需序列化,不能传递函数或复杂对象引用
四、思考题
- 如何在不关闭窗口的情况下隐藏到系统托盘?
app.getPath('userData')在不同操作系统上分别对应什么目录?- 为什么 Electron 不适合做 CPU 密集型后端服务?