Electron+Vue3+Vite+ElectronForge整合-全部ts开发 - 一键启动两个服务 一键打包两个服务

news2024/11/18 5:59:08

说明

本文介绍一下 Electron + Vue3 + Vite + Electron Forge 的高级整合操作。

vue3 : 使用 TS 的语法开发;
Electron : 使用 TS 的语法开发。
补充 : 目前Electron的开发还是以JS为主,不过我们可以直接使用TS开发,在执行和打包时,先进行JS的编译就可以了。

本文将从项目初始化开始,一步一步的完成项目的启动、打包全流程的介绍。
实现的效果是 :
1、一个正常的Vue3项目;

2、整合加入 Electron 框架 :
	 开发时 Electron 加载的是开发的vue项目;
	 【实现一键启动 vue3 项目 + electron 项目】
	 
3、整合加入Electron Forge ,完成打包时整合:
	3.1 先完成vue3项目的正常打包;
	3.2 再完成 electron 项目的打包。
	【实现 一键完成 vue3 项目打包 + electron 项目打包】 

实现思路介绍

一键启动实现思路

核心思路 : electron 启动时,需要加载 vue3 的服务,即需要在启动electron时,将vue3的服务地址获取到。

实现方案:
	1、通过 vite 的自定义插件 + configureServer 钩子,获取vue3 的服务地址;
	2、获取到vue3 的服务地址后,通过 node 的 子进程 spawn 的方式,启动electron服务,并将 该地址作为进程参数传递给 electron 进程;
	3、将Electron 的项目源码编译成 JS的;
	4、通过以上三个连续的操作,实现项目的一键启动。

特殊配置 : 
	需要 配置环境变量。
	electron 启动服务时,需要根据环境变量的配置情况,确定是加载开发环境的服务地址 or 正式环境的文件地址。

一键打包实现思路

electron 打包需求 : 需要加载 一个 index.html 的页面。
而我们的 index.html 页面,此时,就是 vue3 项目打包后的那个 index.html。


核心思路 : 将 vue3 的打包输出目录,直接放到 Electron 的编译之后的目录下;然后执行electron的打包动作。

实现方案:
	1、通过 vite 的自定义插件 + closeBundle 钩子,在vue项目打包完成之后,执行electron的打包动作即可。
	2、特殊配置 : 需要将 vue3 的打包输出目录,配置到electron的编译之后的目录中。

下面,从零开始,进行项目的搭建。

步骤一:创建vue3项目

常规操作,不再赘述。

# 创建项目
npm create vue@latest

# 进入到项目目录
cd <your project dir>

# 安装依赖
npm install

# 启动访问
npm run dev

正经的vue项目启动成功!

在这里插入图片描述

此时的项目目录结构如下:是一个标准的vue3的项目结构

projectName
	| -- node_modules        # 依赖包的位置
	| -- public              # 一些静态资源
	| -- src                 # vue的源文件目录
	| -- .gitignore          # git忽略配置文件 
	| -- env.d.ts            
	| -- index.html          # vue主页面
	| -- package.json        # 项目依赖配置文件
	| -- tsconfig.app.json   # 定义项目中其他文件的ts编译规则
	| -- tsconfig.json       # typescript 配置文件
	| -- tsconfig.node.json  # 配置vite.config.ts文件的编译规则
	| -- vite.config.ts      # vite 配置文件

特殊操作 : .gitignore 中添加 以下两个 目录,无需纳入版本管理
out : electron 的打包目录。
electrontarget : electron 编译 和 vue3 的打包文件的存放目录。

步骤二 :引入Electron

1、安装Electron

# 安装Electron
npm install --save-dev electron

2、项目根目录下创建一个electron的工作目录

# 进入到项目的根目录
cd <your project name>

# 创建electron目录
mkdir electron

3、在electron目录下创建主进程 electronMain.ts 文件

主要干了两个事儿 :
1.创建主窗口;
2.接收【插件参数】,确定加载 vue 的开发时服务 or 打包后的文件。

/**
 * electron 的主进程
 */
// 导入模块
import {app,BrowserWindow} from 'electron'

import path from 'path'

// 创建主窗口
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })

  // 根据是否存在开发路径,决定加载不同的内容
  let devUrl = process.argv[2]
  if(devUrl){
    win.loadURL(devUrl)
  }else{
    // 这个 pages/index.html 就是 vue3 打包之后的那个 index.html
    win.loadFile(path.resolve(__dirname,'pages/index.html'))
  }

  console.log('prod file : ',path.resolve(__dirname,'pages/index.html'))
}

// 应用准备就绪,加载窗口
app.whenReady().then(() => {

  console.log('electronMain.js : ready')

    createWindow()

    // mac 上默认保留一个窗口
    app.on('activate', () => {
        if (BrowserWindow.getAllWindows().length === 0) createWindow()
    })

    console.log('--- app ready ---')
})

// 关闭所有窗口 : 程序退出 : windows & linux
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') app.quit()
})

至此,项目目录如下 :

projectName
	| -- electron                # 【新增的electron的主目录】
		| -- electronMain.ts 
	| -- node_modules            # 依赖包的位置
	| -- public                  # 一些静态资源
	| -- src                     # 源文件目录
	| -- .gitignore              # git忽略配置文件 
	| -- env.d.ts            
	| -- index.html              # vue主页面
	| -- package.json            # 项目配置文件
	| -- tsconfig.app.json       # 定义项目中其他文件的ts编译规则
	| -- tsconfig.json           # typescript 配置文件
	| -- tsconfig.node.json      # 配置vite.config.ts文件的编译规则
	| -- vite.config.ts          # vite 配置文件

