Electron?+?Vue3桌面應(yīng)用開發(fā)實戰(zhàn)指南(含完整代碼)
前言
作為一名擁有 8 年前端開發(fā)經(jīng)驗的工程師,我深知從 Web 到桌面應(yīng)用開發(fā)的轉(zhuǎn)型痛點。Electron 框架雖然降低了跨平臺開發(fā)門檻,但實際項目中仍會遇到各種棘手問題。本文基于最新環(huán)境(Node.js v20.12.2、npm v9.8.1、Electron v29.1.1),結(jié)合實戰(zhàn)經(jīng)驗,從基礎(chǔ)搭建到生產(chǎn)部署,全方位講解 Electron+Vue3 開發(fā)要點。
一、Electron 原生開發(fā)核心流程
1. 項目初始化最佳實踐
npm init -y
關(guān)鍵注意點:
- package.json中的name字段必須是小寫字母 + 連字符組合(如my-electron-app),避免中文或特殊字符,否則后續(xù)打包可能出現(xiàn)莫名其妙的錯誤
- 初始化后立即設(shè)置"private": true,防止意外發(fā)布到 npm 倉庫
2. Electron 安裝與鏡像配置
國內(nèi)網(wǎng)絡(luò)環(huán)境下,直接安裝 Electron 極易失敗,推薦以下配置方案:
# 創(chuàng)建.npmrc文件(優(yōu)先級高于全局配置) cat > .npmrc << EOF electron_mirror=https://npmmirror.com/mirrors/electron/ electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/ registry=https://registry.npmmirror.com/ EOF # 安裝指定版本(鎖定版本號是項目穩(wěn)定的關(guān)鍵) npm install electron@29.1.1 --save-dev
驗證安裝:
npx electron --version # 成功輸出版本號即安裝正常
3. 核心文件編寫規(guī)范
index.html(渲染進(jìn)程)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- 內(nèi)容安全策略(開發(fā)環(huán)境配置) -->
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'">
<title>Electron基礎(chǔ)示例</title>
</head>
<body>
<h1>Hello Electron ??</h1>
<p>當(dāng)前版本: <span id="version"></span></p>
<script>
// 通過預(yù)加載腳本暴露的API獲取版本信息
document.getElementById('version').textContent = window.electronAPI.getVersion()
</script>
</body>
</html>preload.js(進(jìn)程通信橋梁)
// 嚴(yán)格的進(jìn)程間通信邊界是安全的關(guān)鍵
const { contextBridge } = require('electron/renderer')
// 只暴露必要的API,禁止直接暴露整個process對象
contextBridge.exposeInMainWorld('electronAPI', {
getVersion: () => process.versions.electron,
// 后續(xù)可添加更多通信方法
// showDialog: (message) => ipcRenderer.invoke('show-dialog', message)
})
main.js(主進(jìn)程)
const { app, BrowserWindow } = require('electron/main')
const { join } = require('path')
let mainWindow = null
const createWindow = () => {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// 預(yù)加載腳本路徑
preload: join(__dirname, 'preload.js'),
// 安全配置
contextIsolation: true, // 必須開啟上下文隔離
nodeIntegration: false, // 禁止渲染進(jìn)程直接訪問Node.js
enableRemoteModule: false, // 已廢棄的API,確保關(guān)閉
sandbox: false // 生產(chǎn)環(huán)境可考慮開啟沙箱
}
})
// 加載頁面
mainWindow.loadFile(join(__dirname, 'index.html'))
// 開發(fā)環(huán)境自動打開調(diào)試工具
if (process.env.NODE_ENV === 'development') {
mainWindow.webContents.openDevTools({ mode: 'detach' })
}
// 窗口關(guān)閉時清理資源
mainWindow.on('closed', () => {
mainWindow = null
})
}
// 應(yīng)用生命周期管理
app.whenReady().then(() => {
createWindow()
// macOS特殊處理
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
// 所有窗口關(guān)閉時退出應(yīng)用(macOS除外)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
4. 開發(fā)命令配置
{
"scripts": {
"dev": "cross-env NODE_ENV=development electron .",
"start": "npm run dev"
},
"devDependencies": {
"cross-env": "^7.0.3", // 跨平臺設(shè)置環(huán)境變量
"electron": "^29.1.1"
}
}安裝 cross-env:npm install cross-env --save-dev
二、Vue3 + Electron 高效開發(fā)方案
對于中大型項目,推薦使用 electron-vite 框架,它完美整合了 Vite 的熱更新能力和 Electron 的桌面特性。
1. 項目創(chuàng)建與配置
# 推薦使用pnpm(速度更快,依賴管理更嚴(yán)格) npm install -g pnpm pnpm create @quick-start/electron@latest
交互選項建議:
- Project name: 用小寫英文 + 連字符(如vue-electron-app)
- Select a framework: vue
- Add TypeScript? Yes(長期項目強(qiáng)烈建議使用 TS)
- Add Electron updater plugin? Yes(提前集成自動更新)
- Enable Electron download mirror proxy? Yes(國內(nèi)加速)
2. 項目結(jié)構(gòu)深度解析
vue-electron-app/ ├── electron/ # 主進(jìn)程代碼(Node環(huán)境) │ ├── main/ # 主進(jìn)程核心邏輯 │ │ └── index.js # 主進(jìn)程入口 │ └── preload/ # 預(yù)加載腳本 │ └── index.js # 預(yù)加載入口 ├── src/ # 渲染進(jìn)程代碼(Vue環(huán)境) │ ├── components/ # Vue組件 │ ├── App.vue # 根組件 │ └── main.js # Vue入口 ├── electron.vite.config.js # 構(gòu)建配置(核心文件) └── package.json # 項目配置
3. 熱更新優(yōu)化配置
electron-vite 已內(nèi)置熱更新,通過electron.vite.config.js可進(jìn)一步優(yōu)化:
import { defineConfig } from 'electron-vite'
import vue from '@vitejs/plugin-vue'
import { join } from 'path'
export default defineConfig({
main: {
build: {
outDir: 'dist-electron/main'
}
},
preload: {
build: {
outDir: 'dist-electron/preload'
}
},
renderer: {
// 集成Vue插件
plugins: [vue()],
// 開發(fā)服務(wù)器配置
server: {
port: 5173,
strictPort: true, // 端口被占用時不自動切換
open: false // 不自動打開瀏覽器
},
build: {
outDir: 'dist-renderer',
// 靜態(tài)資源處理
assetsDir: 'assets',
rollupOptions: {
input: join(__dirname, 'src/index.html')
}
}
}
})
4. 圖標(biāo)配置全平臺方案
不同操作系統(tǒng)對圖標(biāo)有不同要求,推薦方案:
// electron/main/index.js
import { BrowserWindow, nativeImage } from 'electron'
import { join } from 'path'
const getIconPath = () => {
// 根據(jù)系統(tǒng)返回不同圖標(biāo)
switch (process.platform) {
case 'win32':
return join(__dirname, '../../resources/icons/win/icon.ico')
case 'darwin':
return join(__dirname, '../../resources/icons/mac/icon.icns')
default:
return join(__dirname, '../../resources/icons/linux/icon.png')
}
}
const createWindow = () => {
const mainWindow = new BrowserWindow({
icon: nativeImage.createFromPath(getIconPath()),
// 其他配置...
})
}
圖標(biāo)規(guī)范:
- Windows: .ico格式,至少包含 256x256 像素
- macOS: .icns格式,建議包含 1024x1024 像素
- Linux: .png格式,512x512 像素
5. 系統(tǒng)托盤高級實現(xiàn)
// electron/main/index.js
import { Tray, Menu, nativeImage, app, BrowserWindow } from 'electron'
import { join } from 'path'
let tray = null
let mainWindow = null
const createTray = () => {
// 創(chuàng)建托盤圖標(biāo)
const icon = nativeImage.createFromPath(join(__dirname, '../../resources/icons/tray.ico'))
.resize({ width: 16, height: 16 }) // 托盤圖標(biāo)通常較小
tray = new Tray(icon)
// 托盤菜單模板
const contextMenu = Menu.buildFromTemplate([
{
label: '顯示窗口',
click: () => {
mainWindow.show()
mainWindow.setSkipTaskbar(false) // 從任務(wù)欄顯示
}
},
{
label: '隱藏窗口',
click: () => {
mainWindow.hide()
mainWindow.setSkipTaskbar(true) // 從任務(wù)欄隱藏
}
},
{ type: 'separator' }, // 分隔線
{
label: '退出',
click: () => {
// 確保完全退出應(yīng)用
mainWindow.destroy()
app.quit()
}
}
])
tray.setContextMenu(contextMenu)
tray.setToolTip('Electron Vue應(yīng)用')
// 雙擊托盤切換窗口顯示狀態(tài)
tray.on('double-click', () => {
if (mainWindow.isVisible()) {
mainWindow.hide()
} else {
mainWindow.show()
}
})
}
// 在窗口創(chuàng)建后初始化托盤
app.whenReady().then(() => {
mainWindow = new BrowserWindow(/* 配置 */)
createTray()
})
三、打包與自動更新全流程
1. 打包環(huán)境準(zhǔn)備
# 安裝打包工具 pnpm add electron-builder --save-dev # 若使用原生模塊(如C++擴(kuò)展) pnpm add electron-rebuild --save-dev
2. 打包配置詳解
在package.json中添加:
{
"build": {
"appId": "com.yourcompany.yourapp", // 反向域名格式,唯一標(biāo)識
"productName": "你的應(yīng)用名稱",
"copyright": "Copyright ? 2024 ${author}",
"asar": true, // 啟用asar打包(保護(hù)源碼)
"directories": {
"output": "release/${version}", // 輸出到版本化目錄
"buildResources": "resources" // 構(gòu)建資源目錄
},
"files": [
"dist-electron/**/*",
"dist-renderer/**/*"
],
"win": {
"icon": "resources/icons/win/icon.ico",
"target": [
{
"target": "nsis",
"arch": ["x64", "ia32"] // 支持32位和64位
}
],
"artifactName": "${productName}-v${version}-${arch}-setup.${ext}"
},
"nsis": {
"oneClick": false, // 不啟用一鍵安裝
"allowToChangeInstallationDirectory": true,
"installerIcon": "resources/icons/win/installer.ico",
"uninstallerIcon": "resources/icons/win/uninstaller.ico",
"installerHeaderIcon": "resources/icons/win/installer.ico",
"createDesktopShortcut": true,
"shortcutName": "${productName}"
},
"mac": {
"icon": "resources/icons/mac/icon.icns",
"target": ["dmg", "zip"],
"artifactName": "${productName}-v${version}-${arch}.${ext}"
},
"linux": {
"icon": "resources/icons/linux",
"target": ["AppImage", "deb"],
"artifactName": "${productName}-v${version}-${arch}.${ext}"
}
},
"scripts": {
"build": "electron-vite build && electron-builder",
"build:win": "electron-vite build && electron-builder --win",
"build:mac": "electron-vite build && electron-builder --mac",
"build:linux": "electron-vite build && electron-builder --linux"
}
}3. 原生模塊處理(C++ 庫)
如果項目依賴 C++ 擴(kuò)展(如 serialport、sqlite3 等),必須重新編譯:
# 編譯命令(Windows使用cmd執(zhí)行)
./node_modules/.bin/electron-rebuild
# 或在package.json中添加腳本
"scripts": {
"rebuild": "electron-rebuild"
}
# 執(zhí)行:npm run rebuild常見問題:
- 編譯失敗通常是因為缺少 C++ 編譯工具鏈,Windows 需安裝 Visual Studio Build Tools
- macOS 需要安裝 Xcode Command Line Tools: xcode-select --install
- Linux 需要安裝 build-essential: sudo apt-get install build-essential
4. 自動更新完整實現(xiàn)
1)安裝依賴
pnpm add electron-updater
2)主進(jìn)程更新邏輯
// electron/main/index.js
import { app, dialog, BrowserWindow } from 'electron'
import { autoUpdater } from 'electron-updater'
import log from 'electron-log'
// 配置日志
log.transports.file.level = 'info'
autoUpdater.logger = log
let mainWindow = null
// 初始化更新檢查
const initUpdater = () => {
// 生產(chǎn)環(huán)境才啟用自動更新
if (!app.isPackaged) {
// 開發(fā)環(huán)境可指定測試更新服務(wù)器
autoUpdater.setFeedURL({
provider: 'generic',
url: 'http://localhost:3000/updates/'
})
}
// 檢查更新
autoUpdater.checkForUpdates().catch(err => {
log.error('更新檢查失敗:', err)
})
// 發(fā)現(xiàn)新版本
autoUpdater.on('update-available', (info) => {
dialog.showMessageBox(mainWindow, {
type: 'info',
title: '發(fā)現(xiàn)新版本',
message: `新版本 ${info.version} 已發(fā)布,是否下載更新?`,
buttons: ['立即下載', '稍后再說']
}).then(res => {
if (res.response === 0) {
// 用戶選擇下載
mainWindow.webContents.send('update-start')
}
})
})
// 下載進(jìn)度
autoUpdater.on('download-progress', (progress) => {
mainWindow.webContents.send('update-progress', {
percent: Math.round(progress.percent),
speed: Math.round(progress.bytesPerSecond / 1024) // KB/s
})
})
// 下載完成
autoUpdater.on('update-downloaded', () => {
dialog.showMessageBox(mainWindow, {
type: 'info',
title: '更新就緒',
message: '更新已下載完成,是否立即重啟應(yīng)用?',
buttons: ['立即重啟', '稍后重啟']
}).then(res => {
if (res.response === 0) {
autoUpdater.quitAndInstall()
}
})
})
}
// 在應(yīng)用就緒后初始化
app.whenReady().then(() => {
mainWindow = new BrowserWindow(/* 配置 */)
// 延遲檢查更新,避免影響啟動速度
setTimeout(initUpdater, 5000)
})
3)更新服務(wù)器配置
- 在package.json中配置更新服務(wù)器地址:
"build": {
"publish": [
{
"provider": "generic",
"url": "https://your-server.com/updates/"
}
]
}- 本地測試更新服務(wù)器:
# 安裝靜態(tài)服務(wù)器 pnpm add -g serve # 在打包輸出目錄啟動服務(wù)器 serve -s release/</doubaocanvas>
總結(jié)
到此這篇關(guān)于Electron+Vue3桌面應(yīng)用開發(fā)實戰(zhàn)指南的文章就介紹到這了,更多相關(guān)Electron Vue3桌面應(yīng)用開發(fā)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue3 reactive 請求接口數(shù)據(jù)賦值后拿不到的問題及解決方案
這篇文章主要介紹了vue3 reactive 請求接口數(shù)據(jù)賦值后拿不到的問題及解決方案,本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04
vue?+?element-plus自定義表單驗證(修改密碼業(yè)務(wù))的示例
這篇文章主要介紹了vue?+?element-plus自定義表單驗證(修改密碼業(yè)務(wù)),本文通過實例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2025-04-04
vue導(dǎo)入新工程?“node_modules依賴”問題
這篇文章主要介紹了vue導(dǎo)入新工程?“node_modules依賴”問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
在 Vue 應(yīng)用中使用 Netlify 表單功能的方法詳解
Netlify 帶有內(nèi)置表單處理功能,可以用來存儲表單數(shù)據(jù),下載 csv 文件,同時可以在接收到新的提交時發(fā)送郵件通知或者通過配置 webhook 發(fā)送請求。這篇文章主要介紹了在 Vue 應(yīng)用中使用 Netlify 表單功能,需要的朋友可以參考下2019-06-06
npm install -g @vue/cli安裝vue腳手架報錯問題(一般都能解決)
這篇文章主要介紹了npm install -g @vue/cli安裝vue腳手架報錯問題(一般都能解決),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10

