当前位置: 首页 > article >正文

Vue3.2 项目打包成 Electron 桌面应用

本文将详细介绍如何将基于 Vue3.2 的项目打包成 Electron 桌面应用。通过结合 Electron 和 Vue CLI 工具链,可以轻松实现跨平台桌面应用的开发与发布。

1. 项目结构说明

项目主要分为以下几个部分:

  • electron/main.js:Electron 主进程文件。
  • electron/preload.js:Electron 预加载脚本。
  • package.json:项目配置文件,包含 Electron 相关依赖和脚本。
  • .env 和 .env.electron:环境变量配置文件,分别用于普通模式和 Electron 模式。
  • vue.config.js:Vue CLI 的配置文件,用于优化构建和资源路径。
  • router.ts:Vue 路由配置文件,支持 hash 和 history 模式切换。

2. 代码详解

npm install electron electron-builder cross-env --save-dev

2.1 electron/main.js

主进程文件负责创建窗口并加载 Vue 应用:

const { app, BrowserWindow, globalShortcut, Menu } = require("electron");
const path = require("path");let mainWindow;// 捕获未处理的异常
process.on("uncaughtException", (error) => {console.error("Uncaught Exception:", error);
});process.on("unhandledRejection", (reason, promise) => {console.error("Unhandled Rejection at:", promise, "reason:", reason);
});function createWindow() {mainWindow = new BrowserWindow({width: 800,height: 600,icon: path.join(__dirname, "src", "assets", "logo_32.ico"),  // 设置窗口图标 尺寸:32*32images: true, // 启用图像支持show: false, // 初始时不显示窗口,避免闪烁// frame: false, // 隐藏默认的窗口边框和标题栏// fullscreen: true, // 启动时全屏webPreferences: {preload: path.join(__dirname, "preload.js"), // 预加载脚本(可选)nodeIntegration: true, // 启用 Node.js 集成(根据需要开启)// 添加以下配置解决媒体自动播放问题webSecurity: false, // 禁用同源策略(开发时可关闭,生产环境慎用)autoplayPolicy: "no-user-gesture-required", // 允许自动播放contextIsolation: false, // 必须为false才能访问全局变量},});// 加载 Vue 项目的生产构建文件if (process.env.NODE_ENV === "development") {mainWindow.loadURL("http://localhost:3000"); // 开发环境(Vue 开发服务器)} else {mainWindow.loadFile(path.join(__dirname, "../dist/index.html")); // 生产环境}// 窗口最大化mainWindow.maximize();// 显示窗口(在最大化后显示)mainWindow.show();// 隐藏菜单栏Menu.setApplicationMenu(null);// 打开开发者工具(开发时可以打开)// mainWindow.webContents.openDevTools();// 打开调试工具globalShortcut.register("CommandOrControl+Shift+I", () => {mainWindow.webContents.openDevTools();});// 切换全屏globalShortcut.register("CommandOrControl+Alt+Q", () => {if (mainWindow) {const isFullScreen = mainWindow.isFullScreen();mainWindow.setFullScreen(!isFullScreen);}});// 返回上一页globalShortcut.register("CommandOrControl+Left", () => {if (mainWindow) {const history = mainWindow.webContents.navigationHistory;if (history.canGoBack()) {history.goBack();}}});// 刷新页面globalShortcut.register("CommandOrControl+R", () => {if (mainWindow) {mainWindow.webContents.reload();}});mainWindow.on("closed", () => {mainWindow = null;});
}app.whenReady().then(() => {createWindow();// 创建自定义菜单// const menuTemplate = [//   {//     label: "操作",//     submenu: [//       { type: "separator" },//       { label: "切换全屏", role: "togglefullscreen" },//       { type: "separator" },//       {//         label: "返回上一页",//         accelerator: "CmdOrCtrl+Left",//         click: () => {//           if (mainWindow && mainWindow.webContents.canGoBack()) {//             mainWindow.webContents.goBack();//           }//         },//       },//     ],//   },// ];// // 根据模板创建菜单// const menu = Menu.buildFromTemplate(menuTemplate);// // 设置应用菜单// Menu.setApplicationMenu(menu);app.on("activate", () => {if (BrowserWindow.getAllWindows().length === 0) {createWindow();}});
});app.on("window-all-closed", () => {if (process.platform !== "darwin") {app.quit();}
});// 退出时注销快捷键
app.on("will-quit", () => {globalShortcut.unregisterAll();
});

2.2 electron/preload.js

const { contextBridge, ipcRenderer } = require('electron');contextBridge.exposeInMainWorld('electronAPI', {send: (channel, data) => ipcRenderer.send(channel, data),receive: (channel, func) => ipcRenderer.on(channel, (event, ...args) => func(...args)),
});

2.3 package.json

配置了 Electron 相关的脚本和依赖:

{"name": "saas_system","version": "0.1.35","private": true,"main": "electron/main.js","scripts": {"serve": "vue-cli-service serve","build": "vue-cli-service build","test:unit": "vue-cli-service test:unit","lint": "vue-cli-service lint","start": "electron .","build:electron": "vue-cli-service build --mode electron","electron:serve": "vue-cli-service serve --mode development && electron .","electron:build": "vue-cli-service build --mode electron && electron-builder"},"dependencies": {"electron": "^35.1.3","electron-builder": "^26.0.12"},"build": {"appId": "com.example.myapp","productName": "myapp","files": ["dist/**/*","electron/main.js","src/assets/logo.ico" // 尺寸:256*256],"win": {"target": "nsis","icon": "src/assets/logo.ico" // 尺寸:256*256},"mac": {"target": "dmg"},"linux": {"target": "AppImage"}}
}

2.4 .env 和 .env.electron

分别定义了普通模式和 Electron 模式的环境变量:
.env 文件

VUE_APP_ROUTER_MODE=history
VUE_APP_PUBLIC_PATH=/

.env.electron 文件

VUE_APP_ROUTER_MODE=hash
VUE_APP_PUBLIC_PATH=./

2.5 vue.config.js

动态生成资源路径前缀:

const productionGzipExtensions = ["js", "css"];module.exports = {publicPath: process.env.VUE_APP_PUBLIC_PATH || "/",configureWebpack: {devtool: "source-map",output: {filename: `${getAssetsPath()}js/[name].${Timestamp}.js`,chunkFilename: `${getAssetsPath()}js/[name].${Timestamp}.js`,},},css: {extract: {filename: `${getAssetsPath()}css/[name].${Timestamp}.css`,chunkFilename: `${getAssetsPath()}css/[name].${Timestamp}.css`,},},
};

2.6 router.ts

路由配置支持 hash 和 history 模式切换:

import { createRouter, createWebHashHistory, createWebHistory } from "vue-router";const router = createRouter({history: process.env.VUE_APP_ROUTER_MODE === 'hash'? createWebHashHistory(process.env.BASE_URL): createWebHistory(process.env.BASE_URL),routes,
});router.beforeResolve((to, from, next) => {const isFileProtocol = window.location.protocol === "file:";let token = localStorage.getItem("token");if (!token) {if (isFileProtocol) {next("./official_website?redirect=" + encodeURIComponent(to.path));} else {next("/official_website?redirect=" + encodeURIComponent(to.path));}} else {next();}
});

3. 打包流程

安装依赖:

npm install

启动开发模式:

npm run electron:serve

打包 Electron 应用:

npm run electron:build

生成的安装包会存放在 release 文件夹中。

4. 总结

通过上述步骤,您可以成功将 Vue3.2 项目打包为 Electron 桌面应用。Electron 提供了强大的跨平台能力,而 Vue 则让前端开发更加高效。希望本文对您有所帮助!

相关文章:

Vue3.2 项目打包成 Electron 桌面应用

本文将详细介绍如何将基于 Vue3.2 的项目打包成 Electron 桌面应用。通过结合 Electron 和 Vue CLI 工具链,可以轻松实现跨平台桌面应用的开发与发布。 1. 项目结构说明 项目主要分为以下几个部分: electron/main.js:Electron 主进程文件。…...

git stash pop 后反悔操作

当使用 git stash pop 应用并删除某个存储(stash)后,如果想撤销该操作(即恢复工作目录到 pop 前的状态,并重新将存储放回存储栈),可以按以下步骤操作: 1 强制丢弃所有未提交的更改&…...

Spring Boot 集成 MongoDB 时自动创建的核心 Bean 的详细说明及表格总结

以下是 Spring Boot 集成 MongoDB 时自动创建的核心 Bean 的详细说明及表格总结: 核心 Bean 列表及详细说明 1. MongoClient 类型:com.mongodb.client.MongoClient作用: MongoDB 客户端核心接口,负责与 MongoDB 服务器建立连接、…...

TypeScript面试题集合【初级、中级、高级】

初级面试题 什么是TypeScript? TypeScript是JavaScript的超集,由Microsoft开发,它添加了可选的静态类型和基于类的面向对象编程。TypeScript旨在解决JavaScript的某些局限性,比如缺乏静态类型和基于类的面向对象编程&#xff0c…...

ubuntu 20.04 编译和运行SC-LeGo-LOAM

1.搭建文件目录和clone代码 mkdir -p SC-LeGo-LOAM/src cd SC-LeGo-LOAM/src git clone https://github.com/AbangLZU/SC-LeGO-LOAM.git cd .. 2.修改代码 需要注意的是原作者使用的是Ouster OS-64雷达,需要更改utility.h文件中适配自己的雷达类型,而…...

CentOS 7安装hyperscan

0x00 前言 HyperScan是一款由Intel开发的高性能正则表达式匹配库,专为需要快速处理大量数据流的应用场景而设计。它支持多平台运行,包括Linux、Windows和macOS等操作系统,并针对x86架构进行了优化,以提供卓越的性能表现。HyperSc…...

Quartz MisFire补偿机制 任务补偿 任务延迟 错过触发策略

介绍 在 Quartz 中,MisFire(错过触发)是指触发器错过了预定的触发时间,通常是由于系统延迟、任务执行时间过长或者调度器本身未能及时执行任务等原因。这种情况可能会导致任务无法按预期的时间执行。为了应对这些问题&#xff0c…...

AI训练存储架构革命:存储选型白皮书与万卡集群实战解析

一、引言 在人工智能技术持续高速发展的当下,AI 训练任务对存储系统的依赖愈发关键,而存储系统的选型也变得更为复杂。不同的 AI 训练场景,如机器学习与大模型训练,在模型特性、GPU 使用数量以及数据量带宽等方面的差异&#xff…...

谢志辉和他的《韵之队诗集》:探寻生活与梦想交织的诗意世界

大家好,我是谢志辉,一个扎根在文字世界,默默耕耘的写作者。写作于我而言,早已不是简单的爱好,而是生命中不可或缺的一部分。无数个寂静的夜晚,当世界陷入沉睡,我独自坐在书桌前,伴着…...

UE5 Simulation Stage

首先将Grid2D创建出来,然后设置值,Grid2D类似于在Niagara系统中的RenderTarget2D,可以进行绘制,那么设置大小为512 * 512 开启Niagara粒子中的Simulation Stage 然后开始编写我们的自定义模块 模块很简单,TS就是Textur…...

Swift 解 LeetCode 250:搞懂同值子树,用递归写出权限系统检查器

文章目录 前言问题描述简单说:痛点分析:到底难在哪?1. 子树的概念搞不清楚2. 要不要“递归”?递归从哪开始?3. 怎么“边遍历边判断”?这套路不熟 后序遍历 全局计数器遍历过程解释一下:和实际场…...

怎样使用Python编写的Telegram聊天机器人

怎样使用Python编写的Telegram聊天机器人 代码直接运行可用 以下是对这段代码的详细解释: 1. 导入必要的库 import loggingfrom telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler, filters, MessageHandler import log…...

Elixir语言的移动应用安全

Elixir语言的移动应用安全解析 引言 在当今的数字化时代,移动应用已经成为我们日常生活中不可或缺的一部分。从购物、社交到在线银行,几乎每一个生活领域都与移动应用紧密相连。然而,随着应用的普及,安全问题也随之而来。如何确…...

动态估算gas和gasPrice

目录 一、什么是动态估算? 二、动态估算 Gas(代码示例) ✅ 使用 Ethers.js 估算 gasLimit: 💡 发送交易时加一点 buffer: 三、动态估算 gasPrice / maxFee ✅ 获取当前 baseFee(用 provider): ✅ 搭配交易一起发送: 四、完整组合:动态估算 Gas + EIP-1559 费用…...

数据清洗

map阶段&#xff1a;按行读入内容&#xff0c;对内容进行检查&#xff0c;如果字段的个数少于等于11&#xff0c;就删除这条日志&#xff08;不保留&#xff09;去除日志中字段个数小于等于11的日志内容。 <偏移量&#xff0c;第一行的内容> → <通过刷选之后的第一行…...

增益调度控制 —— 理论、案例与交互式 GUI 实现

目录 增益调度控制 —— 理论、案例与交互式 GUI 实现一、引言二、增益调度控制的基本原理三、数学模型与公式推导四、增益调度控制的优势与局限4.1 优势4.2 局限五、典型案例分析5.1 案例一:航空飞行控制中的增益调度5.2 案例二:发动机推力控制中的增益调度5.3 案例三:化工…...

关于OEC/OEC-turbo刷机问题的一些解决方法(2)——可能是终极解决方法了

前面写了两篇关于OEC/OEC-turbo刷机问题的文章了&#xff0c;从刷机过程、刷机中遇到的问题&#xff0c;以及遇到最多但始终无法有效解决的下载boot失败的问题的剖析&#xff0c;最近确实也做了一些工作&#xff0c;虽然没有最终解决&#xff0c;但也算是这系列文章里面阶段性的…...

前后端接口参数详解与 Mock 配置指南【大模型总结】

前后端接口参数详解与 Mock 配置指南 一、前端请求参数类型及 Mock 处理 1.1 URL 路径参数 (Path Parameters) 场景示例&#xff1a; GET /api/users/{userId}/orders/{orderId}Mock.js 处理&#xff1a; Mock.mock(/\/api\/users\/(\d)\/orders\/(\d)/, get, (options) &g…...

瓦片数据合并方法

影像数据 假如有两份影像数据 1.全球底层影像0-5级别如下&#xff1a; 2.局部高清影像数据级别9-14如下&#xff1a; 合并方法 将9-14文件夹复制到全球底层0-5的目录下 如下&#xff1a; 然后合并xml文件 使得Tileset设置到最高级&#xff08;包含所有级别&#xff09;&…...

第16届蓝桥杯单片机模拟试题Ⅰ

试题 代码 sys.h #ifndef __SYS_H__ #define __SYS_H__#include <STC15F2K60S2.H> //onewire.c float getT(); //sys.c extern unsigned char UI; extern bit touch_mode; extern float jiaozhun; extern float canshu; extern float temper; void init74hc138(unsigned…...

mac 卸载流氓软件安全助手

之前个人电脑在公司使用过一段时间&#xff0c;为了使用网线联网安装了公司指定的 联软上网助手&#xff0c;谁知安装容易卸载难&#xff0c;后来找运维来卸载&#xff0c;输入管理员密码后&#xff0c;也无反应&#xff0c;最后不了了之了&#xff0c;这个毒瘤软件长期在后台驻…...

EM算法到底是什么东东

EM&#xff08;Expectation-Maximization期望最大化&#xff09;算法是机器学习中非常重要的一类算法&#xff0c;广泛应用于聚类、缺失数据建模、隐变量模型学习等场景&#xff0c;比如高斯混合模型&#xff08;GMM&#xff09;就是经典应用。 &#x1f424; 第一步&#xff…...

⭐算法OJ⭐滑动窗口最大值【双端队列(deque)】Sliding Window Maximum

文章目录 双端队列(deque)详解基本特性常用操作1. 构造和初始化2. 元素访问3. 修改操作4. 容量操作 性能特点时间复杂度&#xff1a;空间复杂度&#xff1a; 滑动窗口最大值题目描述方法思路解决代码 双端队列(deque)详解 双端队列(deque&#xff0c;全称double-ended queue)是…...

oracle 快速创建表结构

在 Oracle 中快速创建表结构&#xff08;仅复制表结构&#xff0c;不复制数据&#xff09;可以通过以下方法实现&#xff0c;适用于需要快速复制表定义或生成空表的场景 1. 使用 CREATE TABLE AS SELECT (CTAS) 方法 -- 复制源表的全部列和数据类型&#xff0c;但不复制数据 C…...

沧州铁狮子

又名“镇海吼”&#xff0c;是中国现存年代最久、形体最大的铸铁狮子&#xff0c;具有深厚的历史文化底蕴和独特的艺术价值。以下是关于沧州铁狮子的详细介绍&#xff1a; 历史背景 • 铸造年代&#xff1a;沧州铁狮子铸造于后周广顺三年&#xff08;953年&#xff09;&#…...

Python•判断循环

ʕ⸝⸝⸝˙Ⱉ˙ʔ ♡ 判断🍰常用的判断符号(比较运算符)andor括号notin 和 not inif-elif-else循环🍭计数循环 forrange()函数简易倒计时enumerate()函数zip()函数遍历列表遍历元组遍历字符串遍历字典条件循环 while提前跳转 continue跳出循环 break能量站😚判断🍰 …...

【力扣hot100题】(060)分割回文串

每次需要判断回文串&#xff0c;这点比之前几题回溯题目复杂一些。 还有我怎么又多写了循环…… class Solution { public:vector<vector<string>> result;string s;bool palindromic(string s){for(int i0;i<s.size()/2;i) if(s[i]!s[s.size()-1-i]) return …...

C++---day7

#include <iostream> #include <cstring> #include <cstdlib> #include <unistd.h> #include <sstream> #include <vector> #include <memory>using namespace std;class Stu { private:public:};// 自定义 vector 类&#xff0c;重…...

SvelteKit 最新中文文档教程(17)—— 仅服务端模块和快照

前言 Svelte&#xff0c;一个语法简洁、入门容易&#xff0c;面向未来的前端框架。 从 Svelte 诞生之初&#xff0c;就备受开发者的喜爱&#xff0c;根据统计&#xff0c;从 2019 年到 2024 年&#xff0c;连续 6 年一直是开发者最感兴趣的前端框架 No.1&#xff1a; Svelte …...

C#后端开发培训教程

C#后端开发培训教程 SqlServer 1.创建数据、备份还原数据库 2.SqlServer:数据类型 3.Sql语句&#xff1a;增删改查 4.班级、学生数据结构示例 C#基础语法 C#基础语法、数据类型 C#数组、集合、类操作 C#面向对象基础 C# JSON 数据格式序列化 C# Linq 数据源操作基础语…...