该框架通过整合Chromium内核和Node.js运行时环境,允许开发者使用JavaScript、HTML及CSS构建兼容Windows、macOS与Linux系统的桌面应用,架构采用主进程处理系统级交互、渲染进程依托Chromium展示界面及IPC通信机制。(说白了就是包装)
一、项目概述
使用 Electron 将在线网页封装成独立的 Windows 桌面应用程序 Dr.aiVoss。
二、搭建electron
第一步(文件初始化)
新建一个空的文件夹,编辑器中打开这个文件夹(例如:my-electron-app)
cd 你新创建的文件
npm init

初始化时可以一站式回车,当然也可以填入相应的内容信息。执行完之后会生成package.json文件。
第二步(安装electron)
npm install --save-dev electron
安装之后
html
npm install
html
npm install --save-dev electron-builder
主要是运行整个项目以及打包整个项目生成exe文件。
安装的过程中可能会比较慢,影响因素是文件过大以及网络问题。
第三步(package.json 关键配置)
html
{
"name": "my-electron-app",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "electron .",
"build:win": "electron-builder --win"
},
"build": {
"appId": "com.hithinker.voss",
"productName": "Dr.aiVoss",
"files": ["index.js", "package.json"],
"win": {
"target": [{"target": "nsis", "arch": ["x64"]}],
"icon": "public/icon/icons.ico"
}
},
"devDependencies": {
"electron": "^39.2.7",
"electron-builder": "^26.0.12"
}
}
第四步(编写文件)
根目录创建 index.html
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
<title>Hello World! - My Electron App</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
</body>
</html>
根目录创建 index.js(我在原有基础配置上加上了屏幕的缩放以及控制台显示)
html
// 在文件头部引入 Node.js 中的 path 模块
const path = require('path')
// app 它控制应用程序的事件生命周期。
// BrowserWindow 模块,它创建和管理应用程序 窗口。
const { app, BrowserWindow, globalShortcut } = require('electron');
// 保存主窗口引用
let mainWindow = null
// 创建浏览器窗口
function createWindow () {
//__dirname 字符串指向当前正在执行脚本的路径 (在本例中,它指向你的项目的根文件夹)
mainWindow = new BrowserWindow({
width: 1000,
height: 800,
resizable: true,
minWidth: 800,
minHeight: 600,
backgroundColor: '#fff',
icon: path.join(__dirname, 'public/icon/icons.ico'),
webPreferences: {
nodeIntegration: true
}
})
// 本地文件
//mainWindow.loadFile('index.html')
// 线上页面
mainWindow.loadURL('https://www.csdn.net/')
// 打开控制台
// mainWindow.webContents.openDevTools()
// 启用页面缩放功能
mainWindow.webContents.on('did-finish-load', () => {
// 设置缩放级别限制
mainWindow.webContents.setVisualZoomLevelLimits(1, 5)
// 启用视觉缩放
mainWindow.webContents.setZoomFactor(1.0)
})
// 监听鼠标滚轮缩放
mainWindow.webContents.on('zoom-changed', (event, zoomDirection) => {
const currentZoom = mainWindow.webContents.getZoomFactor()
if (zoomDirection === 'in') {
// 放大
mainWindow.webContents.setZoomFactor(Math.min(currentZoom + 0.1, 5.0))
} else {
// 缩小
mainWindow.webContents.setZoomFactor(Math.max(currentZoom - 0.1, 0.25))
}
})
// 注册缩放快捷键
registerZoomShortcuts()
// 监听窗口内的键盘事件(用于 F12 等按键)
mainWindow.webContents.on('before-input-event', (event, input) => {
// F12 打开/关闭开发者工具
if (input.key === 'F12') {
mainWindow.webContents.toggleDevTools()
}
})
};
// 保存当前缩放级别
let zoomLevel = 1.0
// 注册缩放快捷键
function registerZoomShortcuts() {
// Ctrl + = 放大
globalShortcut.register('CommandOrControl+=', () => {
if (mainWindow) {
zoomLevel = Math.min(zoomLevel + 0.1, 5.0)
mainWindow.webContents.setZoomFactor(zoomLevel)
}
})
// Ctrl + Shift + = 放大(针对不需要按 Shift 就能按 + 的键盘)
globalShortcut.register('CommandOrControl+Shift+=', () => {
if (mainWindow) {
zoomLevel = Math.min(zoomLevel + 0.1, 5.0)
mainWindow.webContents.setZoomFactor(zoomLevel)
}
})
// Ctrl + - 缩小
globalShortcut.register('CommandOrControl+-', () => {
if (mainWindow) {
zoomLevel = Math.max(zoomLevel - 0.1, 0.25)
mainWindow.webContents.setZoomFactor(zoomLevel)
}
})
// Ctrl+Shift+I 打开/关闭开发者工具
globalShortcut.register('CommandOrControl+Shift+I', () => {
if (mainWindow) {
mainWindow.webContents.toggleDevTools()
}
})
// F5 或 Ctrl+R 刷新页面
globalShortcut.register('F5', () => {
if (mainWindow) {
mainWindow.reload()
}
})
globalShortcut.register('CommandOrControl+R', () => {
if (mainWindow) {
mainWindow.reload()
}
})
// Ctrl+Shift+R 强制刷新(清除缓存)
globalShortcut.register('CommandOrControl+Shift+R', () => {
if (mainWindow) {
mainWindow.webContents.reloadIgnoringCache()
}
})
}
// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此,通常对程序和它们在
// 任务栏上的图标来说,应当保持活跃状态,直到用户使用 Cmd + Q 退出。
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// 应用退出时注销所有快捷键
app.on('will-quit', () => {
globalShortcut.unregisterAll()
})
// 部分 API 在 ready 事件触发后才能使用。
// 在 Electron 中,只有在 app 模块的 ready 事件被激发后才能创建浏览器窗口
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// 通常在 macOS 上,当点击 dock 中的应用程序图标时,如果没有其他打开的窗口,那么程序会重新创建一个窗口。
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
三、项目启动与打包
终端执行之后会直接打开网页
html
npm start


