基于electron+vue3+ts搭建桌面端應(yīng)用并且可以熱更新
技術(shù)
字體加黑的是必要的技術(shù),其他的庫(kù)是可以自由選擇的
- electron 13.0.0
- vue3 + ts
- electron-updater
- node 16.13.1
- element-plus
- less
- meansjs
搭建vue3項(xiàng)目
安裝vue-cli
如果有沒有安裝的話就全局安裝
npm install -g @vue/cli
創(chuàng)建vue3項(xiàng)目
跟vue2創(chuàng)建項(xiàng)目差不多,需要配置什么自己去選擇,這兒我選擇的是ts開發(fā)
vue create electron-vue3
啟動(dòng)項(xiàng)目:
yarn serve
啟動(dòng)成功以后,開始安裝electron;
安裝Electron
在此安裝的時(shí)候會(huì)叫你選擇版本,你根據(jù)自己的要求選擇就可(我的是13.0.0)
安裝依賴:
vue add electron-builder
啟動(dòng)項(xiàng)目:
yarn electron:serve
在以上的安裝過程中,electron的版本只能是11、12、13;如果你想要更高版本electron的可以在此安裝一下electron,這樣將會(huì)更新到最新版本的electron(注:2023-6-2更新)
yarn add --dev electron // or
npm install --save-dev electron // or
pnpm add --save-dev electron // or
我們?cè)趩?dòng)的時(shí)候會(huì)報(bào)錯(cuò)如下圖:


解決方案:
安裝:
yarn add ts-loader@8.2.0
找到background.ts文件,將e修改
try {
await installExtension(VUEJS3_DEVTOOLS)
} catch (e:any) {
console.error('Vue Devtools failed to install:', e.toString())
}然后再次啟動(dòng)即可,在啟動(dòng)的過程中有點(diǎn)慢,需要耐心等待;后續(xù)我會(huì)說怎么解決
background.ts文件修改
創(chuàng)建主進(jìn)程文件
在src隨意位置創(chuàng)建一個(gè)host文件,可以在common文件中隨意封裝很多文件然后再host/index.ts文件中引入使用即可
// src/host/index.ts
import { ipcMain} from 'electron';
export default (win:any)=>{
// 窗口最小化
ipcMain.on("window-minimize", function () {
// 收到渲染進(jìn)程的窗口最小化操作的通知,并調(diào)用窗口最小化函數(shù),執(zhí)行該操作
win.minimize();
});
// 窗口最大化
ipcMain.on("window-maximize", function () {
if (win.isMaximized()) {
win.restore();
} else {
win.maximize();
}
});
// 關(guān)閉窗口
ipcMain.on("window-close", function () {
win.hide();
win.close();
});
}修改background.ts
由于太多了,不好描述我就直接貼上代碼了,代碼中有注釋大家也可以查看;還有就是我們?cè)谏厦嬲f到的,項(xiàng)目啟動(dòng)很慢的問題,在這而也是得到了解決的;
大致講解
- hout/index文件是一個(gè)主進(jìn)程接收發(fā)送文件
- await installExtension(VUEJS3_DEVTOOLS)替換成session.defaultSession.loadExtension( path.resolve(__dirname, "../devTools/chrome"));會(huì)提高啟動(dòng)速度,至于為什么請(qǐng)自行百度
- 其他的new BrowserWindow參數(shù)做了一些調(diào)整,就沒怎么修改了;好理解
'use strict'
import { app, protocol, BrowserWindow,session } from 'electron';
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib';
// import installExtension, { VUEJS3_DEVTOOLS } from 'electron-devtools-installer'; // 會(huì)導(dǎo)致啟動(dòng)的時(shí)候很慢,所以不用
const isDevelopment = process.env.NODE_ENV !== 'production';
const path = require("path");
import host from '@/host/index';
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
]);
let win:any;
async function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 1000,
height: 600,
minWidth: 800,
minHeight: 600,
// 不要邊框
frame: true,
webPreferences: {
webviewTag: true,
// 禁止同源策略,避免 axios 無法使用
webSecurity: false,
// Required for Spectron testing
enableRemoteModule: !!process.env.IS_TEST,
nodeIntegration: true,
contextIsolation: false
}
})
// 主進(jìn)程
host(win);
// 開發(fā)環(huán)境
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL as string)
if (!process.env.IS_TEST) win.webContents.openDevTools() // 打開控制臺(tái)
} else {
// 生產(chǎn)環(huán)境
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://./index.html')
}
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
// await installExtension(VUEJS3_DEVTOOLS) // 會(huì)導(dǎo)致啟動(dòng)的時(shí)候很慢
session.defaultSession.loadExtension( path.resolve(__dirname, "../devTools/chrome"));
} catch (e:any) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow();
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}當(dāng)你做到這兒的時(shí)候,你的啟動(dòng)速度會(huì)賊快
然后我們開始配置vue.config.js;打包的時(shí)候需要的
vue.config.js
這里的配置文件我是根據(jù)初始化項(xiàng)目來進(jìn)行配置的,如果你的項(xiàng)目沒有去修改初始文件的名稱的話;可將以下代碼復(fù)制進(jìn)去即可。代碼中我都寫了注釋的,大家需要修改什么地方自己更改就好
注意的地方(重點(diǎn)):
- appId
- icon
- guid
- include
1、appId/guid需保持一致;
2、include重點(diǎn)中的重點(diǎn),如果你需要熱更新的話;這個(gè)文件一定要配置,不然你在卸載/更新后安裝軟件安裝不上;主要原因注冊(cè)機(jī)的問題。這個(gè)文件最有一句代碼也是要和appId一致的;
const { defineConfig } = require('@vue/cli-service');
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false, // 引入插件不使用時(shí)不報(bào)報(bào)錯(cuò)
configureWebpack: {
externals: {
'electron': 'require("electron")'
},
},
// 第三方插件配置
pluginOptions: {
// vue-cli-plugin-electron-builder 配置
electronBuilder: {
nodeIntegration: true,
// 設(shè)置應(yīng)用主進(jìn)程的入口
mainProcessFile: "src/background.ts",
// 設(shè)置應(yīng)用渲染進(jìn)程的入口
rendererProcessFile: "src/main.ts",
customFileProtocol: "../",
// 打包選項(xiàng)
builderOptions: {
// 解決的問題:在安裝到電腦后,系統(tǒng)通知無法工作
appId: "com.zhuhong.vue3", // 軟件id
productName: "JSON工具", // 打包后的名稱
// windows系統(tǒng)相關(guān)配置
win: {
// 應(yīng)用圖標(biāo)路徑(Windows 系統(tǒng)中 icon 需要 256 * 256 的 ico 格式圖片)
icon: "./src/assets/login-icon.png",
target: {
target: "nsis",
// 支持 64 位的 Windows 系統(tǒng)
arch: ["x64"],
},
},
nsis: {
// 如果為false,想要給電腦所有用戶安裝必須使用管理員權(quán)限
allowElevation: true,
// 是否一鍵安裝
oneClick: false,
// 允許修改安裝目錄
allowToChangeInstallationDirectory: true,
"guid": "com.zhuhong.vue3", // 軟件id
"include": "./installer.nsh"
},
},
},
},
})根目錄創(chuàng)建installer.nsh文件
!macro customInit
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\com.zhuhong.vue3"
!macroend
打包:
yarn electron:build
如果配置到這兒打包沒得問題,那么你的項(xiàng)目基本上就行了;

