Electron 桌面开发:用 Web 技术构建桌面客户端

FreeGuideOnline 最新 2026-06-12

什么是 Electron?

Electron 是一个开源框架,让你可以使用熟悉的 Web 技术——HTML、CSS 和 JavaScript——来构建跨平台的桌面应用程序。它由 GitHub 开发和维护,目前支撑着如 Visual Studio Code、Slack、Discord 和 Figma 等众多知名桌面应用。

Electron 在底层将 Chromium 渲染引擎和 Node.js 运行时组合在一起。你可以把 Electron 应用理解为一个经过定制的、能调用操作系统原生能力的 Chromium 浏览器。前端部分由 Chromium 负责展示 Web 页面,每个页面运行在独立的渲染进程中;后端部分由 Node.js 提供底层系统访问能力(文件系统、网络、系统通知等),这些逻辑运行在主进程里。通过进程间通信 (IPC),主进程和渲染进程可以高效协同工作。

环境准备与第一个 Electron 应用

在开始之前,请确保你的计算机安装了 Node.js(推荐使用最新的 LTS 版本)和一个顺手的代码编辑器(如 VS Code)。

初始化项目

创建一个新文件夹,并在其中初始化 npm 项目:

mkdir my-electron-app
cd my-electron-app
npm init -y

这会生成一个 package.json 文件。接下来安装 Electron 作为开发依赖:

npm install --save-dev electron

编写主进程入口文件

在项目根目录下创建一个 main.js 文件,这是 Electron 应用的入口,它运行在主进程中。输入以下基础代码:

const { app, BrowserWindow } = require('electron');
const path = require('path');

function createWindow () {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: false, // 安全起见,保持关闭
      contextIsolation: true, // 启用上下文隔离
    }
  });

  mainWindow.loadFile('index.html');
}

app.whenReady().then(() => {
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

这段代码做了几件重要的事:

  • 等待应用就绪后,创建一个 800×600 的窗口,并加载 index.html
  • 设置了 nodeIntegration: falsecontextIsolation: true,这遵循了 Electron 的安全最佳实践。
  • 处理了 macOS 下关闭所有窗口不退出应用的行为,以及应用激活时重新创建窗口的逻辑。

创建前端页面与预加载脚本

在同一目录下新建 index.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>我的第一个 Electron 应用</title>
</head>
<body>
  <h1>Hello Electron!</h1>
  <p>当前使用的 Node.js 版本:<span id="node-version"></span></p>
  <p>当前平台:<span id="platform"></span></p>
</body>
</html>

接着创建 preload.js,它会在渲染进程加载网页之前执行,并安全地将主进程提供的 API 暴露给网页:

const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
  getNodeVersion: () => process.versions.node,
  getPlatform: () => process.platform,
  // 你可以在这里通过 ipcRenderer 暴露安全的消息通道
});

现在需要让 main.js 中的 preload 指向这个文件(已经在之前的代码中配置了)。最后修改 index.html,使用暴露的 API 填充数据:

<script>
  document.getElementById('node-version').textContent = window.electronAPI.getNodeVersion();
  document.getElementById('platform').textContent = window.electronAPI.getPlatform();
</script>

配置启动脚本并运行

package.jsonscripts 中添加:

"start": "electron ."

然后运行:

npm start

如果一切正常,你会看到一个显示 Node.js 版本和平台信息的桌面窗口。恭喜,你已经成功运行了第一个 Electron 应用!

理解 Electron 的进程模型与架构

深入掌握 Electron,必须清楚它的多进程架构。

  • 主进程 (Main Process):每个 Electron 应用有且仅有一个主进程。main.js 就是它的入口。主进程负责创建和管理窗口(BrowserWindow),处理应用生命周期、系统托盘、菜单等原生能力,以及同系统底层交互。它拥有完整的 Node.js 环境,可以直接使用 fspath 等模块。
  • 渲染进程 (Renderer Process):每个窗口(BrowserWindow)拥有自己独立的渲染进程。它负责展示 UI,就像普通浏览器标签页一样。出于安全考虑,渲染进程默认不能直接访问 Node.js API(因为 nodeIntegration 默认关闭,且 contextIsolation 默认开启)。
  • 预加载脚本 (Preload Script):运行在渲染进程的上下文中,但拥有比网页更高的权限。在 contextIsolation 开启的情况下,它通过 contextBridge 安全地向网页暴露有限的主进程能力,避免将整个 Node.js 环境泄漏给远程内容。

进程间通信主要使用 ipcMain(主进程)和 ipcRenderer(渲染进程)模块,通过事件的方式传递消息。例如,从渲染进程发送消息给主进程:

preload.js 中暴露:

contextBridge.exposeInMainWorld('electronAPI', {
  sendMessage: (msg) => ipcRenderer.send('to-main', msg)
});

main.js 中监听:

const { ipcMain } = require('electron');
ipcMain.on('to-main', (event, message) => {
  console.log('来自渲染进程的消息:', message);
});