至此 vue3 + electron 的 开发时的基础整合步骤就完成了。
下面我们开始进行 【一键启动】& 【一键打包】的整合操作。

步骤三 : 环境变量配置文件准备(重点)

1.在开发环境时,vue 中的路由需要用这个 history 模式;而在打包正式环境时,需要用到 hash 模式
2.在开发环境时,electron 需要加载的是 vue 的服务路径;而在打包正式环境时,electron需要加载 vue 打包后的 index.html 文件
基于以上两点,我们进行 环境变量 的配置。使我们的应用会根据运行时的环境,自动加载正确的内容。

1、操作步骤

1、在项目的根目录创建环境变量文件目录 environmentconfig
2、在该目录下 创建三个文件:
    .env    		   (全局通用的环境变量)
    .env.development  (开发环境的环境变量)
    .env.productrion  (生产环境的环境变量)
3、在配置文件中添加一个 名为 【VITE_ENV】 的变量,用于标识当前是什么环境。

2、具体的文件内容

.env

这个文件中随便添加了一个变量,我们用不到,只是展示一下写法。

# 全局的环境变量
VITE_HELLO=HELLO WORLD

.env.development

这个是开发时用的变量,很关键。
路由模式选择、electron 运行/打包 时加载的内容,都是通过这个变量进行控制的!

# 开发环境的参数配置
VITE_ENV=DEVELOPMENT

.env.production

这个是打包生产环境时用的变量,很关键。
路由模式选择、electron 运行/打包 时加载的内容,都是通过这个变量进行控制的!

# 正式环境的参数配置
VITE_ENV=PRODUCTION

3、至此的目录结构

到这一步完成,我们的目录结构如下 :

projectName
	| -- electron               # 【electron的主目录】
		| -- electronMain.ts 
	| -- environmentconfig      # 【新增的 环境变量的配置目录】
		| -- .env
		| -- .env.development
		| -- .env.production
	| -- node_modules            # 依赖包的位置
	| -- public                  # 一些静态资源
	| -- src                     # 源文件目录
	| -- .gitignore              # git忽略配置文件 
	| -- env.d.ts            
	| -- index.html              # vue主页面
	| -- package.json            # 项目配置文件
	| -- tsconfig.app.json       # 定义项目中其他文件的ts编译规则
	| -- tsconfig.json           # typescript 配置文件
	| -- tsconfig.node.json      # 配置vite.config.ts文件的编译规则
	| -- vite.config.ts          # vite 配置文件

步骤四 : vite 配置文件重构(重点)

本步骤,主要是将 vite 的配置文件,根据,开发环境 与 生产环境 相互独立开来。
这样方便我们后续对项目的配置。

1、操作步骤

1、在项目的根目录创建vite的配置文件目录 viteconfig
2、在该目录下 创建三个文件:
    vite.base.config.ts   (全局通用的vite配置)
    vite.dev.config.ts   (开发环境的vite配置)
    vite.prod.config.ts  (生产环境的vite配置)
3、将原来 根目录下的 vite.config.ts 重命名为 【vite.config.mts】
4、将原来 根目录下的 vite.config.ts 的内容修改为按【运行环境】加载不同的配置文件

2、具体的文件内容

vite.base.config.ts

全局通用的 vite 配置 : 此时需要指定 【上面环境变量文件的路径】

// vite 的通用配置

import { fileURLToPath, URL } from 'node:url'
import vue from '@vitejs/plugin-vue'

import { defineConfig } from "vite"
console.log('load base-config...')
export default defineConfig({

    plugins: [
        vue(),
    ],

    // 指定参数配置的文件目录(比较关键)
    envDir:'environmentconfig',

    resolve: {
        alias: {
        '@': fileURLToPath(new URL('../src', import.meta.url))
        }
    },
   
})

vite.dev.config.ts

开发环境用到的 vite 配置 : 主要指定了一下 开发环境 vue 的服务端口号

// vite 的开发环境的配置

import { defineConfig } from "vite"
console.log('load dev-config...')

export default defineConfig({
   
        // 指定一下访问的服务端口
        server:{
            port:5179
        }
})

vite.prod.config.ts

生产环境用到的 vite 配置 :
1、指定打包时的base路径为相对路径!(重要)
2、指定vue3项目的打包输出路径到 electrontarget的目录下,这样electron 可以直接打包了就。(重要)
注意 : electrontarget 目录,是 electron 的 编译过后的 js 的目录。

// vite 的生产环境的配置

import { defineConfig } from "vite"
console.log('load prod-config...')

export default defineConfig({

    // 配置打包相关的属性
    base:'./',
    build:{
        outDir:'electrontarget/pages'
    }
})

vite.config.mts

根目录下的vite启动配置 : 根据不同的运行参数加载不同的配置文件。
下面的文件内容中,保留了许多 console.log() 语句,可以帮助我们调试确定环境加载是否正确。

// vite 的根配置 : 根据不同的运行参数,读取不同的配置文件
import { defineConfig, loadEnv } from "vite"

// 引入三个环境配置文件
import ViteBaseConfig from "./viteconfig/vite.base.config"
import ViteProdConfig from "./viteconfig/vite.prod.config"
import ViteDevConfig from "./viteconfig/vite.dev.config"
import path from "path"

