Vue集成Electron目前最新版本

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"),
    },
  },
});
相关推荐
bug_kada2 小时前
Flex布局/弹性布局(面试篇)
前端·面试
元元不圆2 小时前
JSP环境部署
前端
luckyCover2 小时前
带你一起攻克js之原型到原型链~
前端·javascript
麦当_2 小时前
SwipeMultiContainer 滑动切换容器算法指南
前端·javascript·算法
星斗大森林2 小时前
Flame游戏开发——噪声合成、域变换与阈值/调色映射的工程化实践(2)
前端
用户31506327304872 小时前
使用 vue-virtual-scroller 实现高性能传输列表功能总结
javascript·vue.js
星斗大森林2 小时前
flame游戏开发——地图拖拽与轻点判定(3)
前端
samonyu2 小时前
fnm 简介及使用
前端·node.js
bug_kada2 小时前
玩转Flex布局:看完这篇你也是布局高手!
前端