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的某些局限性,比如缺乏静态类型和基于类的面向对象编程,…...
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(错过触发)是指触发器错过了预定的触发时间,通常是由于系统延迟、任务执行时间过长或者调度器本身未能及时执行任务等原因。这种情况可能会导致任务无法按预期的时间执行。为了应对这些问题,…...
AI训练存储架构革命:存储选型白皮书与万卡集群实战解析
一、引言 在人工智能技术持续高速发展的当下,AI 训练任务对存储系统的依赖愈发关键,而存储系统的选型也变得更为复杂。不同的 AI 训练场景,如机器学习与大模型训练,在模型特性、GPU 使用数量以及数据量带宽等方面的差异ÿ…...
谢志辉和他的《韵之队诗集》:探寻生活与梦想交织的诗意世界
大家好,我是谢志辉,一个扎根在文字世界,默默耕耘的写作者。写作于我而言,早已不是简单的爱好,而是生命中不可或缺的一部分。无数个寂静的夜晚,当世界陷入沉睡,我独自坐在书桌前,伴着…...
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阶段:按行读入内容,对内容进行检查,如果字段的个数少于等于11,就删除这条日志(不保留)去除日志中字段个数小于等于11的日志内容。 <偏移量,第一行的内容> → <通过刷选之后的第一行…...
增益调度控制 —— 理论、案例与交互式 GUI 实现
目录 增益调度控制 —— 理论、案例与交互式 GUI 实现一、引言二、增益调度控制的基本原理三、数学模型与公式推导四、增益调度控制的优势与局限4.1 优势4.2 局限五、典型案例分析5.1 案例一:航空飞行控制中的增益调度5.2 案例二:发动机推力控制中的增益调度5.3 案例三:化工…...
关于OEC/OEC-turbo刷机问题的一些解决方法(2)——可能是终极解决方法了
前面写了两篇关于OEC/OEC-turbo刷机问题的文章了,从刷机过程、刷机中遇到的问题,以及遇到最多但始终无法有效解决的下载boot失败的问题的剖析,最近确实也做了一些工作,虽然没有最终解决,但也算是这系列文章里面阶段性的…...
前后端接口参数详解与 Mock 配置指南【大模型总结】
前后端接口参数详解与 Mock 配置指南 一、前端请求参数类型及 Mock 处理 1.1 URL 路径参数 (Path Parameters) 场景示例: GET /api/users/{userId}/orders/{orderId}Mock.js 处理: Mock.mock(/\/api\/users\/(\d)\/orders\/(\d)/, get, (options) &g…...
瓦片数据合并方法
影像数据 假如有两份影像数据 1.全球底层影像0-5级别如下: 2.局部高清影像数据级别9-14如下: 合并方法 将9-14文件夹复制到全球底层0-5的目录下 如下: 然后合并xml文件 使得Tileset设置到最高级(包含所有级别)&…...
第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 卸载流氓软件安全助手
之前个人电脑在公司使用过一段时间,为了使用网线联网安装了公司指定的 联软上网助手,谁知安装容易卸载难,后来找运维来卸载,输入管理员密码后,也无反应,最后不了了之了,这个毒瘤软件长期在后台驻…...
EM算法到底是什么东东
EM(Expectation-Maximization期望最大化)算法是机器学习中非常重要的一类算法,广泛应用于聚类、缺失数据建模、隐变量模型学习等场景,比如高斯混合模型(GMM)就是经典应用。 🐤 第一步ÿ…...
⭐算法OJ⭐滑动窗口最大值【双端队列(deque)】Sliding Window Maximum
文章目录 双端队列(deque)详解基本特性常用操作1. 构造和初始化2. 元素访问3. 修改操作4. 容量操作 性能特点时间复杂度:空间复杂度: 滑动窗口最大值题目描述方法思路解决代码 双端队列(deque)详解 双端队列(deque,全称double-ended queue)是…...
oracle 快速创建表结构
在 Oracle 中快速创建表结构(仅复制表结构,不复制数据)可以通过以下方法实现,适用于需要快速复制表定义或生成空表的场景 1. 使用 CREATE TABLE AS SELECT (CTAS) 方法 -- 复制源表的全部列和数据类型,但不复制数据 C…...
沧州铁狮子
又名“镇海吼”,是中国现存年代最久、形体最大的铸铁狮子,具有深厚的历史文化底蕴和独特的艺术价值。以下是关于沧州铁狮子的详细介绍: 历史背景 • 铸造年代:沧州铁狮子铸造于后周广顺三年(953年)&#…...
Python•判断循环
ʕ⸝⸝⸝˙Ⱉ˙ʔ ♡ 判断🍰常用的判断符号(比较运算符)andor括号notin 和 not inif-elif-else循环🍭计数循环 forrange()函数简易倒计时enumerate()函数zip()函数遍历列表遍历元组遍历字符串遍历字典条件循环 while提前跳转 continue跳出循环 break能量站😚判断🍰 …...
【力扣hot100题】(060)分割回文串
每次需要判断回文串,这点比之前几题回溯题目复杂一些。 还有我怎么又多写了循环…… 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 类,重…...
SvelteKit 最新中文文档教程(17)—— 仅服务端模块和快照
前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte …...
C#后端开发培训教程
C#后端开发培训教程 SqlServer 1.创建数据、备份还原数据库 2.SqlServer:数据类型 3.Sql语句:增删改查 4.班级、学生数据结构示例 C#基础语法 C#基础语法、数据类型 C#数组、集合、类操作 C#面向对象基础 C# JSON 数据格式序列化 C# Linq 数据源操作基础语…...