// 策略模式做一个动态的配置
const envResolver = {
    "build":()=>{
        console.log("加载生产环境 : ")
        // 解构的语法
        return ({...ViteBaseConfig,...ViteProdConfig})
    },
    "serve":()=>{
        console.log("加载开发环境 : ")
        // 另一种写法
        return Object.assign({},ViteBaseConfig,ViteDevConfig)
    }
}

// 根据 参数 command 的值,使用不同的环境配置文件
export default defineConfig(({command,mode})=>{
   /console.log("vite start : command : ",command)
    console.log("vite start : mode : ",mode)
    console.log("process.cwd() : ",process.cwd())
    console.log("__dirname: ",__dirname)
    console.log("envdir : ",path.resolve(process.cwd(),'./environmentconfig'))

     // 加载不同环境下的参数
     const envParams = loadEnv(mode,path.resolve(process.cwd(),'./environmentconfig'))

    // 根据不同的环境使用不同的配置文件,注意这个地方的写法,非常的奇特
    return envResolver[command]()
})

3、修改 tsconfig.node.ts文件

此步骤的目的是 为了 解决 vite.config.mts文件中 导入 三个 vite 配置文件提示报错的问题。
其实,只需要将 viteconfig 这个目录添加到 includes 属性下即可。
下面是tsconfig.node.ts 文件中添加的内容:

{
  .....
  "include": [
     ......
     // 添加 viteconfig 目录
    "viteconfig/*"
  ],
   ......
}

4、至此的目录结构

到这一步完成,我们的目录结构如下 :

projectName
	| -- electron               # 【electron的主目录】
		| -- electronMain.ts 
	| -- environmentconfig      # 【环境变量的配置目录】
		| -- .env
		| -- .env.development
		| -- .env.production
	| -- node_modules            # 依赖包的位置
	| -- public                  # 一些静态资源
	| -- src                     # 源文件目录
	| -- viteconfig              #【新增的 vite 配置目录】
		| -- vite.base.config.ts
		| -- vite.dev.config.ts
		| -- vite.prod.config.ts
	| -- .gitignore              # git忽略配置文件 
	| -- env.d.ts            
	| -- index.html              # vue主页面
	| -- package.json            # 项目配置文件
	| -- tsconfig.app.json       # 定义项目中其他文件的ts编译规则
	| -- tsconfig.json           # typescript 配置文件
	| -- tsconfig.node.json      # 配置vite.config.ts文件的编译规则
	| -- vite.config.mts          # 【vite 的根目录配置文件】

步骤五 : 一键启动 配置 (难点)

实现思路 :
1、先启动 vue3 的服务
2、自定义一个vite插件,监听 vue3 的服务启动,并获取启动的端口号;
3、将 electron 的 TS 编译成 JS,输出到 electrontarget 目录中。
4、将 【vue3 的服务访问地址】 和 【环境变量】 作为参数,通过 进程传参的方式,传递给 【electron的主进程】;
4、启动electron 。

1、创建自定义插件

在 项目根目录下,创建 plugins 目录,用于存放 自定义的插件。
plugins 目录下,创建 vite.dev.plugin.ts 文件, 就是我们要写的插件。
插件内容如下 :可以直接复制使用

// 开发环境的自定义插件

import { loadEnv, type Plugin } from "vite";

import type { AddressInfo } from "net";
// 导入子进程
import {ChildProcess, spawn} from 'child_process'
// 导入electron命令
import electron from 'electron'
// 导入 文件操作
import fs from 'fs'
import path from "path";

// 引入esbuild,把 electron 的 ts 打包成 js 
import { BuildResult, buildSync } from "esbuild";

// 手动定义一个方法,用于进行打包的工作
const electronBuild2Js = () => {

    // 每次都先删除target目录,然后执行新的编译动作
    let targetExistFlag = fs.existsSync('electrontarget')
    if(targetExistFlag){
        console.log('electrontarget 目录存在,执行删除')
        fs.rmSync('electrontarget',{recursive:true})
    }else{
        console.log('electrontarget 目录不存在,无需删除')
    }

    // 把electron 的 入口 ts 文件进行打包操作
    let buildRes :BuildResult =  buildSync({
        entryPoints:['electron/**/*.ts','electron/**/*.js'],
        bundle:true,
        outdir:'electrontarget',
        // outfile:'target/electron/electronMain.js',
        platform:'node',
        target:'node20',
        external:['electron']
    })

    console.log('编译 electron ts 文件结果 : ',buildRes)
}

// 自定义的插件的逻辑
export const ElectronDevPlugin = ():Plugin =>{
    return {
        name:'electron-dev-plugin',
        //配置服务的钩子
        configureServer(server){
        
   			// 先把electron执行一下编译
            electronBuild2Js();

            server.httpServer?.on('listening',()=>{
				// 核心1 : 获取vue3的服务地址
                let addressInfo =  server.httpServer?.address() as AddressInfo
                const devUrl = `http://localhost:${addressInfo.port}`
                console.log('plugins-dev : 服务的完整地址 : ',devUrl) 
                
                // 核心2 :加载测试环境的环境变量
                let envParams = loadEnv('development',path.resolve(process.cwd(),'./environmentconfig'));
                console.log('plugins-dev : 获取的环境变量 : ',envParams.VITE_ENV)


                // 核心3 : 进程传参,发送到electron的进程中
                let electronProcess = spawn(electron+'',['electrontarget/electronMain.js',devUrl],{ stdio: 'inherit' }) as ChildProcess
                console.log('plugins-dev : electronProcess : ',electronProcess.pid)
                 
				// 扩展功能 : 增加 electron 的热启动功能
                fs.watch('electron',()=>{
                    console.log('plugins-dev : electron 目录中的文件发生改变了')
                    electronProcess.kill()
                    // 把electron执行一下编译,然后在重新执行
                    electronBuild2Js();
                    electronProcess = spawn(electron+'',['electrontarget/electronMain.js',devUrl],{ stdio: 'inherit' }) as ChildProcess

                })
            })
        }
    }
}

