Electron重点

Electron 开发重点知识体系梳理

Electron 是基于 ChromiumNode.js 的跨平台桌面应用开发框架,核心逻辑是用 Web 技术(HTML/CSS/JS)开发界面,同时通过 Node.js 调用原生系统能力。以下是从基础架构到工程化落地的完整知识体系梳理。


项目汇总

code/all/e-streamlabs-obs-v0.21.2
code/all/e-live
code/all/e-ppt
code/all/e-live-streaming
code/all/e-ipub
code/all/e-ysy


一、核心架构与基础概念

1. 双进程模型(核心基石)

Electron 应用由两类进程组成,二者职责严格分离,通过 IPC 通信协作:

进程类型 核心职责 运行环境 入口文件
主进程 (Main Process) 应用生命周期管理、窗口创建、原生系统调用、全局状态管理 Node.js 环境 package.jsonmain 字段指定的文件(如 main.js
渲染进程 (Renderer Process) 页面渲染、UI 交互、业务逻辑执行 Chromium 环境(类似浏览器标签页) 每个 BrowserWindow 加载的 HTML/JS 文件

2. 关键模块与对象

  • app 模块:控制应用的生命周期(仅主进程可用)。
  • BrowserWindow 模块:创建和管理应用窗口(仅主进程可用)。
  • webContents 对象:渲染进程的核心对象,负责页面渲染和与渲染进程通信(主进程中通过 win.webContents 访问)。

二、进程间通信 (IPC) —— 开发核心难点

Electron 双进程模型下,主进程与渲染进程、渲染进程之间的通信是最频繁且最容易出错的环节,必须掌握以下模式:

1. 核心通信模块

  • **ipcMain**:主进程模块,用于监听渲染进程发送的消息。
  • **ipcRenderer**:渲染进程模块,用于向主进程发送消息、监听主进程回复。

2. 常用通信模式

(1)渲染进程 → 主进程(单向通知)

场景:渲染进程触发主进程执行某个操作(如打开文件选择框、创建新窗口)。

1
2
3
4
5
6
7
8
9
10
// 渲染进程 (renderer.js)
const { ipcRenderer } = require('electron');
ipcRenderer.send('open-file-dialog');

// 主进程 (main.js)
const { ipcMain, dialog } = require('electron');
ipcMain.on('open-file-dialog', async (event) => {
const result = await dialog.showOpenDialog({ properties: ['openFile'] });
console.log(result.filePaths);
});

(2)渲染进程 → 主进程 → 渲染进程(双向请求/响应)

场景:渲染进程请求主进程执行异步操作并返回结果(如读取本地文件、调用系统 API)。

1
2
3
4
5
6
7
8
9
10
11
12
// 渲染进程 (renderer.js)
const { ipcRenderer } = require('electron');
async function readFile() {
const content = await ipcRenderer.invoke('read-local-file', '/path/to/file.txt');
console.log(content);
}

// 主进程 (main.js)
const { ipcMain, fs } = require('electron');
ipcMain.handle('read-local-file', async (event, filePath) => {
return fs.promises.readFile(filePath, 'utf-8');
});

(3)主进程 → 渲染进程(主动推送)

场景:主进程监听系统事件(如托盘点击、网络变化),主动通知渲染进程更新 UI。

1
2
3
4
5
6
7
// 主进程 (main.js)
win.webContents.send('system-tray-clicked', { timestamp: Date.now() });

// 渲染进程 (renderer.js)
ipcRenderer.on('system-tray-clicked', (event, data) => {
console.log('托盘被点击:', data);
});

3. 上下文隔离下的安全通信(现代 Electron 标准做法)

为了安全,**现代 Electron 必须启用 contextIsolation 和禁用 nodeIntegration**,此时渲染进程无法直接访问 ipcRenderer,需通过 Preload 脚本 暴露安全 API:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 主进程创建窗口时配置
const win = new BrowserWindow({
webPreferences: {
nodeIntegration: false, // 禁用渲染进程 Node.js 集成
contextIsolation: true, // 启用上下文隔离(默认开启)
preload: path.join(__dirname, 'preload.js') // 预加载脚本
}
});

// preload.js(预加载脚本,在渲染进程上下文隔离前执行)
const { contextBridge, ipcRenderer } = require('electron');
// 向渲染进程暴露安全 API
contextBridge.exposeInMainWorld('electronAPI', {
openFileDialog: () => ipcRenderer.send('open-file-dialog'),
readLocalFile: (filePath) => ipcRenderer.invoke('read-local-file', filePath),
onTrayClick: (callback) => ipcRenderer.on('system-tray-clicked', callback)
});

// 渲染进程 (renderer.js) 中直接使用暴露的 API
window.electronAPI.openFileDialog();

三、窗口与应用生命周期管理

1. BrowserWindow 窗口配置

创建窗口时的核心配置项(webPreferences 是安全重点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const win = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
frame: false, // 无边框窗口(自定义标题栏时用)
transparent: true, // 透明窗口(配合无边框使用)
resizable: true,
webPreferences: {
// 安全配置(必看)
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js'),
// 开发环境配置
devTools: true // 生产环境建议禁用
}
});