html
npm run build
或者
npm run build:win


直接拖拽到桌面或直接创建快捷方式(直接点击打开即可)


四、实现的功能
1. 窗口管理
- ✅ 自定义窗口大小(1000x800)
- ✅ 可调整窗口大小
- ✅ 最小尺寸限制(800x600)
- ✅ 自定义应用图标
2. 缩放功能
- ✅ Ctrl + 鼠标滚轮 - 页面缩放
- ✅ Ctrl + = - 放大(每次 +10%)
- ✅ Ctrl + - - 缩小(每次 -10%)
- ✅ Ctrl + 0 - 重置到 100%
- ✅ 缩放范围:25% ~ 500%
3. 开发者工具
- ✅ F12 - 打开/关闭控制台
- ✅ Ctrl + Shift + I - 打开/关闭控制台
4. 页面刷新
- ✅ F5 - 刷新页面
- ✅ Ctrl + R - 刷新页面
- ✅ Ctrl + Shift + R - 强制刷新(清除缓存)
五、注意事项
1. 图标要求
.ico文件必须包含至少 256x256 像素- 推荐包含多尺寸:16x16, 32x32, 48x48, 256x256
实现自定义图标
问题分析:
npm start显示了自定义图标 ✅- 打包时因为网络问题无法下载签名工具,导致图标无法嵌入到 exe 文件中 ❌
解决方案有几个:
方案1:手动下载签名工具缓存
# 手动下载 winCodeSign-2.6.0.7z 并放到缓存目录
方案2:使用 ResHacker 或其他工具手动修改图标
方案3:暂时接受现状 (虽然打包失败,但 exe 文件已经生成在 dist/win-unpacked/Dr.aiVoss.exe,只是图标是默认的)
方案4:在能连接 GitHub 的环境下重新打包
由于网络问题,当前情况下:
- 开发模式 (
npm start) - 图标正常 ✅ - 打包后 (
dist/win-unpacked/Dr.aiVoss.exe) - 使用默认图标 ❌
建议:
- 先使用
dist/win-unpacked/Dr.aiVoss.exe这个可执行文件 - 或者使用代理/VPN 后重新运行
npm run build:win - 或者使用工具如 Resource Hacker 手动替换 exe 图标
2. 开发 vs 打包
- 开发模式 :通过代码中的
icon属性显示图标 - 打包模式 :通过
package.json的build.win.icon配置
3. 网络问题
- 打包时需要下载签名工具(winCodeSign)
- 如遇网络问题,可使用
dist/win-unpacked/中的 exe 文件
六、总结
通过 Electron 成功实现了:
- 将在线网页封装为独立桌面应用
- 完整的窗口管理功能
- 用户体验优化(缩放、刷新等)
- 自定义应用图标和名称
- 生成可分发的 .exe 文件
这种方式非常适合将现有的 Web 应用快速打包成桌面应用,无需重写代码。