2、加载插件

viteconfig/vite.base.config.ts 文件中,添加 我们的自定义插件。
下面只展示了 vite.base.config.ts增量修改的部分。


// 导入 electron开发时的插件,实现一键启动两个服务的功能
import { ElectronDevPlugin } from '../plugins/vite.dev.plugin'

import { defineConfig } from "vite"
console.log('load base-config...')
export default defineConfig({

    plugins: [
         ......
		// 添加自定义的插件
        ElectronDevPlugin(),
        
    ],

   .... 其他的配置
   
})

3、在 tsconfig.node.json 中添加插件目录

这一步主要是解决 关于插件的异常提示的问题。
tsconfig.node.json 文件的 include 中添加 plugins 目录即可。

{
  "extends": "@tsconfig/node20/tsconfig.json",
  "include": [
     ......
    "plugins/*"
  ],

}

4、确保electronMain.ts 文件的加载内容如下

此步骤的目的,是为了实现 在不同的环境下,加载不同的内容:
开发环境下 : 直接加载 vue3 的项目服务地址;
打包时 : 直接加载 vue3 打包之后的index.html文件。

下面截取的是 要修改的内容:
......


// 引入path 模块
const path = require('path')

// 创建主窗口
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })

  // 根据是否存在开发路径,决定加载开发环境的路径 or 生产环境的包
  // 下面的这个是核心
  let devUrl = process.argv[2]
  if(devUrl){
    win.loadURL(devUrl)
  }else{
    win.loadFile(path.resolve(__dirname,'pages/index.html'))
  }
}

......

5、vue3 路由文件的修改

本步骤,主要是为了实现
1、开发环境时,使用 history 模式;
2、打包生产时,使用 hash 模式。

要修改的内容如下 :
import { createRouter, createWebHistory,createWebHashHistory } from 'vue-router'

const router = createRouter({
  // history: createWebHistory(import.meta.env.BASE_URL),
  // 根据环境变量的配置,开发时使用 history模式,打包时使用 hash 模式
  history: (import.meta.env.VITE_ENV == 'DEVELOPMENT') ? createWebHistory(import.meta.env.BASE_URL) : createWebHashHistory(),
  routes: [
     ......
     正常的路由配置
  ]
})

// 导出路由对象
export default router

6、package.json 中添加 启动脚本

package.json 文件中,添加 【一键启动】的脚本命令。

  ......
  "scripts": {
     .....
    // 一键启动两个服务的脚本
    "dev:all":"vite",
	......
  },
......

7、至此的目录结构

至此,我们的项目目录结构如下:

projectName
	| -- electron               # 【electron的主目录】
		| -- electronMain.ts 
	| -- environmentconfig      # 【环境变量的配置目录】
		| -- .env
		| -- .env.development
		| -- .env.production
	| -- node_modules            # 依赖包的位置
	| -- plugins                 #【自定义插件的目录】
		| -- vite.dev.plugin.ts
	| -- public                  # 一些静态资源
	| -- src                     # 源文件目录
	| -- viteconfig              #【vite 配置目录】
		| -- vite.base.config.ts
		| -- vite.dev.config.ts
		| -- vite.prod.config.ts
	| -- .gitignore              # git忽略配置文件 
	| -- env.d.ts            
	| -- index.html              # vue主页面
	| -- package.json            # 项目配置文件
	| -- tsconfig.app.json       # 定义项目中其他文件的ts编译规则
	| -- tsconfig.json           # typescript 配置文件
	| -- tsconfig.node.json      # 配置vite.config.ts文件的编译规则
	| -- vite.config.mts          # 【vite 的根目录配置文件】

8、一键启动

下面我们进行启动测试:
命令行中执行 npm run dev:all

在这里插入图片描述
在这里插入图片描述

》 至此,一键启动的功能整合就完成了!

步骤六 : 一键打包 配置 (难点)

实现思路 :
1、先打包 vue3,将内容输出到 electrontarget/pages 目录下;
2、自定义一个vite插件,在vue3打包完成之后,执行 electron 的打包操作;

1、electron-forge 依赖安装

npm install --save-dev @electron-forge/cli

2、import 导入 forge 的脚手架

以下命令执行完成后,会在 根目录下 生成 forge.config.js 配置文件。
以及 在 package.json 文件的 script 脚本配置中自动添加如下内容 :
其中,"make" 命令就是执行 electron 打包的脚本。

   "start": "electron-forge start",
   "package": "electron-forge package",
   "make": "electron-forge make"
npx electron-forge import

为了确保相关的依赖都安装了,可以再手动执行以下下面的命令。

