Electron 学习教程
Electron 是一个使用 JavaScript、HTML 和 CSS 构建跨平台桌面应用程序的框架。
目录
- [Electron 简介](#Electron 简介 "#electron-%E7%AE%80%E4%BB%8B")
- 环境搭建
- [Electron 基础](#Electron 基础 "#electron-%E5%9F%BA%E7%A1%80")
- 主进程与渲染进程
- 进程间通信
- 常用模块
- 打包与分发
- 安全实践
- 性能优化
- 进阶主题
Electron 简介
Electron 由 GitHub 开发并开源,结合了 Chromium 和 Node.js,允许开发者使用 Web 技术构建桌面应用。知名应用如 VS Code、Slack、Discord 等都使用 Electron 构建。
核心特点:
- 跨平台(Windows、macOS、Linux),HarmonyOS支持普通应用(需适配)
- 使用 HTML、CSS 和 JavaScript 开发
- 完整的 Node.js 集成
- 丰富的原生 API 访问能力
环境搭建
准备工作
确保你的系统已安装:
- Node.js (建议使用最新的 LTS 版本)
- npm 或 yarn (本教程使用 npm)
- 代码编辑器 (如 VS Code)
第一步:创建 Vue 3 项目
- 使用 Vue CLI 创建新项目:
bash
npm install -g @vue/cli
bash
vue create electron-vue3-app
-
在交互式界面中选择(可选):
- 选择 "Manually select features"
- 勾选:Babel, Router, Vuex, CSS Pre-processors, Linter
- 选择 Vue 3.x
- 其他选项按需选择或使用默认值
-
进入项目目录:
bash
cd electron-vue3-app
第二步:添加 Electron 支持
- 安装 Electron 作为开发依赖:
bash
npm install electron --save-dev
在工程目录下新增.mpmrc文件, 配置如下, 直接执行上述命令会报错
bash
# npmrc文件配置
registry=https://cmc.centralrepo.rnd.huawei.com/artifactory/api/npm/npm-central-repo/
strict-ssl=false
electron_mirror=http://mirrors.tools.huawei.com/electron/
# 其它依赖配置(可选)
sass_binary_site=http://mirrors-devcloud.rnd.huawei.com/repository/toolkit/node-sass/
@devui:registry=https://cmc.centralrepo.rnd.huawei.com/artifactory/api/npm/product_npm/
@baize:registry=https://cmc.centralrepo.rnd.huawei.com/artifactory/api/npm/product_npm/
@avenueui:registry=https://maven.cloudartifact.lfg.dragon.tools.huawei.com/artifactory/api/npm/npm-cbu-common/
@cloud:registry=https://maven.cloudartifact.lfg.dragon.tools.huawei.com/artifactory/api/npm/npm-cbu-common/
- 安装必要的工具:
bash
npm install electron-builder --save-dev
npm install concurrently wait-on cross-env --save-dev
第三步:配置 Electron 主进程
- 在项目根目录创建
electron
文件夹,然后创建main.js
文件:
javascript
// electron/main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
function createWindow() {
// 创建浏览器窗口
const win = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
// 加载应用
if (process.env.NODE_ENV === 'development') {
win.loadURL('http://localhost:8080')
win.webContents.openDevTools()
} else {
win.loadFile(path.join(__dirname, '../dist/index.html'))
}
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
第四步:修改 package.json
- 修改
package.json
文件:
json
{
"name": "electron-vue3-app",
"version": "0.1.0",
"private": true,
"main": "electron/main.js",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"electron:serve": "concurrently -k \"cross-env NODE_ENV=development vue-cli-service serve\" \"wait-on http://localhost:8080 && electron .\"",
"electron:build": "vue-cli-service build && electron-builder"
},
"dependencies": {
// Vue 3 相关依赖
},
"devDependencies": {
// 原有的 devDependencies
"electron": "^最新版本",
"electron-builder": "^最新版本",
"concurrently": "^最新版本",
"wait-on": "^最新版本",
"cross-env": "^最新版本"
}
}
第五步:解决 Electron 与 Vue 的集成问题
- 在
vue.config.js
中添加以下配置(如果没有则创建该文件):
javascript
// vue.config.js
module.exports = {
pluginOptions: {
electronBuilder: {
nodeIntegration: true
}
},
configureWebpack: {
target: 'electron-renderer'
}
}
第六步:运行项目
- 开发模式运行:
bash
npm run electron:serve
- 生产环境构建:
bash
npm run electron:build
Electron 基础
最小 Electron 应用
perl
my-electron-app/
├── package.json
├── main.js # 主进程文件
└── index.html # 渲染进程页面
main.js(主进程):
javascript
const { app, BrowserWindow } = require('electron')
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
win.loadFile('index.html')
}
app.whenReady().then(createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
index.html(渲染进程):
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello Electron</title>
</head>
<body>
<h1>Hello Electron!</h1>
<p>We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.</p>
</body>
</html>
package.json:
json
{
"name": "my-electron-app",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^latest"
}
}
主进程与渲染进程
Electron 应用基于多进程架构:
-
主进程:管理应用生命周期、创建窗口、调用原生 API
- 每个 Electron 应用有且只有一个主进程
- 使用 Node.js API
-
渲染进程:显示网页内容(每个窗口一个渲染进程)
- 类似常规网页,可以使用 DOM API
- 默认情况下不能直接访问 Node.js API
进程间通信
Electron 提供了几种 IPC(进程间通信)方式:
1. 使用 ipcMain
和 ipcRenderer
主进程 (main.js):
javascript
const { ipcMain } = require('electron')
ipcMain.on('message-from-renderer', (event, arg) => {
console.log(arg) // 打印 "Hello from renderer"
event.reply('message-from-main', 'Hello from main')
})
渲染进程 (index.html):
html
<script>
const { ipcRenderer } = require('electron')
// 发送消息到主进程
ipcRenderer.send('message-from-renderer', 'Hello from renderer')
// 监听主进程回复
ipcRenderer.on('message-from-main', (event, arg) => {
console.log(arg) // 打印 "Hello from main"
})
</script>
更加详细的内容请参考文章:Electron 进程通信机制详解
常用模块
-
菜单 (Menu)
-
对话框 (Dialog)
-
系统通知 (Notification)
-
系统托盘 (Tray)
更加详细的内容请参考文章:Electron 常用 API 全面指南
打包与分发
1. 使用 electron-builder
bash
npm install electron-builder --save-dev
2. 使用 electron-forge
bash
npx create-electron-app my-app --template=webpack
cd my-app
npm run make
3. electron-builder vs. electron-forge
特性 | electron-builder | electron-forge |
---|---|---|
定位 | 专注于打包和分发 | 完整的 Electron 开发工具链 |
配置复杂度 | 中等,需要较多配置 | 简单,开箱即用 |
功能范围 | 强大的打包功能 | 全生命周期管理(创建→开发→打包) |
自定义能力 | 非常高 | 中等 |
自动更新支持 | 内置完善 | 需要插件 |
社区生态 | 非常活跃 | 较活跃 |
多平台打包 | 单机跨平台打包 | 需要分平台打包 |
安全实践
-
禁用 Node.js 集成:对不需要 Node.js 集成的窗口禁用
javascriptnew BrowserWindow({ webPreferences: { nodeIntegration: false, contextIsolation: true } })
-
使用上下文隔离:保护预加载脚本
javascript// 主进程 new BrowserWindow({ webPreferences: { contextIsolation: true, preload: path.join(__dirname, 'preload.js') } }) // preload.js const { contextBridge } = require('electron') contextBridge.exposeInMainWorld('api', { send: (channel, data) => { // 白名单验证 const validChannels = ['to-main'] if (validChannels.includes(channel)) { ipcRenderer.send(channel, data) } }, receive: (channel, func) => { const validChannels = ['from-main'] if (validChannels.includes(channel)) { ipcRenderer.on(channel, (event, ...args) => func(...args)) } } })
-
验证用户输入:特别是来自渲染进程的输入
-
保持依赖更新:定期更新 Electron 和依赖项
性能优化
-
启用原生窗口:避免透明窗口和自定义边框
javascriptnew BrowserWindow({ transparent: false, frame: true })
-
懒加载资源:按需加载页面和资源
-
使用 Web Workers:处理 CPU 密集型任务
-
禁用 DevTools 扩展:生产环境中
javascriptwin.webContents.on('devtools-opened', () => { win.webContents.closeDevTools() })
-
监控内存使用:
javascriptsetInterval(() => { console.log(process.memoryUsage()) }, 5000)
其他
1. 使用 TypeScript
bash
npm install --save-dev typescript @types/node @types/electron
tsconfig.json:
json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
}
}
2. 调试技巧
-
使用 Chrome DevTools
javascriptwin.webContents.openDevTools()
-
快捷键
javascriptctrl+shift+I
学习资源
- Electron 官方文档
- Electron Fiddle - 学习和实验 Electron 的工具
- Awesome Electron - 精选资源列表
- Electron 示例应用