📅 更新时间:2026年5月14日 🎯 适用版本:Electron 28+ 💡 适合人群:桌面应用开发者、Web前端转桌面开发者
1. Electron 简介
1.1 什么是 Electron?
Electron 是一个使用 Web 技术(HTML、CSS、JavaScript)构建跨平台桌面应用的框架。由 GitHub 开发维护,著名的 VS Code、Slack、Notion 等应用都基于 Electron 构建。
1.2 核心优势
| 优势 | 说明 |
|---|---|
| 跨平台 | 一次开发,Windows/macOS/Linux 均可运行 |
| 技术栈统一 | 前端开发者可快速上手 |
| 生态丰富 | 可直接使用 npm 生态中的百万级包 |
| 开发效率高 | 支持热重载,快速迭代 |
| 原生能力 | 可访问文件系统、系统托盘、通知等 |
1.3 架构概览
┌─────────────────────────────────────────────────┐
│ Electron │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ Main Process │◄───────►│ Render Process │ │
│ │ (主进程) │ IPC │ (渲染进程) │ │
│ └───────────────┘ └───────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ Node.js │ │ Chromium │ │
│ │ Runtime │ │ Browser │ │
│ └───────────────┘ └───────────────┘ │
└─────────────────────────────────────────────────┘
2. 核心概念
2.1 主进程 (Main Process)
- 唯一性:每个应用只有一个主进程
- 职责:创建窗口、管理应用生命周期、调用原生 API
- 运行环境:Node.js 环境
2.2 渲染进程 (Renderer Process)
- 多实例:每个窗口对应一个渲染进程
- 职责:负责 UI 渲染、用户交互
- 运行环境:Chromium + 限制版的 Node.js
2.3 预加载脚本 (Preload Script)
- 桥接主进程和渲染进程的安全通道
- 通过
contextBridge暴露安全的 API 给渲染进程
2.4 进程隔离
⚠️ 安全模型:
- 渲染进程默认无法访问 Node.js API
- 渲染进程无法直接访问原生资源
- 通过 preload 脚本和 contextBridge 实现安全通信
3. 快速开始
3.1 环境准备
# Node.js 版本要求 (Electron 28+)
node >= 18.0.0
npm >= 9.0.0
# 验证版本
node -v
npm -v
3.2 项目初始化
方式一:使用脚手架(推荐)
# 创建项目
npm create electron-app@latest my-electron-app
# 进入目录
cd my-electron-app
# 启动开发模式
npm run dev
方式二:手动创建
# 创建项目目录
mkdir my-electron-app && cd my-electron-app
# 初始化 package.json
npm init -y
# 安装 Electron (开发依赖)
npm install electron --save-dev
# 安装 electron-builder (打包工具)
npm install electron-builder --save-dev
3.3 目录结构
my-electron-app/
├── package.json
├── main.js # 主进程入口
├── preload.js # 预加载脚本
├── src/
│ ├── index.html # 渲染进程 HTML
│ ├── index.css # 样式文件
│ └── renderer.js # 渲染进程 JS
└── build/ # 打包资源
3.4 最小化示例
main.js (主进程)
const { app, BrowserWindow } = require('electron');
const path = require('path');
function createWindow() {
const mainWindow = new BrowserWindow({
width: 1200,
height: 800,
title: 'My Electron App',
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true, // 启用上下文隔离
nodeIntegration: false, // 禁用 Node.js 集成
sandbox: true // 启用沙箱
}
});
// 加载页面
mainWindow.loadFile(path.join(__dirname, 'src', 'index.html'));
// 打开开发者工具 (开发模式)
if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.openDevTools();
}
}
// 应用就绪后创建窗口
app.whenReady().then(createWindow);
// 所有窗口关闭时退出应用 (macOS 除外)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
// macOS 点击 Dock 图标时重新创建窗口
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
preload.js (预加载脚本)
const { contextBridge, ipcRenderer } = require('electron');
// 暴露安全的 API 给渲染进程
contextBridge.exposeInMainWorld('electronAPI', {
// 窗口控制
minimizeWindow: () => ipcRenderer.send('window-minimize'),
maximizeWindow: () => ipcRenderer.send('window-maximize'),
closeWindow: () => ipcRenderer.send('window-close'),
// 读取文件
readFile: (filePath) => ipcRenderer.invoke('read-file', filePath),
// 监听事件
onUpdate: (callback) => ipcRenderer.on('update-data', callback)
});
index.html (渲染进程)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Electron App</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<h1>Hello Electron!</h1>
<button id="minimizeBtn">最小化</button>
<button id="maximizeBtn">最大化</button>
<button id="closeBtn">关闭</button>
<script src="renderer.js"></script>
</body>
</html>
renderer.js (渲染进程)
// 通过 preload 暴露的 API 与主进程通信
document.getElementById('minimizeBtn').addEventListener('click', () => {
window.electronAPI.minimizeWindow();
});
document.getElementById('maximizeBtn').addEventListener('click', () => {
window.electronAPI.maximizeWindow();
});
document.getElementById('closeBtn').addEventListener('click', () => {
window.electronAPI.closeWindow();
});
3.5 配置 package.json
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "My Electron Application",
"main": "main.js",
"scripts": {
"start": "electron .",
"dev": "NODE_ENV=development electron .",
"build": "electron-builder",
"build:win": "electron-builder --win",
"build:mac": "electron-builder --mac",
"build:linux": "electron-builder --linux"
},
"build": {
"appId": "com.myapp.electron",
"productName": "MyElectronApp",
"directories": {
"output": "dist"
},
"win": {
"target": ["nsis"],
"icon": "build/icon.ico"
},
"mac": {
"target": ["dmg"],
"icon": "build/icon.icns"
},
"linux": {
"target": ["AppImage"],
"icon": "build/icon.png"
}
}
}
4. 主进程与渲染进程
4.1 生命周期
应用启动 → ready → window-all-closed → quit
↓
window 创建
↓
窗口关闭
↓
activate (macOS)
4.2 app 模块常用 API
const { app } = require('electron');
// 获取应用信息
console.log(app.getPath('userData')); // 用户数据目录
console.log(app.getPath('downloads')); // 下载目录
console.log(app.getName()); // 应用名称
console.log(app.getVersion()); // 应用版本
// 应用事件
app.on('ready', () => { /* 应用就绪 */ });
app.on('window-all-closed', () => { /* 所有窗口关闭 */ });
app.on('activate', () => { /* macOS 激活 */ });
app.on('before-quit', () => { /* 退出前 */ });
// 控制应用
app.quit(); // 退出应用
app.exit(); // 强制退出
app.relaunch(); // 重启应用
4.3 BrowserWindow 常用配置
const mainWindow = new BrowserWindow({
// 尺寸
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
// 位置
x: 100,
y: 100,
center: true, // 居中显示
// 外观
title: 'My App',
backgroundColor: '#ffffff',
opacity: 1,
// 窗口行为
resizable: true, // 可调整大小
movable: true, // 可移动
minimizable: true, // 可最小化
maximizable: true, // 可最大化
closable: true, // 可关闭
// 帧
frame: true, // 显示窗口边框 (false = 无边框窗口)
titleBarStyle: 'hidden', // macOS 隐藏标题栏
// Web 偏好
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
nodeIntegration: false,
sandbox: true
}
});
5. 进程间通信 (IPC)
5.1 IPC 通信模式
┌─────────────┐ invoke ┌─────────────┐
│ Renderer │ ──────────► │ Main │
│ │ sendSync │ │
│ │ ◄────────── │ │
│ │ reply │ │
└─────────────┘ └─────────────┘
┌─────────────┐ send ┌─────────────┐
│ Renderer │ ──────────► │ Main │
│ │ on/listen │ │
└─────────────┘ └─────────────┘
5.2 主进程 → 渲染进程
主进程 (main.js)
const { ipcMain, BrowserWindow } = require('electron');
// 发送消息到指定窗口
mainWindow.webContents.send('update-data', { message: 'Hello from main!' });
// 回复渲染进程的请求
ipcMain.handle('get-app-info', async (event, args) => {
return {
version: app.getVersion(),
platform: process.platform
};
});
渲染进程 (preload.js)
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
// 双向通信 - 发送请求并等待回复
getAppInfo: () => ipcRenderer.invoke('get-app-info'),
// 监听主进程消息
onUpdate: (callback) => {
ipcRenderer.on('update-data', (event, data) => callback(data));
},
// 移除监听器
removeUpdateListener: () => {
ipcRenderer.removeAllListeners('update-data');
}
});
5.3 渲染进程 → 主进程
渲染进程 (renderer.js)
// 调用主进程的方法
const info = await window.electronAPI.getAppInfo();
console.log(info.version, info.platform);
// 发送窗口控制命令
window.electronAPI.minimizeWindow();
主进程 (main.js)
// 处理窗口控制
ipcMain.on('window-minimize', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
win.minimize();
});
ipcMain.on('window-maximize', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
if (win.isMaximized()) {
win.unmaximize();
} else {
win.maximize();
}
});
ipcMain.on('window-close', (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
win.close();
});
6. 窗口管理
6.1 多窗口管理
const { BrowserWindow } = require('electron');
let mainWindow;
let settingsWindow;
// 创建主窗口
function createMainWindow() {
mainWindow = new BrowserWindow({ width: 1200, height: 800 });
mainWindow.loadFile('index.html');
mainWindow.on('closed', () => {
mainWindow = null;
});
}
// 创建子窗口
function createSettingsWindow() {
if (settingsWindow) {
settingsWindow.focus();
return;
}
settingsWindow = new BrowserWindow({
width: 600,
height: 400,
parent: mainWindow, // 模态窗口,阻塞父窗口
modal: true,
resizable: false
});
settingsWindow.loadFile('settings.html');
settingsWindow.on('closed', () => {
settingsWindow = null;
});
}
6.2 无边框窗口
const mainWindow = new BrowserWindow({
frame: false, // 隐藏原生窗口边框
titleBarStyle: 'hidden', // macOS 隐藏标题栏但保留控制按钮
// 交通灯按钮位置 (macOS)
titleBarOverlay: {
color: '#2d2d2d',
symbolColor: '#ffffff',
height: 50
}
});
// 自定义拖拽区域
// 在 HTML 中添加 style="webkit-app-region: drag;"
// 可拖动元素添加 style="webkit-app-region: no-drag;"
6.3 窗口状态管理
// 保存窗口状态
const fs = require('fs');
function saveWindowState() {
const bounds = mainWindow.getBounds();
const isMaximized = mainWindow.isMaximized();
fs.writeFileSync('window-state.json', JSON.stringify({
bounds,
isMaximized
}));
}
// 恢复窗口状态
function restoreWindowState() {
let state = { width: 1200, height: 800, x: undefined, y: undefined };
try {
state = JSON.parse(fs.readFileSync('window-state.json'));
} catch (e) {}
return state;
}
7. 系统集成
7.1 系统托盘
const { Tray, Menu, nativeImage } = require('electron');
const path = require('path');
let tray;
function createTray() {
// 创建托盘图标
const icon = nativeImage.createFromPath(
path.join(__dirname, 'assets', 'tray-icon.png')
);
tray = new Tray(icon);
const contextMenu = Menu.buildFromTemplate([
{ label: '打开主窗口', click: () => mainWindow.show() },
{ label: '设置', click: () => createSettingsWindow() },
{ type: 'separator' },
{ label: '关于', click: () => showAboutDialog() },
{ type: 'separator' },
{ label: '退出', click: () => app.quit() }
]);
tray.setToolTip('My Electron App');
tray.setContextMenu(contextMenu);
// 单击托盘图标显示窗口
tray.on('click', () => {
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
});
}
7.2 系统通知
const { Notification } = require('electron');
function showNotification(title, body) {
if (Notification.isSupported()) {
const notification = new Notification({
title,
body,
icon: path.join(__dirname, 'assets', 'icon.png'),
silent: false
});
notification.on('click', () => {
mainWindow.show();
mainWindow.focus();
});
notification.show();
}
}
7.3 菜单栏
const { Menu } = require('electron');
function createMenu() {
const template = [
{
label: '文件',
submenu: [
{ label: '新建', accelerator: 'CmdOrCtrl+N', click: () => {} },
{ label: '打开', accelerator: 'CmdOrCtrl+O', click: () => openFile() },
{ type: 'separator' },
{ label: '退出', accelerator: 'CmdOrCtrl+Q', click: () => app.quit() }
]
},
{
label: '编辑',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
{ role: 'selectAll' }
]
},
{
label: '视图',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
},
{
label: '帮助',
submenu: [
{ label: '关于', click: () => showAboutDialog() }
]
}
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
}
7.4 拖放文件
// 主进程处理文件拖放
mainWindow.webContents.on('will-navigate', (event) => {
event.preventDefault();
});
// 渲染进程处理拖放
const holder = document.getElementById('drop-zone');
holder.ondragover = (e) => {
e.preventDefault();
e.stopPropagation();
};
holder.ondrop = (e) => {
e.preventDefault();
e.stopPropagation();
const files = [...e.dataTransfer.files];
files.forEach(file => {
console.log('Dropped file:', file.path);
});
};
8. 打包与发布
8.1 electron-builder 配置
{
"appId": "com.gamebox.app",
"productName": "GameBox",
"copyright": "Copyright © 2026",
"directories": {
"output": "release",
"buildResources": "build"
},
"files": [
"main.js",
"preload.js",
"src/**/*",
"assets/**/*"
],
"win": {
"target": [
{
"target": "nsis",
"arch": ["x64"]
},
{
"target": "portable",
"arch": ["x64"]
}
],
"icon": "build/icon.ico",
"artifactName": "${productName}-${version}-${arch}.${ext}"
},
"mac": {
"target": ["dmg", "zip"],
"icon": "build/icon.icns",
"category": "public.app-category.games"
},
"linux": {
"target": ["AppImage", "deb"],
"icon": "build/icon.png",
"category": "Game"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"createStartMenuShortcut": true
}
}
8.2 打包命令
# 开发环境启动
npm run dev
# 构建 Windows 安装包
npm run build:win
# 构建 macOS 应用
npm run build:mac
# 构建 Linux 应用
npm run build:linux
# 构建所有平台
npm run build
8.3 自动更新
const { autoUpdater } = require('electron-updater');
function setupAutoUpdater() {
autoUpdater.autoDownload = false;
autoUpdater.on('update-available', (info) => {
mainWindow.webContents.send('update-available', info);
});
autoUpdater.on('update-downloaded', (info) => {
mainWindow.webContents.send('update-downloaded', info);
});
autoUpdater.on('error', (err) => {
console.error('Update error:', err);
});
// 检查更新
autoUpdater.checkForUpdates();
}
// 安装更新并重启
function installUpdate() {
autoUpdater.quitAndInstall();
}
9. 常见问题与最佳实践
9.1 安全最佳实践
// ✅ 始终启用安全配置
webPreferences: {
contextIsolation: true, // 隔离上下文
nodeIntegration: false, // 禁用 Node 集成
sandbox: true, // 启用沙箱
webSecurity: true, // 启用 Web 安全
allowRunningInsecureContent: false
}
// ❌ 避免的安全问题
webPreferences: {
nodeIntegration: true, // 危险!
contextIsolation: false, // 危险!
enableRemoteModule: true // 已废弃,危险!
}
9.2 性能优化
// 1. 延迟加载窗口
app.whenReady().then(() => {
setTimeout(createWindow, 1000); // 延迟 1 秒
});
// 2. 使用内容安全策略
// 在 index.html 的 <head> 中添加
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'">
// 3. 禁用硬件加速(如果出现渲染问题)
app.disableHardwareAcceleration();
// 4. 使用 webFrame API 优化
const { webFrame } = require('electron');
webFrame.setZoomFactor(1);
webFrame.setVisualZoomLevelLimits(1, 1);
9.3 调试技巧
// 开发模式打开 DevTools
if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.openDevTools();
}
// 主进程调试
console.log('Debug info:', process.argv);
// 渲染进程调试
window.electronAPI.debug && window.electronAPI.debug();
9.4 常见错误处理
// 捕获未处理的异常
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
});
// 捕获未处理的 Promise 拒绝
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection:', reason);
});
// 窗口加载失败处理
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDesc) => {
console.error('Failed to load:', errorCode, errorDesc);
});
// 网络错误处理
mainWindow.webContents.on('did-fail-provisional-load', (event, errorCode) => {
if (errorCode === -10) { // ERR_BLOCKED_BY_CLIENT
console.log('Resource blocked');
}
});
附录:常用 npm 包
| 包名 | 用途 |
|---|---|
electron | Electron 核心 |
electron-builder | 应用打包 |
electron-updater | 自动更新 |
electron-log | 日志记录 |
electron-store | 数据持久化 |
electron-squirrel-startup | Squirrel 安装支持 |
参考资源
💡 提示:本文档会持续更新。如有问题或建议,欢迎在评论区留言!
📧 联系作者:[CSDN 博客地址]
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END














暂无评论内容