npm install --save-dev @electron-forge/maker-squirrel 
npm install --save-dev @electron-forge/maker-deb 
npm install --save-dev @electron-forge/maker-rpm
npm install --save-dev @electron-forge/maker-zip
npm install --save-dev @electron-forge/maker-dmg

3、修改 forge.config.js 文件内容

主要是确保 配置中包含 windows 和 mac 的打包配置。
包含以下内容即可。不用太多。
主要看 makers 中的内容。

const { FusesPlugin } = require('@electron-forge/plugin-fuses');
const { FuseV1Options, FuseVersion } = require('@electron/fuses');

module.exports = {
  packagerConfig: {
    asar: true,
  },
  rebuildConfig: {},
  makers: [
    // windows 上的打包
    {
      name: '@electron-forge/maker-squirrel',
      config: {},
    },
  
    // mac 上的打包
    {
      name: '@electron-forge/maker-dmg',
      config: {
        //background: './assets/dmg-background.png',
        format: 'ULFO'
      }
    },
    // 打成 zip 的包,windows 上和 mac 上都有
    {
      name: '@electron-forge/maker-zip',
      platforms: ['darwin','win32'],
    },

  ],
  plugins: [
    {
      name: '@electron-forge/plugin-auto-unpack-natives',
      config: {},
    },
    // Fuses are used to enable/disable various Electron functionality
    // at package time, before code signing the application
    new FusesPlugin({
      version: FuseVersion.V1,
      [FuseV1Options.RunAsNode]: false,
      [FuseV1Options.EnableCookieEncryption]: true,
      [FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
      [FuseV1Options.EnableNodeCliInspectArguments]: false,
      [FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
      [FuseV1Options.OnlyLoadAppFromAsar]: true,
    }),
  ],
};

4、修改package.json 文件的配置(关键)

主要是:
1.需要完善项目的 authordescription 属性的配置(打包时必须要用的属性);
2.明确主要的打包脚本,main 属性指定了 electron 的主进程文件,注意,此处我们要指定的是 electron 编译完成之后的 js 的文件目录
下面是 【package.json】 文件的内容节选。

{
  "name": "electronvuebuildtest", // 项目的名称,也是打包之后的程序名称
  "version": "1.0.0", // 版本信息
  "private": true,
  "author": "northcastle", // 作者信息,必填
  "description": "The Project of Electron + Vue3 + Electron Forge", // 描述信息,必填
  "main": "electrontarget/electronMain.js",
  "scripts": {
  
  	// 其实就是 一个默认的 vue3 的打包命令
    "build:all":"run-p type-check \"build-only {@}\" --",
    // electron-forge 相关的命令(必须要有)
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make"  // electron 打包实际执行的命令就是这个
    ......
  },
  "dependencies": {
     ...
  },
  "devDependencies": {
    ...
  }
}

5、自定义打包插件

自定义插件,
1、编译打包 vue3 之前,先将 electron 的ts文件重新编译为 js;
2、实现 vue3 打包完成之后,继续执行 electron的打包命令。
插件位置 : plugins/vite.build.plugin.ts

// 打包时用到的插件
// 项目打包时候的自定义插件

import { Plugin } from "vite";

// 通过 spawn 的方式执行 electron-forge 的打包命令
import { ChildProcess, spawn } from "node:child_process";

import os from 'os'

import fs from 'fs'

// 引入esbuild,把 electron 的 ts 打包成 js 
import { BuildResult, buildSync } from "esbuild";

// 手动定义一个方法,用于进行打包的工作
const electronBuild2Js = () => {

    // 每次都先删除target目录,然后执行新的编译动作
    let targetExistFlag = fs.existsSync('electrontarget')
    if(targetExistFlag){
        console.log('electrontarget 目录存在,执行删除')
        fs.rmSync('electrontarget',{recursive:true})
    }else{
        console.log('electrontarget 目录不存在,无需删除')
    }

    // 把electron 的 入口 ts 文件进行打包操作
    let buildRes :BuildResult =  buildSync({
        entryPoints:['electron/**/*.ts','electron/**/*.js'],
        bundle:true,
        outdir:'electrontarget',
        // outfile:'target/electron/electronMain.js',
        platform:'node',
        target:'node20',
        external:['electron']
    })

    console.log('编译 electron ts 文件完成')
}

// 思路 : 先等vite 打完包,然后再执行 electron的打包动作
// 因为,electron 打包是需要用到 vue 打包之后的 index.html 文件的
export const ElectronBuildPlugin = ():Plugin =>{
    return{
        name:'electron-build-plugin',
        
        buildStart(){
            console.log('vite-prod 开始编译vue对象 : 先重新编译 electron 的 ts ')

            // 先执行 electron 的 编译动作
            electronBuild2Js();
        },
        
        closeBundle() {
            console.log('vite-vue 打包完成')

            // 先把之前的打包的文件删除
            let dirFlag = fs.existsSync('out')
            if(dirFlag){
                console.log('plugins-build : out目录 存在,先删除')
                fs.rmSync('out',{recursive:true})
            }else{
                console.log('plugins-build : out目录 不存在')
            }
            
           // 下面执行命令进行electron的打包
            const platform = os.platform();
        
            if (platform === 'win32') {
                console.log('当前运行环境是 Windows');
                // windows 上需要执行这种方式
                let buildChildProcess =  spawn('npm.cmd',['run','make'],{stdio: 'inherit'}) as ChildProcess

            } else if (platform === 'darwin') {
                console.log('当前运行环境是 Mac');
                // Mac上可以执行这种方式
                // let buildChildProcess = spawn('electron-forge',['make'],{stdio: 'inherit'}) as ChildProcess
                let buildChildProcess = spawn('npm',['run','make'],{stdio: 'inherit'}) as ChildProcess
            } else {
                console.log('其他平台 : ',platform,'【暂不支持打包】');
            }

        },
    }
}

6、把插件放到 vite.base.config.ts 中

// vite 的通用配置

......

// 导入 打包时的插件,实现一键打包两个服务的功能
import { ElectronBuildPlugin } from '../plugins/vite.build.plugin'


import { defineConfig } from "vite"
console.log('load base-config...')
export default defineConfig({

    plugins: [
       ......
        ElectronBuildPlugin()
    ],

    ......
})

7.vite.prod.config.ts 文件属性确认

在打包为生产环境时,会加载 vite.prod.config.ts 文件
需要对以下两个属性进行确认,否则会影响打包效果。

a.base属性为./ 相对路径

必须修改,否则打包后无法加载页面

b.修改vue的打包输出目录

主要是为了把 vue 打包的内容直接输出到 electrontarget/pages 的目录下,
这样就不用手动复制过去了。

》以下是上述两个的配置案例 :

// vite 的生产环境的配置

import { defineConfig } from "vite"
console.log('load prod-config...')

export default defineConfig({

    // 配置打包相关的属性
    base:'./',
    build:{
        outDir:'electrontarget/pages'
    }
})

8、确认 electronMain.ts 中是按环境加载的

此时需要加载我们打包完成之后的vue的页面内容。

/**
 * electron 的主进程
 */
// 导入模块
const { app, BrowserWindow  } = require('electron')

// 创建主窗口
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })

  // 根据是否存在开发路径,决定加载不同的内容

  let devUrl = process.argv[2]
  if(devUrl){
    win.loadURL(devUrl)
  }else{
    // 打包时,主要用到的就是这一块,目录也需要搞正确
    // ‘pages/index.html’ 就是 vue 打包之后的存放的目录
    win.loadFile(path.resolve(__dirname,'pages/index.html'))
  }

}

