官网: https://www.electronjs.org/zh/
安装依赖
首先初始化 package.json 文件,然后安装 Electron 作为开发依赖。
pnpm init
pnpm add -D electron
如果安装过程中遇到网络问题,可以通过配置 npm 镜像来解决。打开 npm 的配置文件(可通过 npm config edit 命令),在空白处添加以下淘宝镜像地址:
registry=https://registry.npmmirror.com
electron_mirror=https://cdn.npmmirror.com/binaries/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
手动配置完成后,重新运行 pnpm add -D electron 即可成功安装。
启动一个简单的项目
- 修改
package.json文件,更新main字段指向主进程脚本,并在scripts中添加启动命令。注意author和description字段为必填。
{
"name": "Electron-补习所",
"version": "1.0.0",
"description": "electron-test",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"keywords": [],
"author": "wangfan",
"license": "ISC",
"devDependencies": {
"electron": "^32.1.2"
}
}
- 在根目录新建
main.js文件作为主进程入口。监听应用的ready事件,创建一个浏览器窗口并加载指定 URL。
const { app, BrowserWindow } = require("electron");
app.on("ready", () => {
const win = new BrowserWindow({
width: 500,
height: 500,
autoHideMenuBar: true,
});
win.loadURL('https://www.electronjs.org/zh/');
});
加载本地页面
在根目录新建 pages 文件夹,并在其中创建 index.html 和 index.css 文件,编写简单的页面内容。接着修改 main.js,使用 loadFile 方法加载本地页面。
const { app, BrowserWindow } = require("electron");
app.on("ready", () => {
const win = new BrowserWindow({
width: 500,
height: 500,
autoHideMenuBar: true,
alwaysOnTop: true
});
win.loadFile('./pages/index.html');
});
启动项目后,如果开发者工具出现内容安全策略(CSP)警告,需要在 HTML 的 <head> 部分配置 CSP。具体配置可参考 MDN 文档。
完善窗口行为
为了管理窗口的生命周期,将创建窗口的逻辑封装为 createWindow 函数。根据操作系统差异,在 Windows 系统上,所有窗口关闭时退出应用;在 macOS 系统上,应用被激活时若没有窗口则自动创建一个。
const { app, BrowserWindow } = require("electron");
function createWindow() {
const win = new BrowserWindow({
width: 800,
height: 500,
autoHideMenuBar: true,
});
win.loadFile("./pages/index.html");
}
app.on("ready", () => {
createWindow();
app.on("window-all-closed", () => {
if (process.platform !== "darwin") app.quit();
});
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
自动启动应用
为了避免每次修改主进程代码后手动重启应用,可以安装 nodemon 来实现自动重启。
pnpm i nodemon -D
在 package.json 的 scripts 中修改启动命令:
"scripts": {
"start": "nodemon --exec electron ."
}
还可以在根目录创建 nodemon.json 配置文件,指定监视的文件类型,实现主进程或页面文件修改后自动重启。
{
"ignore": ["node modules", "dist"],
"restartable": "r",
"watch": ["*.*"],
"ext": "html,js,css"
}
主进程与渲染进程
在 Electron 中,主进程只有一个(即 main.js,运行在 Node.js 环境),而渲染进程可以有多个(即每个浏览器窗口中的 Web 页面,运行在 Web 环境)。两者环境隔离,不能直接互访 API。
预加载脚本(如 preload.js)作为桥梁,它在渲染进程之前运行,可以访问部分 Node.js API。通过 contextBridge 可以向渲染进程暴露自定义的全局对象。
主进程中加载预加载脚本的绝对路径:
const path = require("path");
const win = new BrowserWindow({
webPreferences: {
preload: path.resolve(__dirname, './preload.js'),
}
});
预加载脚本示例,向渲染进程暴露一个 myAPI 对象:
const { contextBridge } = require("electron");
contextBridge.exposeInMainWorld("myAPI", {
mytext: "这是暴露的变量,预加载进程可使用部分nodeAPI",
version: process.version
});
在渲染进程的 JavaScript 文件中,可以直接访问 window.myAPI 或 myAPI。
进程通讯(IPC)
进程间通信(IPC)是 Electron 的核心功能,允许主进程和渲染进程交换数据。
渲染进程向主进程通信(单向)
例如,实现点击按钮在 D 盘创建文件。在渲染进程中,通过预加载脚本暴露的函数发送消息。
渲染进程 (render.js):
setBtn.onclick = () => {
myAPI.saveFile(input.value);
};
预加载脚本 (preload.js):
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("myAPI", {
saveFile: (data) => {
ipcRenderer.send("file-save", data);
},
});
主进程 (main.js) 监听该事件并执行文件写入操作:
const { ipcMain } = require("electron");
const fs = require("fs");
function writeFile(_, data) {
fs.writeFileSync("D:/hello.txt", data);
}
ipcMain.on("file-save", writeFile);
渲染进程向主进程通信(双向)
例如,读取 D 盘文件内容。这需要使用 ipcRenderer.invoke 发送请求并返回 Promise。
渲染进程 (render.js):
getBtn.onclick = async () => {
let txt = await myAPI.readFile();
console.log(txt);
};
预加载脚本 (preload.js):
contextBridge.exposeInMainWorld("myAPI", {
readFile: () => {
return ipcRenderer.invoke("file-read");
},
});
主进程 (main.js) 处理请求并返回结果:
function readFile() {
return fs.readFileSync("D:/hello.txt").toString();
}
ipcMain.handle("file-read", readFile);
打包应用
使用 electron-builder 进行应用打包。
pnpm install electron-builder -D
在 package.json 中配置打包信息:
{
"scripts": {
"build": "electron-builder"
},
"build": {
"appId": "myelectron-app",
"win": {
"icon": "./logo.ico",
"target": [{
"target": "nsis",
"arch": ["x64"]
}]
},
"nsis": {
"oneClick": false,
"perMachine": true,
"allowToChangeInstallationDirectory": true
}
}
}
运行 pnpm run build 后,会在 dist 目录下生成安装包。