news 2026/9/30 11:48:06

网页包装为桌面应用(electron版)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
网页包装为桌面应用(electron版)

该框架通过整合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

安装之后

npm install
npm install --save-dev electron-builder

主要是运行整个项目以及打包整个项目生成exe文件。

安装的过程中可能会比较慢,影响因素是文件过大以及网络问题。

第三步(package.json 关键配置)

{ "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

<!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(我在原有基础配置上加上了屏幕的缩放以及控制台显示)

// 在文件头部引入 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() }) })

三、项目启动与打包

终端执行之后会直接打开网页

npm start

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

https://www.ico51.cn/ 在线转换

实现自定义图标

问题分析:

  1. npm start显示了自定义图标 ✅
  2. 打包时因为网络问题无法下载签名工具,导致图标无法嵌入到 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) - 使用默认图标 ❌

建议:

  1. 先使用dist/win-unpacked/Dr.aiVoss.exe这个可执行文件
  2. 或者使用代理/VPN 后重新运行npm run build:win
  3. 或者使用工具如 Resource Hacker 手动替换 exe 图标

2. 开发 vs 打包

  • 开发模式:通过代码中的icon属性显示图标
  • 打包模式:通过package.json的build.win.icon配置

3. 网络问题

  • 打包时需要下载签名工具(winCodeSign)
  • 如遇网络问题,可使用dist/win-unpacked/中的 exe 文件

六、总结

通过 Electron 成功实现了:

  1. 将在线网页封装为独立桌面应用
  2. 完整的窗口管理功能
  3. 用户体验优化(缩放、刷新等)
  4. 自定义应用图标和名称
  5. 生成可分发的 .exe 文件

这种方式非常适合将现有的 Web 应用快速打包成桌面应用,无需重写代码。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 10:33:10

YOLOv8移动端部署方案:NCNN/TensorRT/Lite适配

YOLOv8移动端部署方案&#xff1a;NCNN/TensorRT/Lite适配 在智能手机、无人机、智能摄像头等边缘设备上实现实时目标检测&#xff0c;早已不再是实验室里的概念。随着AI算力向终端下沉&#xff0c;越来越多的应用场景要求模型不仅“看得准”&#xff0c;还要“跑得快”——而这…

作者头像 李华
网站建设 2026/9/29 9:16:21

YOLOv8日志文件清理策略避免占用过多空间

YOLOv8日志文件清理策略避免占用过多空间 在AI研发的日常中&#xff0c;一个看似不起眼却频频引发“生产事故”的问题悄然浮现&#xff1a;磁盘满了。尤其是在使用YOLOv8这类高度自动化的深度学习框架时&#xff0c;一次不经意的训练任务可能就在后台悄悄生成几百MB甚至数GB的日…

作者头像 李华
网站建设 2026/9/29 9:16:23

YOLOv8特征融合网络结构图解说明

YOLOv8特征融合网络结构图解说明 在智能监控、自动驾驶和工业质检等现实场景中&#xff0c;目标检测模型不仅要“看得准”&#xff0c;还得“跑得快”。尤其是在复杂环境中&#xff0c;小目标密集、尺度变化剧烈、背景干扰严重等问题&#xff0c;对模型的多尺度感知能力提出了极…

作者头像 李华
网站建设 2026/9/29 9:16:20

YOLOv8 Cannot find module 错误修复指南

YOLOv8 Cannot find module 错误修复指南 在部署 YOLOv8 模型时&#xff0c;你是否曾遇到这样的报错&#xff1a; ModuleNotFoundError: No module named ultralytics明明已经拉取了官方镜像、启动了容器&#xff0c;为什么连最基本的 from ultralytics import YOLO 都无法执行…

作者头像 李华
网站建设 2026/9/29 9:16:22

YOLOv8模型版本管理:Git Tag发布规范说明

YOLOv8模型版本管理&#xff1a;Git Tag发布规范说明 在现代深度学习项目中&#xff0c;尤其是像YOLOv8这样迭代频繁、应用场景复杂的模型开发过程中&#xff0c;一个常见的困扰是&#xff1a;“我们上周训练的那个性能最好的模型&#xff0c;到底用的是哪份代码&#xff1f;用…

作者头像 李华
网站建设 2026/9/29 9:16:21

论文 AI 率到底怎么降?别再乱改了

一、为什么手动降重总翻车&#xff1f;学术党必知的3大痛点“明明查重率达标了&#xff0c;导师却说论文有AI味要求重写&#xff01;”——这是不是你的真实写照&#xff1f;很多同学误以为同义词替换调整句式就能蒙混过关&#xff0c;结果陷入三大困局&#xff1a;❌ 痛点1&am…

作者头像 李华