Vue集成Electron
本文章对小满zs,满哥之前发过Vue3 Vite electron 开发桌面程序,进行修改完成适配,桀桀桀
添加依赖
bash
# 一定要安装成开发依赖
npm install electron electron-builder -D
开发环境启动electron
我们希望npm run dev的时候直接把electron也启动起来而不是开两个启动一次vite再启动一次electron
第一步我们需要先建立一个文件夹
在根目录创建一个plugins
编写vite插件帮我们启动electron
- plugins
- vite.electron.dev.ts //编写electron开发模式
- vite.electron.build.ts//打包electron项目
- index.html
- src
- main.ts
- App.vue
- background.ts //手动创建文件用于编写electron
- package.json
- tsconfig.json
- vite.config.ts
background.ts
ts
import { app, BrowserWindow } from 'electron'
import { fileURLToPath } from 'url'
import { dirname, join } from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
// 设置应用安全策略
app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors')
let mainWindow: BrowserWindow | null = null
const createWindow = async () => {
console.log('🚀 正在创建 Electron 窗口...')
// 创建浏览器窗口
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
show: true, // 立即显示窗口以便调试
autoHideMenuBar: true, // 隐藏菜单栏
icon: join(__dirname, '../public/vite.svg'), // 应用图标
webPreferences: {
nodeIntegration: false, // 禁用Node.js集成(安全)
contextIsolation: true, // 启用上下文隔离(安全)
webSecurity: true, // 启用web安全策略
sandbox: false, // 如果需要预加载脚本,设为false
}
})
console.log('✅ Electron 窗口已创建')
// 根据环境加载不同的内容
const isDev = process.argv[2]
console.log('🔗 开发环境URL:', isDev)
if (isDev) {
// 开发环境:加载开发服务器
console.log('🌐 正在加载开发服务器:', isDev)
await mainWindow.loadURL(isDev)
// 开发环境下打开开发者工具
mainWindow.webContents.openDevTools()
console.log('✅ 已加载开发服务器并打开开发者工具')
} else {
// 生产环境:加载构建后的文件
const indexPath = join(__dirname, '../index.html')
console.log('📁 正在加载本地文件:', indexPath)
await mainWindow.loadFile(indexPath)
console.log('✅ 已加载本地文件')
}
// 页面加载完成后显示窗口
mainWindow.once('ready-to-show', () => {
mainWindow?.show()
})
// 窗口关闭时清理引用
mainWindow.on('closed', () => {
mainWindow = null
})
}
// 应用就绪时创建窗口
app.whenReady().then(createWindow)
// 当所有窗口都关闭时退出应用(macOS除外)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
vite.electron.dev.ts
ts
// 导入需要使用的类型和库
import type { Plugin } from 'vite'
import type { AddressInfo } from 'net'
import type { ChildProcess } from 'child_process'
import { spawn } from 'child_process'
import fs from 'fs'
import { build } from 'esbuild'
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
// 导出Vite插件函数
export const viteElectronDev = (): Plugin => {
return {
name: 'vite-electron-dev',
// 在configureServer中实现插件的逻辑
configureServer(server) {
// 定义初始化Electron的函数
const initElectron = async () => {
// 使用esbuild编译TypeScript代码为JavaScript
await build({
entryPoints: ['src/background.ts'],
bundle: true,
outfile: 'dist/background.js',
platform: 'node',
target: 'node18',
external: ['electron'],
format: 'esm'
})
}
// 调用初始化Electron函数
initElectron()
// 监听Vite的HTTP服务器的listening事件
server?.httpServer?.once('listening', () => {
// 获取HTTP服务器的监听地址和端口号
const addressInfo = server?.httpServer?.address() as AddressInfo
const IP = `http://localhost:${addressInfo.port}`
// 使用 require 获取 electron 可执行文件路径
const electronPath = require('electron') as string
// 启动Electron进程
let electronProcess: ChildProcess = spawn(electronPath, ['dist/background.js', IP])
// 监听主进程代码的更改
fs.watchFile('src/background.ts', async () => {
// 杀死当前的Electron进程
electronProcess.kill?.()
// 重新编译主进程代码并重新启动Electron进程
await initElectron()
electronProcess = spawn(electronPath, ['dist/background.js', IP])
})
// 监听Electron进程的stdout输出
electronProcess.stdout?.on('data', (data) => {
console.log(`日志: ${data}`);
});
})
}
}
}
vite.electron.build.ts
ts
import type { Plugin } from 'vite'
import * as electronBuilder from 'electron-builder'
import path from 'path'
import fs from 'fs'
import { build } from 'esbuild'
// 导出Vite插件函数
export const viteElectronBuild = (): Plugin => {
return {
name: 'vite-electron-build',
// closeBundle是Vite的一个插件钩子函数,用于在Vite构建完成后执行一些自定义逻辑。
async closeBundle() {
// 定义初始化Electron的函数
const initElectron = async () => {
// 使用esbuild编译TypeScript代码为JavaScript
await build({
entryPoints: ['src/background.ts'],
bundle: true,
outfile: 'dist/background.js',
platform: 'node',
target: 'node18',
external: ['electron'],
format: 'esm'
})
}
// 调用初始化Electron函数
await initElectron()
// 修改package.json文件的main字段 不然会打包失败
const json = JSON.parse(fs.readFileSync('package.json', 'utf-8'))
json.main = 'background.js'
fs.writeFileSync('dist/package.json', JSON.stringify(json, null, 2))
// 创建一个空的node_modules目录 不然会打包失败
fs.mkdirSync(path.join(process.cwd(), "dist/node_modules"));
// 使用electron-builder打包Electron应用程序
electronBuilder.build({
config: {
appId: 'com.example.app',
productName: 'vite-electron',
directories: {
output: path.join(process.cwd(), "release"), //输出目录
app: path.join(process.cwd(), "dist"), //app目录
},
asar: true,
nsis: {
oneClick: false, //取消一键安装
}
}
})
}
}
}
vite.config.ts
ts
import path from "node:path";
import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
import { viteElectronDev } from "./plugins/vite.electron.dev";
import { viteElectronBuild } from "./plugins/vite.electron.build";
export default defineConfig({
plugins: [
vue(),
viteElectronDev(),
viteElectronBuild(),
],
base: "./",
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});