...
其他的内容不变

9、文件目录确认

至此,所有的准备工作都搞定了,目录结构如下:

projectName
	| -- electron               # 【electron的主目录】
		| -- electronMain.ts 
	| -- environmentconfig      # 【环境变量的配置目录】
		| -- .env
		| -- .env.development
		| -- .env.production
	| -- node_modules            # 依赖包的位置
	| -- plugins                 #【自定义插件的目录】
		| -- vite.dev.plugin.ts
		| -- vite.prod.plugin.ts
	| -- public                  # 一些静态资源
	| -- src                     # 源文件目录
	| -- viteconfig              #【vite 配置目录】
		| -- vite.base.config.ts
		| -- vite.dev.config.ts
		| -- vite.prod.config.ts
	| -- .gitignore              # git忽略配置文件 
	| -- env.d.ts            
	| -- forge.config.js         #  electron-forge 打包的配置文件
	| -- index.html              # vue主页面
	| -- package.json            # 项目配置文件
	| -- tsconfig.app.json       # 定义项目中其他文件的ts编译规则
	| -- tsconfig.json           # typescript 配置文件
	| -- tsconfig.node.json      # 配置vite.config.ts文件的编译规则
	| -- vite.config.mts          # 【vite 的根目录配置文件】

至此,所有打包的配置步骤就完了。下面就可以执行打包了

步骤七 : 一键打包

打包 : 虽然 forge.config.js 中我们配置了不同操作系统上的打包操作,
但实际上,在某个操作系统上执行的打包命令,则只能产出该操作系统上的文件。
例如 :
在 Windows执行打包,只能打包出 Windows 上的安装程序;
在 Mac 上执行打包,只能打包出 Mac 上的安装程序。

1、执行打包

npm run build:all
根据我们的配置,打包完成后,
1、electron 的 ts 将会被 编译输出到 electrontarget 目录下;
2、vue的内容将会保存到 electrontarget/pages 目录下;
3、electron 打包的内容将会被存放到 out 目录下。

打包过程记录如下 :

npm run build:all

> electronvue3devbuild01@0.0.0 build:all
> run-p type-check "build-only {@}" --

> electronvue3devbuild01@0.0.0 build-only
> vite build

> electronvue3devbuild01@0.0.0 type-check
> vue-tsc --build --force

load base-config...
load prod-config...
load dev-config...
vite start : command :  build
vite start : mode :  production
process.cwd() :  /xxx/electronvue3devbuild01
__dirname:  /xxx3/electronvue3devbuild01
envdir :  /xxx/electronvue3devbuild01/environmentconfig
加载生产环境 : 
vite v5.2.10 building for production...
vite-prod 开始编译vue对象 : 先重新编译 electron 的 ts 
electrontarget 目录存在,执行删除
▲ [WARNING] The glob pattern "electron/**/*.js" did not match any files [empty-glob]

编译 electron ts 文件完成
✓ 48 modules transformed.
electrontarget/pages/index.html                      0.43 kB │ gzip:  0.28 kB
electrontarget/pages/assets/AboutView-C6Dx7pxG.css   0.09 kB │ gzip:  0.10 kB
electrontarget/pages/assets/index-D6pr4OYR.css       4.21 kB │ gzip:  1.30 kB
electrontarget/pages/assets/AboutView-Y2lkSRWg.js    0.22 kB │ gzip:  0.20 kB
electrontarget/pages/assets/index-CweW04qw.js       89.45 kB │ gzip: 35.39 kB
✓ built in 459ms
vite-vue 打包完成
plugins-build : out目录 不存在
当前运行环境是 Mac