最后呢?就是熱更新了;需要的可以繼續(xù)往下看
熱更新
安裝
yarn add electron-updater
新建JSPatch文件
注意:
- autoUpdater.setFeedURL一定要寫在外面,不然打包的時(shí)候會(huì)報(bào)錯(cuò)
- url: process.env.VUE_APP_HOT_UPDATE, 不能這樣使用;否則打包也會(huì)報(bào)錯(cuò)
- url鏈接地址事你存放打包文件的地址
- 需要將此文件引入background.ts文件中
- 必須在app.on('ready', 函數(shù)中引用
// src/host/common/JSPatch.ts
import { ipcMain } from "electron";
const { autoUpdater } = require("electron-updater");
autoUpdater.autoDownload = false; // 是否自動(dòng)更新
autoUpdater.autoInstallOnAppQuit = true // APP退出的時(shí)候自動(dòng)安裝
/*
* 在開啟更新監(jiān)聽事件之前設(shè)置
* 一定要保證該地址下面包含lasted.yml文件和需要更新的exe文件
*/
autoUpdater.setFeedURL({
provider: 'generic',
url: 'https://', // 打包文件存放地址
});
export default (win:any)=>{
// 發(fā)送消息給渲染線程
function sendStatusToWindow(status?:any, params?:any) {
win.webContents.send(status, params);
}
autoUpdater.on('checking-for-update', () => {
sendStatusToWindow('Checking for update...');
})
autoUpdater.on('update-available', (info:any) => {
// 可以更新版本
sendStatusToWindow('autoUpdater-canUpdate', info)
})
autoUpdater.on('error', (err:any) => {
// 更新錯(cuò)誤
sendStatusToWindow('autoUpdater-error', err)
})
// 發(fā)起更新程序
ipcMain.on('autoUpdater-toDownload', () => {
autoUpdater.downloadUpdate()
})
autoUpdater.on('download-progress', (progressObj:any) => {
// 正在下載的下載進(jìn)度
sendStatusToWindow('autoUpdater-progress', progressObj)
})
autoUpdater.on('update-downloaded', () => {
// 下載完成
sendStatusToWindow('autoUpdater-downloaded')
})
// 退出程序
ipcMain.on('exit-app', () => {
autoUpdater.quitAndInstall()
})
// 重新檢查是否有新版本更新
ipcMain.on('monitor-update-system',()=>{
autoUpdater.checkForUpdates()
})
// 檢測(cè)是否有更新
setTimeout(() => {
autoUpdater.checkForUpdates();
}, 5000);
}新建一個(gè)組件或者在app.vue中使用也可以jspatch
<template>
<div class="jspatch">
<el-dialog
title="JSON工具更新中......"
v-model="showUpdater"
:close-on-click-modal="false"
:close-on-press-escape="true"
:show-close="false"
width="40%"
top="26vh"
center
>
<template v-if="downloadProcess">
<p> {{`當(dāng)前:【${downloadProcess.transferred}】 / 共【${downloadProcess.total}】`}}</p>
<el-progress
:text-inside="true"
:stroke-width="18"
status="warning"
:percentage="downloadProcess.percent"
></el-progress>
<p>正在下載({{ downloadProcess.speed }})......</p>
</template>
</el-dialog>
</div>
</template>
<script lang='ts'>
import { defineComponent, reactive, toRefs } from "vue";
import { ipcRenderer } from "electron";
import { ElMessage ,ElMessageBox } from 'element-plus';
export default defineComponent({
name: "Jspatch",
setup(props: any, { emit }: { emit: any }) {
const data = reactive({
showUpdater: false,
downloadProcess: {
percent: 10,
speed: 0,
transferred:'1kb',
total:"2M"
},
});
// 發(fā)現(xiàn)新版本 once
ipcRenderer.on("autoUpdater-canUpdate", (event, info) => {
/*
* 這兒會(huì)監(jiān)聽,如果info.version比現(xiàn)在版本??;就會(huì)觸發(fā);反之,不會(huì)觸發(fā)
*/
ElMessageBox.confirm(`發(fā)現(xiàn)有新版本【v${info.version}】,是否更新?`, "提示", {
confirmButtonText: "確定",
cancelButtonText: "取消",
closeOnClickModal: false,
type: "warning",
}).then(() => {
ipcRenderer.send("autoUpdater-toDownload");
});
});
// 下載進(jìn)度
ipcRenderer.on("autoUpdater-progress", (event, process) => {
if (process.transferred >= 1024 * 1024) {
process.transferred =
(process.transferred / 1024 / 1024).toFixed(2) + "M";
} else {
process.transferred = (process.transferred / 1024).toFixed(2) + "K";
}
if (process.total >= 1024 * 1024) {
process.total = (process.total / 1024 / 1024).toFixed(2) + "M";
} else {
process.total = (process.total / 1024).toFixed(2) + "K";
}
if (process.bytesPerSecond >= 1024 * 1024) {
process.speed =
(process.bytesPerSecond / 1024 / 1024).toFixed(2) + "M/s";
} else if (process.bytesPerSecond >= 1024) {
process.speed = (process.bytesPerSecond / 1024).toFixed(2) + "K/s";
} else {
process.speed = process.bytesPerSecond + "B/s";
}
process.percent = process.percent.toFixed(2);
data.downloadProcess = process;
data.showUpdater = true;
});
// 下載更新失敗
ipcRenderer.once("autoUpdater-error", () => {
ElMessage.error("更新失??!");
data.showUpdater = false;
});
// 下載完成
ipcRenderer.once("autoUpdater-downloaded", () => {
data.showUpdater = false;
ElMessageBox.confirm(`更新完成,是否關(guān)閉應(yīng)用程序安裝新版本?`, "提示", {
confirmButtonText: "確定",
cancelButtonText: "取消",
closeOnClickModal: false,
type: "warning",
}).then(() => {
ipcRenderer.send("exit-app");
});
});
return {
...toRefs(data),
};
},
});
</script>
<style scoped lang='less'>
.jspatch {
/deep/ .el-dialog__header {
font-weight: 700;
.el-dialog__title {
color: #00adb5;
}
}
}
</style>最后修改一哈vue.config.js就完成了
將以下代碼復(fù)制到vue.config.js的builderOptions對(duì)象中即可
publish: [
{
provider: "generic",
url: 'https:', // 打包文件地址,與以上鏈接需相同
},
],然后再次打包安裝測(cè)試;沒有問題就可以上線了
也可以查看線上代碼
下載依賴問題
如果你在下載依賴很慢的情況下,在.npmrc文件中配置以下文件,基本上配置了都能下載成功。
registry=https://registry.npmmirror.com electron_mirror=https://cdn.npmmirror.com/binaries/electron/ electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
以上就是基于electron+vue3+ts搭建桌面端應(yīng)用并且可以熱更新的詳細(xì)內(nèi)容,更多關(guān)于electron+vue3+ts搭建桌面應(yīng)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue+SpringBoot實(shí)現(xiàn)支付寶沙箱支付的示例代碼
本文主要介紹了Vue+SpringBoot實(shí)現(xiàn)支付寶沙箱支付的示例代碼,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-06-06

