• Vue3 Vite electron 开发桌面程序


    Electron是一个跨平台的桌面应用程序开发框架,它允许开发人员使用Web技术(如HTML、CSS和JavaScript)构建桌面应用程序,这些应用程序可以在Windows、macOS和Linux等操作系统上运行。

    Electron的核心是Chromium浏览器内核和Node.js运行时环境。Chromium内核提供了现代浏览器的功能,例如HTML5和CSS3支持,JavaScript引擎等,而Node.js运行时环境则提供了服务器端JavaScript的能力和模块系统,这使得开发人员可以使用Node.js的模块和工具来构建桌面应用程序。

    Electron 案例

    1. Visual Studio Code:由Microsoft开发的跨平台代码编辑器,支持多种编程语言和插件扩展。使用Electron和TypeScript构建。
    2. Atom:由GitHub开发的跨平台代码编辑器,支持多种编程语言和插件扩展。使用Electron和CoffeeScript构建。
    3. Postman:由Postman Inc.开发的API测试和开发工具,允许用户轻松地测试和调试REST API。使用Electron和React构建。

    image.png

    创建项目 dev

    # 创建Vue项目
     npm init vue 
    # 安装依赖
    npm install
    # 一定要安装成开发依赖
    npm install electron electron-builder -D 
    # 安装超时 请使用某宝镜像 或者XX上网
    npm config set electron_mirror=https://registry.npmmirror.com/-/binary/electron/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    开发环境启动electron

    我们希望npm run dev的时候直接把electron也启动起来而不是开两个启动一次vite再启动一次electron

    第一步我们需要先建立一个文件夹

    在根目录创建一个plugins编写vite插件帮我们启动electron

    background.ts
    import { app, BrowserWindow } from 'electron'
    
    // 等待Electron应用就绪后创建BrowserWindow窗口
    app.whenReady().then(async () => {
        const win = await new BrowserWindow({
            width: 800,
            height: 600,
    
            // 配置窗口的WebPreferences选项,用于控制渲染进程的行为
            webPreferences: {
                nodeIntegration: true, // 启用Node.js集成
                contextIsolation: false, // 禁用上下文隔离
                webSecurity: false, // 禁用web安全策略
            }
        })
    
        // 根据命令行参数加载URL或本地文件
        if (process.argv[2]) {
            win.loadURL(process.argv[2])
        } else {
            win.loadFile('index.html')
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    这段代码创建了一个Electron应用程序的入口文件。该文件使用了Electron的appBrowserWindow模块来创建一个窗口。在应用程序准备就绪后,它会创建一个新的BrowserWindow对象,并将其设置为800x600像素的大小。窗口的webPreferences选项用于配置渲染进程的行为,例如启用Node.js集成、禁用上下文隔离和web安全策略等。

    接着,该代码检查命令行参数,如果有参数则加载URL,否则加载本地文件index.html。在开发模式下,可以将URL指向本地的开发服务器,以便实现热更新和实时调试。在生产模式下,需要将URL指向本地的index.html文件,以便在本地运行Electron应用程序。

    在这段代码中,app.whenReady()函数用于在Electron应用程序准备就绪后执行回调函数。该函数返回一个Promise对象,可以使用async/await语法来等待应用程序就绪后执行其他操作。在这个例子中,我们使用await关键字来等待BrowserWindow对象的创建完成。

    vite.electron.dev.ts
    // 导入需要使用的类型和库
    import type { Plugin } from 'vite'
    import type { AddressInfo } from 'net'
    import { spawn } from 'child_process'
    import fs from 'fs'
    
    // 导出Vite插件函数
    export const viteElectronDev = (): Plugin => {
        return {
            name: 'vite-electron-dev',
            // 在configureServer中实现插件的逻辑
            configureServer(server) {
                // 定义初始化Electron的函数
                const initElectron = () => {
                    // 使用esbuild编译TypeScript代码为JavaScript
                    require('esbuild').buildSync({
                        entryPoints: ['src/background.ts'],
                        bundle: true,
                        outfile: 'dist/background.js',
                        platform: 'node',
                        target: 'node12',
                        external: ['electron']
                    })
                }
    
                // 调用初始化Electron函数
                initElectron()
    
                // 监听Vite的HTTP服务器的listening事件
                server?.httpServer?.once('listening', () => {
                    // 获取HTTP服务器的监听地址和端口号
                    const addressInfo = server?.httpServer?.address() as AddressInfo
                    const IP = `http://localhost:${addressInfo.port}`
                    // 启动Electron进程
                    let electronProcess = spawn(require('electron'), ['dist/background.js', IP])
    
                    // 监听主进程代码的更改
                    fs.watchFile('src/background.ts', () => {
                        // 杀死当前的Electron进程
                        electronProcess.kill()
                        // 重新编译主进程代码并重新启动Electron进程
                        initElectron()
                        electronProcess = spawn(require('electron'), ['dist/background.js', IP])
                    })
    
                    // 监听Electron进程的stdout输出
                    electronProcess.stdout?.on('data', (data) => {
                        console.log(`日志: ${data}`);
                    });
                })
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    configureServer是Vite的一个插件钩子函数,用于在Vite开发服务器启动时执行一些自定义逻辑。该函数接受一个ServerOptions对象作为参数,该对象包含有关当前Vite服务器的配置信息。在这个钩子函数中,您可以访问Vite服务器的HTTP服务器对象(httpServer),WebSocket服务器对象(wsServer)和Vite的构建配置对象(config)等。您可以使用这些对象来实现各种功能,例如自定义路由、添加中间件、实现实时重载和调试等。

    esbuild.buildSync()

    • entryPoints:指定要编译的入口文件,这里是src/background.ts
    • bundle:指定是否打包所有依赖项,这里是true,表示需要打包所有依赖项。
    • outfile:指定输出文件的路径和名称,这里是dist/background.js
    • platform:指定编译的目标平台,这里是node,表示编译为Node.js可用的代码。
    • target:指定编译的目标JavaScript版本,这里是node12,表示编译为Node.js 12及以上版本可用的代码。
    • external:指定不需要被打包的外部依赖项,这里是['electron'],表示electron模块不需要被打包。

    在这段代码中,esbuild会将src/background.ts文件编译为JavaScript 并且放入dist

    fs.watch 主要实现热更新
    每次background.ts 修改完成就会重新启动electron进程

    image.png

    vite.electron.build.ts
    import type { Plugin } from 'vite'
    import * as electronBuilder from 'electron-builder'
    import path from 'path'
    import fs from 'fs'
    
    // 导出Vite插件函数
    export const viteElectronBuild = (): Plugin => {
        return {
            name: 'vite-electron-build',
    
            // closeBundle是Vite的一个插件钩子函数,用于在Vite构建完成后执行一些自定义逻辑。
            closeBundle() {
    
                // 定义初始化Electron的函数
                const initElectron = () => {
                    // 使用esbuild编译TypeScript代码为JavaScript
                    require('esbuild').buildSync({
                        entryPoints: ['src/background.ts'],
                        bundle: true,
                        outfile: 'dist/background.js',
                        platform: 'node',
                        target: 'node12',
                        external: ['electron'],
                    })
                }
    
                // 调用初始化Electron函数
                initElectron()
    
                // 修改package.json文件的main字段 不然会打包失败
                const json =  JSON.parse(fs.readFileSync('package.json', 'utf-8')) 
                json.main = 'background.js'
                fs.writeSync(fs.openSync('dist/package.json', 'w'), 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, //取消一键安装
                        }
                    }
                })
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55

    打包主要依靠electron-builder 这个库 他的参数是有很多的这儿只是简单演示

    closeBundle 我们electron打包是需要index.html 所以我们先等vite打完包之后vite会自动调用这个钩子 然后在这个钩子里面打包electron

    vite.config.ts
    import { fileURLToPath, URL } from 'node:url'
    
    import { defineConfig } from 'vite'
    import vue from '@vitejs/plugin-vue'
    import {viteElectronDev} from './plugins/vite.electron.dev'
    import {viteElectronBuild} from './plugins/vite.electron.build'
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [
        vue(),
        viteElectronDev(),
        viteElectronBuild()
      ],
      base:'./', //默认绝对路径改为相对路径 否则打包白屏
      resolve: {
        alias: {
          '@': fileURLToPath(new URL('./src', import.meta.url))
        }
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    image.png

  • 相关阅读:
    Linux文件的各种*id属性
    二、枚举 enum
    【油猴脚本 Greasemonkey】GM_xmlhttpRequest内部实现原理
    Ascii码表
    IDEA Java1.8通过sqljdbc4连接sqlserver插入语句
    2023年腾讯云双十一活动攻略整理汇总
    Flutter 类似onResume 监听,解决入场动画卡顿(2)
    Java实习生常规技术面试题每日十题Java基础(七)
    BGP联邦综合实验
    ubuntu22.04设置中文
  • 原文地址:https://blog.csdn.net/qq1195566313/article/details/131713875