> electronvue3devbuild01@0.0.0 make
> electron-forge make

✔ Checking your system
✔ Loading configuration
✔ Resolving make targets
  › Making for the following targets: ,
✔ Running package command
  ✔ Preparing to package application
  ✔ Running packaging hooks
    ✔ Running generateAssets hook
    ✔ Running prePackage hook
  ✔ Packaging application
    ✔ Packaging for arm64 on darwin [2s]
  ✔ Running postPackage hook
✔ Running preMake hook
✔ Making distributables
  ✔ Making a dmg distributable for darwin/arm64 [4s]
  ✔ Making a zip distributable for darwin/arm64 [7s]
✔ Running postMake hook

  // 重点提示 :打包文件输出目录 
  › Artifacts available at: /xxx/electronvue3devbuild01/out/make

(node:47262) [DEP0147] DeprecationWarning: In future versions of Node.js, fs.rmdir(path, { recursive: true }) will be removed. Use fs.rm(path, { recursive: true }) instead
(Use `node --trace-deprecation ...` to show where the warning was created)
northcastle@192 electronvue3devbuild01 % 

2、打包完成之后的目录

projectName
	| -- electron              #【electron的开发目录】
		| -- electronMain.ts
	| -- electrontarget         # 【electron的编译之后的主目录】 
		| -- pages              #【vue 打包的输出目录】
			| -- index.html
			| -- assets
			| -- xxxxx
		| -- electronMain.js 
	| -- environmentconfig      # 【环境变量的配置目录】
		| -- .env
		| -- .env.development
		| -- .env.production
	| -- node_modules            # 依赖包的位置
   | -- out                     #【electron 打包输出目录】
   		| -- make
	| -- plugins                 #【自定义插件的目录】
		| -- vite.dev.plugin.ts
		| -- vite.prod.plugin.ts
	| -- public                  # 一些静态资源
	| -- src                     # 源文件目录
	| -- viteconfig              #【vite 配置目录】
		| -- vite.base.config.ts
		| -- vite.dev.config.ts
		| -- vite.prod.config.ts
	| -- .gitignore              # git忽略配置文件 
	| -- env.d.ts            
	| -- forge.config.js         #  electron-forge 打包的配置文件
	| -- index.html              # vue主页面
	| -- package.json            # 项目配置文件
	| -- tsconfig.app.json       # 定义项目中其他文件的ts编译规则
	| -- tsconfig.json           # typescript 配置文件
	| -- tsconfig.node.json      # 配置vite.config.ts文件的编译规则
	| -- vite.config.mts          # 【vite 的根目录配置文件】

ok ,至此,electron + vue3 + vite + electron forge 的 全ts 开发 的全流程 一键启动 & 一键打包功能就完成了。
如果您完全按照我的步骤进行操作,则相信您已经成功构建出自己的项目啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1637354.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MaskFormer

This repository has been archived by the owner on Aug 30, 2023. It is now read-only.不建议复现

linux系统的rsync命令实现本机到远程主机之间目录的复制和同步

一、rsync命令介绍 在Linux中&#xff0c;rsync 是一个强大的命令行工具&#xff0c;用于同步文件和目录。它可以在本地或通过网络在远程系统之间复制文件。 二、远程目录复制的条件 1、系统要已经安装rsync工具 要使用 rsync 复制远程目录&#xff0c;需要确保系统上安装了 …

高效率的做事方法?

高效率的做事方法可以帮助我们更好地管理时间和资源&#xff0c;以下是一些建议&#xff1a; 1.明确目标和计划&#xff1a; 在开始任何任务之前&#xff0c;先明确你的目标是什么。 制定一个详细的计划&#xff0c;包括步骤、时间表和预期结果。 将任务分解成小块&#xff0…

浅谈Agent AI智能体的未来

Agent AI智能体的未来非常广阔和潜力巨大。随着技术的发展和应用场景的不断拓展&#xff0c;我们可以期待以下几个方面的发展&#xff1a; 更加智能化&#xff1a;Agent AI智能体将会变得越来越智能&#xff0c;具备更强大的学习、推理和决策能力。它们可以通过大数据和机器学习…

修改word文件的创作者方法有哪些?如何修改文档的作者 这两个方法你一定要知道

在数字化时代&#xff0c;文件创作者的信息往往嵌入在文件的元数据中&#xff0c;这些元数据包括创作者的姓名、创建日期以及其他相关信息。然而&#xff0c;有时候我们可能需要修改这些创作者信息&#xff0c;出于隐私保护、版权调整或者其他实际需求。那么&#xff0c;有没有…

Linux系统启动Canal错误

说明&#xff1a;记录在Linux系统&#xff08;Cent OS 7&#xff09;中使用Canal的错误&#xff1b; 场景 将下载的Canal包解压&#xff0c;启动Canal时&#xff0c;Canal没有启动&#xff0c;如下&#xff1a; 分析&#xff1a;hs_err_pid13418.log是JVM运行异常生成的日志文…

SDKMAN!