// 加载页面
win.loadURL('https://example.com'); // 加载远程 URL
win.loadFile('index.html'); // 加载本地 HTML 文件

2. 窗口类型与层级

  • 父子窗口:通过 parent 选项创建,子窗口始终显示在父窗口上方。
    1
    const childWin = new BrowserWindow({ parent: win, modal: true });
  • 模态窗口:设置 modal: true,阻塞父窗口交互(常用于弹窗、对话框)。

3. 应用生命周期(app 模块事件)

掌握核心生命周期事件,控制应用启动、退出逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const { app } = require('electron');

// 1. 应用准备就绪(创建窗口的最佳时机)
app.whenReady().then(() => {
createWindow();
// macOS 特性:点击 Dock 图标重新创建窗口
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});

// 2. 所有窗口关闭时(Windows/Linux 直接退出应用)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit();
});

// 3. 应用退出前(清理资源、保存数据)
app.on('before-quit', (event) => {
// 可在此阻止退出:event.preventDefault();
});

四、原生能力与系统交互

Electron 的核心优势是通过 Node.js 和内置模块调用原生系统能力,以下是高频使用场景:

1. 文件系统操作

主进程可直接使用 Node.js 的 fspath 模块,结合 dialog 模块实现文件选择:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const { dialog } = require('electron');
const fs = require('fs/promises');

// 打开文件选择框
async function selectAndReadFile() {
const { canceled, filePaths } = await dialog.showOpenDialog({
properties: ['openFile'],
filters: [{ name: 'Text Files', extensions: ['txt'] }]
});
if (!canceled) {
const content = await fs.readFile(filePaths[0], 'utf-8');
return content;
}
}

2. 菜单与托盘

  • 应用菜单:通过 Menu 模块创建自定义菜单栏(Windows/Linux 在窗口顶部,macOS 在屏幕顶部)。
    1
    2
    3
    4
    5
    6
    7
    const { Menu } = require('electron');
    const template = [
    { label: '文件', submenu: [{ label: '打开', click: () => console.log('打开文件') }] },
    { label: '编辑', submenu: [{ role: 'copy' }, { role: 'paste' }] } // 使用内置 role
    ];
    const menu = Menu.buildFromTemplate(template);
    Menu.setApplicationMenu(menu);
  • 系统托盘:通过 Tray 模块添加系统托盘图标和右键菜单。
    1
    2
    3
    4
    5
    6
    7
    8
    const { Tray, Menu } = require('electron');
    const tray = new Tray('path/to/icon.png');
    const contextMenu = Menu.buildFromTemplate([
    { label: '显示窗口', click: () => win.show() },
    { label: '退出', click: () => app.quit() }
    ]);
    tray.setToolTip('My Electron App');
    tray.setContextMenu(contextMenu);

