1. Electron 开发环境快速搭建
对于刚接触 Electron 的新手来说,环境搭建往往是第一个门槛。我推荐使用 Node.js 16.x 及以上版本作为基础环境,这是目前 Electron 官方文档明确支持的稳定版本。
安装完 Node.js 后,建议通过以下命令初始化项目:
bash复制mkdir my-electron-app && cd my-electron-app
npm init -y
npm install --save-dev electron
这里有个小技巧:在 package.json 中,main 字段要指向主进程文件(通常命名为 main.js),同时需要添加一个 start 脚本:
json复制{
"main": "main.js",
"scripts": {
"start": "electron ."
}
}
注意:Windows 用户可能会遇到 node-gyp 编译问题,需要先安装 Python 2.7 和 Visual Studio Build Tools。这是 Electron 底层依赖 native 模块时的常见痛点。
1.1 项目目录结构设计
合理的目录结构能大幅提升后续开发效率。我推荐采用如下结构:
code复制/my-electron-app
├── main.js # 主进程
├── preload.js # 预加载脚本
├── package.json
└── src/
├── renderer/ # 渲染进程代码
└── assets/ # 静态资源
这种分离式结构有几个优势:
- 主进程和渲染进程代码物理隔离,避免混淆
- 静态资源集中管理
- 方便后续打包配置
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 主进程与渲染进程核心逻辑
2.1 基础主进程实现
主进程是 Electron 应用的核心,负责窗口管理和应用生命周期。下面是一个最简实现:
javascript复制const { app, BrowserWindow } = require('electron')
let mainWindow
app.whenReady().then(() => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
mainWindow.loadFile('src/renderer/index.html')
})
关键点解析:
BrowserWindow是渲染窗口的构造函数webPreferences.preload指定预加载脚本路径loadFile加载本地 HTML 文件
2.2 渲染进程安全实践
渲染进程默认运行在浏览器环境中,但直接暴露 Node.js API 会带来严重安全隐患。正确的做法是通过预加载脚本暴露有限接口:
preload.js 示例:
javascript复制const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
sendNotification: (title, body) => {
ipcRenderer.send('notify', { title, body })
}
})
然后在渲染进程中通过 window.electronAPI 调用这些安全封装的方法。
3. 常见功能模块实现
3.1 系统通知功能
系统通知是桌面应用的常见需求。在主进程中添加:
javascript复制const { Notification } = require('electron')
ipcMain.on('notify', (event, { title, body }) => {
new Notification({ title, body }).show()
})
重要:MacOS 需要在 package.json 中额外配置:
json复制{
"build": {
"mac": {
"extendInfo": {
"NSUserNotificationAlertStyle": "alert"
}
}
}
}
3.2 菜单栏定制
应用菜单通过 Menu 模块创建。典型配置:
javascript复制const { Menu } = require('electron')
const template = [
{
label: '文件',
submenu: [
{ role: 'quit' }
]
},
{
label: '编辑',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' }
]
}
]
Menu.setApplicationMenu(Menu.buildFromTemplate(template))
4. 调试与问题排查
4.1 主进程调试技巧
启动应用时添加 --inspect 参数可以调试主进程:
json复制{
"scripts": {
"debug": "electron --inspect=9229 ."
}
}
然后在 Chrome 中访问 chrome://inspect 即可附加调试器。
4.2 常见错误解决方案
问题:Electron 二进制下载失败
code复制downloading electron binary... typeerror: fetch failed
解决方案:
- 设置国内镜像源:
bash复制npm config set electron_mirror https://npm.taobao.org/mirrors/electron/
- 或使用 cnpm 安装
问题:DevServer 启动报错
code复制error during start dev server and electron app
检查 webpack 配置中 target 是否设置为 electron-renderer,并确保没有错误的 require 调用。
5. 打包与分发
5.1 使用 electron-builder
推荐配置:
json复制{
"build": {
"appId": "com.example.myapp",
"win": {
"target": "nsis"
},
"mac": {
"category": "public.app-category.developer-tools"
}
}
}
打包命令:
bash复制npx electron-builder --win --x64
5.2 鸿蒙系统适配
虽然 Electron 主要面向 Windows/Mac/Linux,但通过以下方式可以在鸿蒙上运行:
- 打包为 Linux 应用
- 使用鸿蒙的 Linux 兼容层运行
- 或通过 Web 版实现功能降级
6. 进阶技巧
6.1 性能优化实践
- 启用原生窗口句柄:
javascript复制new BrowserWindow({
webPreferences: {
nativeWindowOpen: true
}
})
- 使用 V8 快照:
bash复制electron --v8-compile-cache
- 对于复杂应用,考虑将计算密集型任务放到 Worker 线程。
6.2 安全加固措施
- 禁用 Node.js 集成(对不需要 Node 的窗口):
javascript复制new BrowserWindow({
webPreferences: {
nodeIntegration: false,
contextIsolation: true
}
})
- 实现 CSP 策略:
html复制<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'">
- 定期检查依赖漏洞:
bash复制npm audit
7. 与后端服务集成
7.1 调用 Spring Boot API
在预加载脚本中封装 fetch:
javascript复制contextBridge.exposeInMainWorld('api', {
fetchData: () => fetch('http://localhost:8080/api')
.then(res => res.json())
})
7.2 进程间通信优化
对于高频通信,考虑使用 SharedArrayBuffer:
javascript复制// 主进程
const sharedBuffer = new SharedArrayBuffer(1024)
mainWindow.webContents.postMessage('shared-buffer', sharedBuffer)
// 渲染进程
window.addEventListener('message', (e) => {
if (e.data === 'shared-buffer') {
const buffer = e.data
// 直接操作共享内存
}
})
8. 实际项目经验分享
在开发钉钉这类大型 Electron 应用时,我们总结出几个关键点:
- 模块化加载:将不常用的功能拆分为独立模块,按需加载
- 内存管理:显式释放不再使用的 BrowserWindow 实例
- 更新策略:采用差量更新减少包体积
- 崩溃报告:集成 Sentry 收集客户端错误
一个实用的性能检测方案:
javascript复制app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
app.on('web-contents-created', (e, contents) => {
contents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error(`加载失败: ${errorDescription}`)
})
})
最后提醒新手开发者:Electron 虽然强大,但要注意控制依赖数量,每个额外 npm 包都可能显著增加最终打包体积。建议定期运行 npm prune 清理未使用的依赖。