概述 官网&#xff0c;SDKMAN是一款管理多版本SDK的工具&#xff0c;可以实现在多个版本间的快速切换。 其他特性&#xff1a; 易用&#xff1a;安装SDK不再需要去Google想安装的某个软件的官网的下载页&#xff0c;或找其他下载页面&#xff0c;然后下载安装包、解压、设置…

Apollo Dreamview+之播放离线数据包

前提条件 完成 Dreamview 插件安装&#xff0c;参见 Studio 插件安装 。 操作步骤 您可以通过包管理和源码两种方式快速体验离线数据包播放操作。其中进入 docker 环境和启动 dreamview 的命令有所区别&#xff0c;请您按照命令进行操作。 步骤一&#xff1a;启动并打开 Dr…

踏上R语言之旅:解锁数据世界的神秘密码(三)

多元相关与回归分析及R使用 文章目录 多元相关与回归分析及R使用一.变量间的关系分析1.两变量线性相关系数的计算2.相关系数的假设检验 二.一元线性回归分析的R计算三、回归系数的假设检验总结 一.变量间的关系分析 变量间的关系及分析方法如下&#xff1a; 1.两变量线性相关…

openlayer 使用ol-ext插件实现凸显区域

使用ol-ext插件实现凸显多变形 效果如图 1、创建openlayer var map; var view; var tileLayer, source, vector;function init() {tileLayer new ol.layer.Tile({source: new ol.source.TileArcGISRest({url: "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStr…

java 远程debug

java -agentlib:jdwptransportdt_socket,servery,suspendn,address50050 -Xmx1536m -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath./ -jar ${JAR_NAME} >/dev/null 2>&1 &参数说明 -agentlib:jdwptransportdt_socket,servery,suspendn,address50050: 这个参数…

Linux:使用匿名管道对进程池的模拟实现

目录 一、Makefile 二、processpool.cc 2.1创建通信管道和子进程 2.2控制子进程 2.3回收进程 三、task.hpp 四、完整代码 接下来我们将模拟实现一个进程池&#xff0c;进程池广泛应用与各个领域和方向&#xff0c;比如我们打开电脑后同时打开很多个进程&#xff08;也就是软…

python公务用车医院校园企业车辆管理系统

本 Python版本&#xff1a;python3.7 前端&#xff1a;vue.jselementui 框架&#xff1a;django/flask都有,都支持 后端&#xff1a;python 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat 开发软件&#xff1a;PyCharm 公务用车管理智慧云服务监管平台有管理员和用户…

托普利兹矩阵(T矩阵)及其应用(Matlab demo测试)

托普利兹矩阵&#xff08;T矩阵&#xff09;及其应用&#xff08;Matlab demo测试&#xff09; 1. 概念2. Matlab简单测试2.1 生成测试2.2 基本性质及原理2.3 性质验证 3. 其他应用总结3.1 其他性质3.2 文献阅读看到的 参考资料 1. 概念 托普利兹矩阵&#xff0c;简称为T型矩阵…

O2OA开发平台前端源码级二次开发(Vue3,React)

在使用O2OA进行项目定制化开发时&#xff0c;我们可以开发新的前端组件&#xff08;x_component&#xff09;以扩展O2OA来实现更多的业务。这种新增前端组件或者前端业务的开发通常会配合后端自定义应用实现的服务来完成系统内数据的交互。在当系统默认的界面不符合系统UI/UE设…

Sentinel 控制台学习

引言 上篇文章已经讲过 SpringCloud Sentinel集成到微服务项目中&#xff0c;接下来我们继续学习怎么使用sentinel控制台对微服务进行限流&#xff0c;熔断&#xff0c;降级等一系列操作。 控制台 接下来我们单独讲解每一个菜单按钮 实时监控 实时监控&#xff1a; 可以看到…

Leetcode 145:二叉树的后序遍历(迭代法)

给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。 思路&#xff1a; 迭代法的思路是&#xff0c;使用栈&#xff0c;一层一层的将树节点遍历入栈。 比如下面这个树&#xff0c;使用迭代法&#xff0c;1&#xff09;第一层&#xff0c;让根节点入栈。2&a…

2024深圳杯数学建模竞赛A题(东三省数学建模竞赛A题):建立火箭残骸音爆多源定位模型

更新完整代码和成品完整论文 《2024深圳杯&东三省数学建模思路代码成品论文》↓↓↓&#xff08;浏览器打开&#xff09; https://www.yuque.com/u42168770/qv6z0d/zx70edxvbv7rheu7?singleDoc# 2024深圳杯数学建模竞赛A题&#xff08;东三省数学建模竞赛A题&#xff0…

2024五一杯数学建模A题思路分析-钢板最优切割路径问题

文章目录 1 赛题选题分析 2 解题思路3 最新思路更新 1 赛题 A题 钢板最优切割路径问题 提高钢板下料切割过程中的工作效率&#xff0c;是模具加工企业降低成本和增加经济效益的重要途径&#xff0c;其中钢板切割的路径规划是钢板切割过程的一个关键环节。 钢板切割就是使用特殊…

附录6-1 黑马优购项目-组件与过滤器

目录 1 过滤器-格式化价格 2 组件-搜索框 3 组件-数量框 4 组件-商品概况 4.1 格式化价格 4.2 选择性使用勾选框和数量框 4.3 源码 1 过滤器-格式化价格 这个项目中仅用到格式化价格这一种过滤器。过滤器文件位置为store/filter.wxs 文件内容是这样的&#xf…