3. 系统集成

  • 通知:使用 HTML5 Notification API(渲染进程)或 Node.js 模块(主进程)。
  • 剪贴板:通过 clipboard 模块读写系统剪贴板。
  • 外部链接:通过 shell 模块在默认浏览器中打开链接(避免在 Electron 窗口中打开外部页面)。
    1
    2
    const { shell } = require('electron');
    shell.openExternal('https://github.com');

五、工程化:打包与分发

开发完成后,需将 Electron 应用打包为各平台的安装包(.exe.dmg.AppImage 等),**electron-builder** 是目前最主流的打包工具。

1. 快速配置

package.json 中添加 build 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"name": "my-electron-app",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron .",
"build:win": "electron-builder --win", // 打包 Windows
"build:mac": "electron-builder --mac", // 打包 macOS
"build:linux": "electron-builder --linux" // 打包 Linux
},
"build": {
"appId": "com.example.myapp",
"productName": "My Electron App",
"directories": { "output": "dist" },
"win": { "target": "nsis", "icon": "build/icon.ico" },
"mac": { "target": "dmg", "icon": "build/icon.icns" },
"linux": { "target": "AppImage" }
}
}

2. 自动更新

使用 electron-updater 实现应用自动更新(需配合静态文件服务器或 GitHub Releases):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 主进程中配置
const { autoUpdater } = require('electron-updater');

// 检查更新
app.whenReady().then(() => {
autoUpdater.checkForUpdatesAndNotify();
});

// 监听更新事件
autoUpdater.on('update-available', () => {
dialog.showMessageBox({ message: '发现新版本,正在下载...' });
});
autoUpdater.on('update-downloaded', () => {
dialog.showMessageBox({ message: '更新下载完成,点击确定重启应用' }, () => {
autoUpdater.quitAndInstall();
});
});

六、性能优化与安全

1. 性能优化重点

  • 渲染进程性能
    • 避免在主线程执行 heavy 计算,使用 Web Workers
    • 优化 DOM 操作,使用虚拟滚动(如 react-window)处理长列表。
    • 减少不必要的重绘重排,使用 CSS transformopacity 做动画。
  • 主进程性能
    • 避免在主进程执行阻塞操作(如同步文件读写),尽量使用异步 API。
    • 合理使用 BrowserWindowshow: false 预加载窗口,提升打开速度。
  • 内存管理
    • 及时关闭不再使用的窗口,避免内存泄漏。
    • 移除不再需要的 IPC 监听器(ipcRenderer.removeListener)。

2. 安全红线(必须遵守)

Electron 应用的安全漏洞可能导致远程代码执行,以下是强制安全配置

  1. **始终禁用 nodeIntegration**,启用 contextIsolation
  2. 使用 Preload 脚本 暴露 API,禁止直接在渲染进程使用 Node.js。
  3. 禁止加载不受信任的远程内容,若必须加载,启用 webSecurity(默认开启)。
  4. **设置 Content Security Policy (CSP)**,在 HTML 中添加:
    1
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
  5. 避免使用 remote 模块(已弃用),改用 IPC 通信。

七、调试与常见问题

1. 调试技巧

  • 渲染进程调试:打开 DevTools(win.webContents.openDevTools()),和 Chrome 调试一致。
  • 主进程调试:使用 --inspect 启动应用,通过 Chrome DevTools 连接:
    1
    electron --inspect=5858 main.js
    然后在 Chrome 中访问 chrome://inspect 进行调试。

2. 常见坑点

  • 跨域问题:渲染进程加载远程接口时可能遇到 CORS,可在主进程通过 webRequest 模块修改响应头,或配置代理。
  • 路径问题:打包后文件路径变化,使用 path.join(__dirname, 'file.txt') 而非相对路径。
  • macOS 签名与公证:macOS 应用必须签名和公证才能在非开发者机器上运行,需在 electron-builder 中配置证书。

以上是 Electron 开发的核心知识体系,重点掌握双进程模型、IPC 通信、安全配置、打包分发,结合实际项目练习即可快速上手。


Electron重点
https://cszy.top/20260212-Electron重点/
作者
csorz
发布于
2026年2月12日
许可协议