Electron 完整教程:从零开始构建跨平台桌面应用
什么是 Electron?
Electron 是一个使用 Web 技术(HTML, CSS, JavaScript)来构建跨平台桌面应用的开源框架。

它由 GitHub 开发并维护,著名的应用如 Visual Studio Code、Slack、Discord、Figma、Postman 等都是基于 Electron 构建的。
核心思想: Electron 将 Chromium(Google Chrome 的内核)和 Node.js 打包在一起,你写的代码运行在一个独立的、可定制的“浏览器窗口”中,同时这个窗口又拥有完整的 Node.js API,可以访问操作系统资源(如文件系统、网络、原生通知等)。
架构: Electron 应用由两个主要进程组成:
-
主进程:
(图片来源网络,侵删)- 这是应用的入口点,运行着
package.json中main字段指定的脚本。 - 负责创建和管理应用窗口。
- 管理应用的生命周期(打开、关闭、最小化等)。
- 是唯一可以与原生操作系统 API 直接交互的进程。
- 可以使用 Node.js 模块。
- 这是应用的入口点,运行着
-
渲染进程:
- 每个应用窗口都有一个对应的渲染进程。
- 负责渲染用户界面,也就是你的 HTML, CSS, JavaScript 代码。
- 本质上就是一个独立的 Chrome 浏览器实例。
- 默认情况下,出于安全考虑,渲染进程不能直接使用 Node.js 模块。
-
预加载脚本:
- 这是一个在渲染进程加载之前就加载的脚本,运行在渲染进程的上下文中。
- 它是连接主进程和渲染进程的安全桥梁,你可以在这里暴露一些主进程的 API 给渲染进程使用,而不会破坏 Electron 的安全模型。
开发环境准备
在开始之前,确保你的电脑上安装了以下工具:
-
Node.js 和 npm:
(图片来源网络,侵删)- 访问 Node.js 官网 下载并安装 LTS(长期支持)版本。
- 安装完成后,打开终端(命令提示符或 PowerShell)运行以下命令,确认安装成功:
node -v npm -v
-
代码编辑器:
- 强烈推荐 Visual Studio Code,它本身就是用 Electron 构建的,对 Electron 开发支持非常好。
第一个 Electron 应用:Hello World
让我们一步步创建一个最简单的 Electron 应用。
步骤 1:初始化项目
-
创建一个新的项目文件夹,并进入该文件夹。
mkdir my-electron-app cd my-electron-app
-
初始化 npm 项目。
-y参数会接受所有默认设置。npm init -y
-
安装 Electron。
# 安装为开发依赖 npm install electron --save-dev
步骤 2:创建核心文件
在你的项目根目录下,创建以下三个文件:
package.json(已由npm init创建,稍作修改)main.js(主进程入口文件)index.html(渲染进程的界面)
package.json
修改 main 字段,指向我们的主进程文件 main.js。
{
"name": "my-electron-app",
"version": "1.0.0",
"description": "My first Electron app",
"main": "main.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^latest-version" // 这里的版本号会是你安装的版本
}
}
index.html
一个简单的 HTML 页面。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">Hello World!</title>
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #f0f0f0;
}
h1 {
color: #333;
}
</style>
</head>
<body>
<h1>Hello World from Electron!</h1>
<p>This is my first Electron application.</p>
</body>
</html>
main.js
这是 Electron 应用的核心,负责创建和管理窗口。
// 引入 Electron 模块
const { app, BrowserWindow } = require('electron');
// 定义一个函数来创建主窗口
function createWindow() {
// 创建一个浏览器窗口
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// 预加载脚本,稍后会用到
preload: path.join(__dirname, 'preload.js')
}
});
// 加载应用的 index.html
mainWindow.loadFile('index.html');
// (可选)打开开发者工具,方便调试
// mainWindow.webContents.openDevTools();
}
// Electron 会在初始化完成并准备好创建浏览器窗口时调用这个函数
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(createWindow);
// 当所有窗口都关闭时退出应用
app.on('window-all-closed', () => {
// 在 macOS 上,通常应用和它们的菜单栏会保持活跃
// 直到用户使用 Cmd + Q 明确退出
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// 在 macOS 上,当点击 dock 图标并且没有其他窗口打开时
// 通常会重新创建一个窗口
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
注意:上面的 main.js 使用了 path 模块,所以需要在文件顶部引入它:
const path = require('path');
const { app, BrowserWindow } = require('electron');
步骤 3:运行应用
回到你的终端,运行 npm start 命令:
npm start
如果一切顺利,你将看到一个包含 "Hello World from Electron!" 文本的窗口,恭喜你,你已经成功运行了第一个 Electron 应用!
进阶:进程间通信
我们来实现一个常见的需求:点击 HTML 按钮,让主进程执行一个操作(比如选择文件)。
这需要用到预加载脚本。
步骤 1:创建 preload.js
在项目根目录创建 preload.js 文件。
// 在预加载脚本中,我们可以使用 Electron 的 contextBridge 模块
// 安全地将一些 API 从主进程暴露给渲染进程
const { contextBridge, ipcRenderer } = require('electron');
// 将 ipcRenderer 暴露给渲染进程的全局 window 对象
contextBridge.exposeInMainWorld('electronAPI', {
// 暴露一个选择文件的函数
selectFile: () => ipcRenderer.send('dialog:openFile')
});
步骤 2:修改 main.js
更新主进程,让它监听来自渲染进程的消息,并执行操作。
const path = require('path');
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// 指定预加载脚本
preload: path.join(__dirname, 'preload.js')
}
});
mainWindow.loadFile('index.html');
}
app.whenReady().then(createWindow);
// 监听来自渲染进程的 'dialog:openFile' 事件
ipcMain.on('dialog:openFile', async (event) => {
const result = await dialog.showOpenDialog({
properties: ['openFile', 'multiSelections'],
filters: [
{ name: 'Images', extensions: ['jpg', 'png', 'gif'] }
]
});
// 如果用户选择了文件,将文件路径发回给渲染进程
if (!result.canceled) {
event.sender.send('dialog:fileSelected', result.filePaths);
}
});
// ... (app.on('window-all-closed') 和 app.on('activate') 代码保持不变)
步骤 3:修改 index.html
更新 HTML,添加一个按钮,并添加 JavaScript 来处理点击事件和接收主进程的响应。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">IPC Demo</title>
<style>
body { font-family: sans-serif; display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; }
button { padding: 10px 20px; font-size: 16px; cursor: pointer; }
#file-info { margin-top: 20px; word-break: break-all; }
</style>
</head>
<body>
<h1>进程间通信演示</h1>
<button id="select-file-btn">选择文件</button>
<div id="file-info"></div>
<script>
const selectFileBtn = document.getElementById('select-file-btn');
const fileInfoDiv = document.getElementById('file-info');
// 监听按钮点击事件
selectFileBtn.addEventListener('click, () => {
// 调用在 preload.js 中暴露的 electronAPI.selectFile
window.electronAPI.selectFile();
});
// 监听来自主进程的 'dialog:fileSelected' 事件
// 注意:这里使用 window.addEventListener 是因为主进程使用 event.sender.send 发送消息
window.addEventListener('dialog:fileSelected', (event) => {
const filePaths = event.detail;
fileInfoDiv.innerHTML = `你选择了文件:<br>${filePaths.join('<br>')}`;
});
</script>
</body>
</html>
再次运行 npm start,现在你可以点击按钮,系统会弹出文件选择对话框,选择文件后,文件路径会显示在页面上。
打包应用
开发完成后,你需要将应用打包成可执行文件,以便在没有安装 Node.js 的电脑上运行。
推荐工具:Electron Forge 或 Electron Builder
这里以 Electron Forge 为例,它集成了创建、打包、发布等功能,非常方便。
步骤 1:安装 Electron Forge
# 安装 Electron Forge npm install electron-forge --save-dev # 初始化 Electron Forge,它会自动检测你的项目并配置好 npx electron-forge import
步骤 2:配置 package.json
electron-forge import 会修改你的 package.json,添加 make 脚本。
{
// ... 其他配置
"config": {
"forge": {
"packagerConfig": {},
"makers": [
{
"name": "@electron-forge/maker-squirrel",
"platforms": ["win32"]
},
{
"name": "@electron-forge/maker-zip",
"platforms": ["darwin"]
},
{
"name": "@electron-forge/maker-deb",
"platforms": ["linux"]
}
]
}
},
"scripts": {
"start": "electron .",
"package": "electron-forge package",
"make": "electron-forge make", // 打包命令
// ... 其他脚本
}
}
步骤 3:执行打包
运行 make 命令:
npm run make
打包过程可能需要几分钟,完成后,在你的项目根目录下会生成一个 out 文件夹。
out 文件夹结构:
out/
├── make/
│ ├── win32/ // Windows 平台的可执行文件和安装包
│ ├── darwin/ // macOS 平台的 .app 应用包
│ └── linux/ // Linux 平台的 .deb 安装包
└── ...
你可以将 make/win32 目录下的内容分享给 Windows 用户,他们就可以直接运行你的应用了。
学习资源与最佳实践
官方资源:
- Electron 官方文档: 最权威、最全面的资料。
- Electron API 文档: 查找所有 API 的详细用法。
社区与教程:
- Electron 官方示例: 包含了各种 API 的使用示例,是学习的宝库。
- Build a Desktop App with Electron (freeCodeCamp): 一篇非常受欢迎的英文教程。
最佳实践:
- 架构清晰:严格区分主进程和渲染进程的职责,主进程只负责管理窗口和系统交互,UI 和业务逻辑尽量放在渲染进程中。
- 安全第一:
- 始终使用
contextBridge和preload脚本来暴露 API,不要在渲染进程中直接引入 Node.js 模块 (require('fs'))。 - 对所有来自渲染进程的数据进行验证和清理,防止 XSS 攻击。
- 始终使用
- 性能优化:
- 避免渲染进程阻塞:长时间运行的任务(如文件读写、网络请求)应该放在主进程中执行,或者使用 Worker 线程。
- 按需加载:如果应用功能复杂,可以考虑使用多窗口,只在需要时创建窗口。
- 调试:
- 使用
mainWindow.webContents.openDevTools()打开开发者工具,可以像调试网页一样调试渲染进程。 - 使用
console.log或更专业的调试工具(如 VS Code 的 Debug 功能)来调试主进程。
- 使用
