作为前端开发者,你是否曾想过将自己的网页项目改造成桌面应用?是否羡慕那些能在 Windows、macOS、Linux 上无缝运行的工具软件?今天,我要给大家介绍的 Electron 框架,就能帮你实现这个愿望------用 HTML、CSS、JavaScript 这些前端技术栈,轻松打造跨平台桌面应用。
VS Code、Figma、Slack 这些知名软件,都是基于 Electron 开发的。是不是瞬间觉得这个框架很有吸引力?接下来,我会从环境搭建到打包发布,带你走完 Electron 开发的完整流程,最后还会分享实战中的优化技巧和踩坑经验。
一、先搞懂这3个核心概念,避免后续踩坑
在动手开发前,先理清 Electron 的核心架构,不然写代码时很容易混淆进程职责,出现"主进程调不了 DOM,渲染进程用不了系统 API"的问题。
1. 主进程(Main Process)
整个应用的"大脑",负责统筹全局: - 管理窗口的创建、关闭、最大化等操作; - 调用系统原生 API(比如文件读写、系统对话框); - 控制应用的生命周期(启动、退出)。 每个应用只有一个主进程,对应我们项目中的 main.js 文件。
2. 渲染进程(Renderer Process)
每个窗口对应一个渲染进程,相当于"显示器": - 负责 UI 渲染,和普通网页一样用 HTML/CSS/JS 开发; - 基于 Chromium 内核,支持所有前端技术(Vue/React 都能上); - 不能直接调用系统 API,需要通过 IPC 向主进程"求助"。 对应项目中的 index.html 及相关脚本。
3. IPC 通信(Inter-Process Communication)
主进程和渲染进程之间的"对讲机",用于传递数据和指令。比如渲染进程要读取本地文件,就通过 IPC 告诉主进程,主进程执行后再把结果返回给渲染进程。
记住这个核心原则:系统级操作找主进程,UI 相关操作找渲染进程
二、环境搭建:3分钟搞定前置依赖
Electron 依赖 Node.js,整个环境搭建非常简单,新手也能快速上手。
1. 安装必要工具
- Node.js :推荐 LTS 版本(v16+ 稳定,本文用 v20 演示),自带 npm 包管理器。 下载地址:Node.js 官网 验证安装:打开终端输入
node -v和npm -v,能显示版本号就没问题。 - 代码编辑器:首推 VS Code,再装两个插件提升效率: - Electron:语法提示、代码补全; - Electron Debugger:调试主进程。
- 系统依赖(可选) : - Windows:无需额外操作,确保 PowerShell 能用; - macOS:执行
xcode-select --install安装命令行工具; - Linux(Ubuntu):执行sudo apt-get install libx11-dev libxkbfile-dev安装依赖。
2. 配置镜像(解决安装慢问题)
Electron 安装包在国外,直接装可能卡住,先配置国内镜像:
arduino
# npm 配置镜像
npm config set electron_mirror https://npmmirror.com/mirrors/electron/
# yarn 配置(如果用 yarn)
yarn config set electron_mirror https://npmmirror.com/mirrors/electron/
三、项目初始化:5步创建第一个 Electron 应用
我们从空文件夹开始,一步步搭建一个能运行的基础项目。
1. 创建项目目录并初始化
bash
# 1. 创建文件夹并进入
mkdir electron-demo && cd electron-demo
# 2. 初始化 npm 项目(一路回车,后续可修改 package.json)
npm init -y
执行完后,文件夹里会多出一个 package.json 文件,这是项目的配置核心。
2. 安装 Electron
把 Electron 装为开发依赖(避免打包时冗余):
csharp
# npm 安装
npm install electron --save-dev
# 或 yarn 安装
yarn add electron --dev
3. 配置 package.json
修改 package.json 的关键配置,指定入口文件和启动脚本:
json
{
"name": "electron-demo",
"version": "1.0.0",
"description": "Electron 新手实战项目",
"main": "main.js", // 主进程入口文件
"scripts": {
"start": "electron .", // 启动应用的命令
"pack": "electron-builder --dir", // 打包测试版
"build": "electron-builder" // 打包正式版
},
"author": "你的名字",
"license": "MIT",
"devDependencies": {
"electron": "^28.0.0",
"electron-builder": "^24.9.1" // 打包工具,先提前装
},
"build": { // 打包配置,后续详细讲
"appId": "com.youname.electrondemo",
"productName": "ElectronDemo",
"output": "dist"
}
}
4. 编写核心代码
现在创建三个核心文件,实现"主进程创建窗口 + 渲染进程显示界面 + 进程间通信"的基础功能。
① 主进程:main.js
负责创建窗口、处理 IPC 通信和系统事件:
javascript
// 引入 Electron 核心模块
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
let mainWindow; // 保存窗口引用,避免被垃圾回收
// 创建主窗口的函数
function createWindow() {
mainWindow = new BrowserWindow({
width: 800, // 窗口宽度
height: 600, // 窗口高度
minWidth: 600, // 最小宽度
webPreferences: {
// 安全起见,推荐用 preload 脚本替代直接开启 nodeIntegration
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
}
});
// 加载渲染进程的 HTML 文件
mainWindow.loadFile('index.html');
// 开发阶段打开开发者工具(和网页调试一样方便)
mainWindow.webContents.openDevTools();
// 窗口关闭时释放引用
mainWindow.on('closed', () => {
mainWindow = null;
});
// 监听窗口状态变化,通过 IPC 通知渲染进程
mainWindow.on('maximize', () => {
mainWindow.webContents.send('window-status', '已最大化');
});
}
// 监听渲染进程发来的消息
ipcMain.on('send-to-main', (event, data) => {
console.log('渲染进程传来:', data);
// 回复渲染进程
event.reply('reply-from-main', `收到你的消息啦:${data}`);
});
// 应用就绪后创建窗口
app.whenReady().then(createWindow);
// 处理不同系统的窗口关闭逻辑(macOS 特殊处理)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') { // darwin 是 macOS 的标识
app.quit();
}
});
// macOS 下点击 Dock 图标重新创建窗口
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
② 预加载脚本:preload.js(安全通信关键)
Electron 12+ 后默认关闭了渲染进程的 Node.js 权限,推荐用预加载脚本实现安全通信------它像一个"中间件",把主进程的 API 安全地暴露给渲染进程。
javascript
const { contextBridge, ipcRenderer } = require('electron');
// 向渲染进程的全局对象暴露 API(命名空间为 electronAPI)
contextBridge.exposeInMainWorld('electronAPI', {
// 发送消息到主进程
sendMessage: (data) => ipcRenderer.send('send-to-main', data),
// 监听主进程的回复
onMessage: (callback) => ipcRenderer.on('reply-from-main', (event, data) => callback(data)),
// 监听窗口状态变化
onWindowStatus: (callback) => ipcRenderer.on('window-status', (event, data) => callback(data))
});
③ 渲染进程:index.html + renderer.js
渲染进程负责 UI 展示和用户交互,和开发普通网页完全一样。
javascript
const btn = document.getElementById('btn');
const msgBox = document.getElementById('msg-box');
// 点击按钮发送消息到主进程
btn.addEventListener('click', () => {
window.electronAPI.sendMessage('Hello 主进程,我是渲染进程!');
});
// 监听主进程的回复
window.electronAPI.onMessage((data) => {
msgBox.innerHTML += `${data}`;
});
// 监听窗口状态变化
window.electronAPI.onWindowStatus((data) => {
msgBox.innerHTML += `窗口状态:${data}`;
});
5. 启动应用,看效果!
在终端执行命令,就能看到你的第一个 Electron 应用跑起来了:
sql
npm start
点击按钮会看到进程间通信的效果,最大化窗口也会收到状态通知,开发者工具也默认打开了,调试起来和网页一模一样。
四、调试技巧:主进程+渲染进程都能调
开发中难免遇到 bug,掌握调试技巧能省很多时间。
1. 渲染进程调试
和网页调试完全一致: - 启动应用后,主进程代码里已经加了 mainWindow.webContents.openDevTools(),会自动打开开发者工具; - 断点、Console、Network 面板都能用,和调试 Vue/React 项目没区别。
2. 主进程调试(VS Code)
主进程是 Node.js 环境,需要配置调试文件:
- 在项目根目录创建
.vscode/launch.json文件; - 粘贴以下配置:
bash
{
"version": "0.2.0",
"configurations": [
{
"name": "Electron: Main",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
"windows": {
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
},
"args": ["."],
"outputCapture": "std"
}
]
}
配置完成后,在 VS Code 中按 F5 就能启动调试,在 main.js 里打个断点,代码执行到这里就会暂停,方便排查问题。
五、实战扩展:常用功能怎么实现?
基础应用跑通后,我们来加几个常用功能,让应用更实用。
1. 文件读写(主进程+IPC)
渲染进程不能直接操作文件,需要通过 IPC 调用主进程的 Node.js 能力。
csharp
const fs = require('fs'); // 引入 Node.js 的 fs 模块
// 用 handle 方法处理异步请求(有返回值)
ipcMain.handle('read-file', async (event, filePath) => {
try {
const content = fs.readFileSync(filePath, 'utf8');
return { success: true, content };
} catch (err) {
return { success: false, error: err.message };
}
});
// 文件写入
ipcMain.handle('write-file', async (event, { filePath, content }) => {
try {
fs.writeFileSync(filePath, content, 'utf8');
return { success: true };
} catch (err) {
return { success: false, error: err.message };
}
});
javascript
contextBridge.exposeInMainWorld('electronAPI', {
// 新增文件读写方法
readFile: (filePath) => ipcMain.invoke('read-file', filePath),
writeFile: (data) => ipcMain.invoke('write-file', data),
// 原有方法...
});
javascript
// 读取文件示例
async function readTestFile() {
const result = await window.electronAPI.readFile('./test.txt');
if (result.success) {
msgBox.innerHTML += `文件内容:${result.content}`;
} else {
msgBox.innerHTML += `读取失败:${result.error}`;
}
}
// 写入文件示例
async function writeTestFile() {
const result = await window.electronAPI.writeFile({
filePath: './output.txt',
content: '这是 Electron 写入的内容'
});
if (result.success) {
msgBox.innerHTML += `写入成功!`;
}
}
2. 系统对话框(打开文件/保存文件)
用 Electron 自带的 dialog 模块,实现系统级的文件选择框:
csharp
const { dialog } = require('electron');
// 打开文件选择框
ipcMain.on('open-file-dialog', async (event) => {
const { filePaths } = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile'], // 只允许打开文件
filters: [{ name: '文本文件', extensions: ['txt'] }] // 筛选文件类型
});
// 将选中的文件路径返回给渲染进程
if (filePaths.length > 0) {
event.reply('file-selected', filePaths[0]);
}
});
3. 系统托盘(常驻任务栏)
给应用加个托盘图标,点击能显示菜单,提升用户体验:
scss
const { Tray, Menu } = require('electron');
let tray;
function createTray() {
// 托盘图标(需要自己准备一张图片,比如 tray.png)
tray = new Tray(path.join(__dirname, 'tray.png'));
// 托盘右键菜单
const trayMenu = Menu.buildFromTemplate([
{ label: '显示窗口', click: () => mainWindow.show() },
{ label: '隐藏窗口', click: () => mainWindow.hide() },
{ type: 'separator' }, // 分割线
{ label: '退出应用', click: () => app.quit() }
]);
tray.setContextMenu(trayMenu);
tray.setToolTip('我的 Electron 应用'); // 鼠标悬浮提示
// 点击托盘图标显示/隐藏窗口
tray.on('click', () => {
mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
});
}
// 在 createWindow 函数末尾调用
createWindow() {
// ... 原有代码 ...
createTray();
}
六、打包发布:生成各平台安装包
开发完成后,需要打包成对应系统的安装包,才能分发给用户。这里用最常用的 electron-builder 工具。
1. 完善打包配置
修改 package.json 中的 build 字段,适配 Windows、macOS、Linux 三大平台:
json
"build": {
"appId": "com.youname.electrondemo", // 应用唯一标识(反向域名格式)
"productName": "ElectronDemo", // 应用名称
"directories": {
"output": "dist" // 打包输出目录
},
"files": [ // 打包时需要包含的文件
"main.js",
"preload.js",
"index.html",
"renderer.js",
"tray.png", // 托盘图标
"node_modules/**/*" // 依赖包
],
// Windows 配置
"win": {
"target": [
{ "target": "nsis", "arch": ["x64", "ia32"] }, // 安装包(32/64位)
"portable" // 便携版(无需安装)
],
"icon": "assets/icon.ico" // 应用图标(ico 格式)
},
// macOS 配置
"mac": {
"target": "dmg", // 生成 dmg 安装包
"icon": "assets/icon.icns", // 图标(icns 格式)
"category": "public.app-category.utilities" // 应用分类
},
// Linux 配置
"linux": {
"target": "deb", // deb 包(Ubuntu 等系统用)
"icon": "assets/icon.png" // 图标(png 格式)
},
// Windows 安装包细节配置
"nsis": {
"oneClick": false, // 不启用一键安装
"allowToChangeInstallationDirectory": true, // 允许用户选择安装目录
"createDesktopShortcut": true, // 创建桌面快捷方式
"installerIcon": "assets/icon.ico" // 安装程序图标
}
}
2. 准备图标资源
不同平台对图标格式要求不同,推荐用 图标转换工具 生成对应格式:
- Windows:ico 格式(尺寸 256x256);
- macOS:icns 格式;
- Linux:png 格式(尺寸 512x512)。
在项目根目录创建 assets 文件夹,把图标放进去。
3. 执行打包命令
perl
# 打包测试版(未压缩,快速生成,用于测试)
npm run pack
# 打包正式版(生成安装包,适合分发)
npm run build
打包完成后,dist 目录下会出现对应平台的安装包,比如 Windows 会有 .exe 安装程序和便携版,macOS 会有 .dmg 文件。
注意:macOS 安装包需要在 macOS 系统上打包,Windows 安装包可在 Windows 或 macOS(需装 Wine)上打包。
七、性能优化:解决 Electron 应用"体积大、启动慢"问题
Electron 应用的通病是体积大、启动慢,这些优化技巧能帮你改善体验。
- 精简依赖 : - 用
npm prune --production移除开发依赖; - 避免引入大体积库(比如用 Lodash 子集替代完整包)。 - 禁用不必要功能 : - 生产环境关闭开发者工具; - 关闭
nodeIntegration,只用 preload 脚本暴露必要 API。 - 资源压缩: - 用 Webpack/Vite 压缩 HTML/CSS/JS; - 优化图片(用 TinyPNG 等工具压缩)。
- 启动优化: - 延迟加载非首屏资源; - 避免主进程启动时执行过多同步操作。
- 内存管理 : - 窗口关闭时及时释放引用; - 清理无用的 IPC 监听(用
ipcRenderer.removeListener)。
八、常见踩坑总结
整理了几个新手常遇到的问题,帮你少走弯路:
- Electron 安装失败 : 原因:网络问题或 Node.js 版本不兼容。 解决:配置国内镜像,确认 Node.js 是 LTS 版本,执行
npm cache clean --force清理缓存后重试。 - 渲染进程调用 electronAPI 报错 : 原因:preload 脚本配置错误,或 API 未暴露。 解决:检查
webPreferences中preload路径是否正确,确认contextBridge.exposeInMainWorld配置无误。 - 打包后应用无法运行 : 原因:
build.files配置遗漏文件,或依赖缺失。 解决:确认所有核心文件都在files列表中,打包前重新安装依赖(rm -rf node_modules && npm install)。 - macOS 应用无法打开(提示"未知开发者") : 原因:macOS 安全机制限制。 解决:右键应用选择"打开",或用苹果开发者账号签名(正式发布需要)。
九、总结与扩展
到这里,你已经掌握了 Electron 开发的完整流程:从环境搭建到项目初始化,从核心功能开发到打包发布,再到调试和优化。Electron 的核心优势就是"复用前端技术栈,跨平台成本低",前端开发者几乎零门槛就能上手。
如果想开发更复杂的应用,可以结合这些工具:
- UI 框架 :用 Vue/React/Angular 构建复杂界面(比如
vue-cli-plugin-electron-builder可快速创建 Vue+Electron 项目); - 本地存储 :用
electron-store存储配置信息,比localStorage更稳定; - 自动更新 :用
electron-updater实现应用自动更新; - 调试工具 :
electron-inspector增强调试能力。
现在,就用 Electron 把你的网页项目改造成桌面应用吧!如果遇到问题,欢迎在评论区交流~