本文导读

Vue集成Electron

本文章对小满zs,满哥之前发过Vue3 Vite electron 开发桌面程序,进行修改完成适配,桀桀桀

添加依赖

# 一定要安装成开发依赖
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

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

// 导入需要使用的类型和库
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

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

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"),
    },
  },
});
本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]