构建丰富的桌面功能

掌握基本结构后,你可以为应用添加大量原生特性。

自定义菜单与系统托盘

Electron 提供了 MenuTray 模块。在主进程中,你可以创建应用菜单:

const { Menu } = require('electron');
const template = [
  { label: '文件', submenu: [{ label: '打开文件' }, { label: '退出', role: 'quit' }] },
  { label: '编辑', submenu: [{ role: 'undo' }, { role: 'redo' }] }
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);

系统托盘常用于后台驻留应用。在主进程中创建托盘图标(需要准备一个小图标文件 icon.png):

const { Tray } = require('electron');
let tray = null;
app.whenReady().then(() => {
  tray = new Tray('path/to/icon.png');
  tray.setToolTip('我的 Electron 应用');
});

对话框与文件系统交互

桌面应用经常需要打开文件、保存文件或弹出消息框。dialog 模块在主进程中工作。你可以通过 IPC 让渲染进程触发对话框,并返回结果。

main.js 中注册 IPC 处理程序:

const { dialog } = require('electron');
ipcMain.handle('open-file-dialog', async () => {
  const { canceled, filePaths } = await dialog.showOpenDialog({
    properties: ['openFile']
  });
  if (!canceled) return filePaths[0];
});

在预加载脚本中暴露:

contextBridge.exposeInMainWorld('electronAPI', {
  openFileDialog: () => ipcRenderer.invoke('open-file-dialog')
});

渲染进程调用 window.electronAPI.openFileDialog() 就可以打开文件选择框,并获得用户选择的文件路径。之后,主进程可以利用 Node.js 的 fs 模块读取文件内容,再通过 IPC 返回给渲染进程。

自动更新与打包分发

将应用打包成可执行文件供用户安装,通常使用 electron-builderelectron-forge。以 electron-builder 为例:

  1. 安装依赖:
    npm install --save-dev electron-builder
    
  2. package.json 中添加构建配置:
    "build": {
      "appId": "com.example.myapp",
      "productName": "MyElectronApp",
      "directories": { "output": "dist" },
      "win": { "target": "nsis" },
      "mac": { "target": "dmg" },
      "linux": { "target": "AppImage" }
    }
    
  3. 添加构建脚本:
    "scripts": {
      "start": "electron .",
      "build": "electron-builder"
    }
    
  4. 运行 npm run build,即可在 dist 文件夹中得到当前平台的安装包。

对于自动更新,Electron 生态中常用 electron-updater(配合 electron-builder)或 Electron 自己的 autoUpdater 模块。它们可以检测新版本、下载并提示用户安装,你需要搭建一个简单的版本服务器来托管安装包文件和最新版本描述信息。

进阶话题与最佳实践

安全第一

永远不要在主进程启用 nodeIntegration: true,也不要同时设置 contextIsolation: false,除非你完全信任加载的本地文件且没有任何远程内容。始终通过预加载脚本和 contextBridge 精确暴露所需功能,遵循最小权限原则。

性能优化

  • 避免阻塞主进程:任何长时间运行的任务(如大量 I/O 或计算)都应该交给 worker_threads 或在渲染进程中使用 Web Workers。
  • 窗口数量控制:渲染进程消耗内存,多个复杂窗口可能导致资源紧张。
  • 使用 <webview>BrowserView:当需要在应用中嵌入不受信任的内容时,使用 <webview> 标签以隔离进程,避免 iframe 带来的风险。

现代前端框架集成

Electron 并不绑定任何前端框架。你可以使用 React、Vue、Svelte 等现代框架构建 UI。常见做法是先用对应框架的脚手架创建项目,然后将 Electron 作为运行时容器。也可以使用 electron-viteelectron-forge 的 Vite 模板等工具快速启动集成项目。

调试与错误收集

  • 开发阶段:可以使用 Chrome DevTools 调试渲染进程(mainWindow.webContents.openDevTools())。
  • 主进程调试:使用 --inspect 参数启动 Electron,在 VS Code 或 Chrome DevTools 中附加调试器。
  • 崩溃报告:Electron 内置了 crashReporter 模块,可以将崩溃报告发送到你的服务器。

总结与学习路径

通过本教程,你已经了解了 Electron 的核心思想、进程模型、基本开发流程以及如何添加菜单、对话框、自动更新等实用功能。下一步建议你尝试:

  1. 阅读官方文档的指南部分(进程间通信、安全、应用打包等)。
  2. 克隆一个 Electron 示例仓库,如 electron/electron-quick-start,自行修改实验。
  3. 探索 Electron 的 API 文档,寻找你需要的原生功能。
  4. 关注社区中优秀的工具和模板(例如 electron-viteelectron-builder),它们能大幅提升开发效率。

Electron 赋予了 Web 开发者前所未有的桌面端交付能力。现在,就用你掌握的 HTML、CSS 和 JavaScript 技能,去构建下一款令人印象深刻的桌面应用吧!