说明
本文介绍一下 Electron + Vue3 的整合的中级操作。
实现的效果是 :
1、一个正常的Vue3项目;
2、整合加入 Electron 框架 :
开发时只执行一条命令,启动 vue 项目 后 再启动 electron;
electron 的开发使用 typescript;
支持 electron 的 ts 文件修改的热更新,无需重新启动服务。
注意 :
本文中的electron 使用的是 ts 的方式进行开发的;
因此,在执行electron 项目之前,需要先将它的 ts 编译成 js,然后运行electron。
步骤一:创建vue3项目
常规操作,不再赘述。
# 创建项目
npm create vue@latest
# 进入到项目目录
cd <your project dir>
# 安装依赖
npm install
# 启动访问
npm run dev
正经的vue项目启动成功!
此时的项目目录结构如下:是一个标准的vue3的项目结构
projectName
| -- node_modules # 依赖包的位置
| -- public # 一些静态资源
| -- src # 源文件目录
| -- .gitignore # git忽略配置文件
| -- env.d.ts
| -- index.html # vue主页面
| -- package.json # 项目配置文件
| -- tsconfig.json # typescript 配置文件
| -- vite.config.ts # vite 配置文件
步骤二 :引入Electron
1、安装Electron
# 安装Electron
npm install --save-dev electron
# 安装 esbuild ,编译文件时会用到
npm install --save-dev esbuild
2、项目根目录下创建一个electron的工作目录
# 进入到项目的根目录
cd <your project name>
# 创建electron目录
mkdir electron
3、在electron目录下创建主进程 electronMain.ts
文件
主要干了两个事儿 : 1.创建主窗口;
2.接收【插件】参数,加载vue的页面进来。
此时,窗口加载的页面是动态的,会根据【步骤三】
定义的插件传过来的参数进行加载。
/**
* electron 的主进程
*/
// 导入模块
const { app, BrowserWindow } = require('electron')
const path = require('node:path')
// 创建主窗口
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
})
// ********** 核心操作: 加载当前vue 的地址 **********
let devUrl = process.argv[2]
if(devUrl){ // 存在路径,则证明是开发环境,直接加载
win.loadURL(devUrl)
}else{ // 不存在路径,则我们先默认加载百度吧
win.loadURL('https://www.baidu.com')
}
}
// 应用准备就绪,加载窗口
app.whenReady().then(() => {
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()
})
步骤三 : 自定义插件(重点)
本插件的功能:
1、先对 electron 的 ts 文件执行编译;
2、获取 vue 项目的页面访问端口,组装完整的页面访问路径;
3、将完整的页面访问路径传递给electron主进程;
4、启动electron住进程,加载vue的页面。
1、新建插件目录
# 进入到项目的根目录
cd <your project name>
# 创建插件目录
mkdir plugins
2、新建插件文件
插件文件名称为 :
vite.electron.dev.ts
插件的主要功能 :
1、编译electron的ts文件为 js 文件;
2、监听 vite 服务启动;
3、组装 vue3 服务的页面访问地址;
4、使用 spawn 的方式,将组装的地址传递给electron主进程;
5、监听electron 的文件变动,实现热更新。
插件的内容基本确定,可以直接copy使用。
// 开发环境插件
import type { Plugin } from "vite";
import type { AddressInfo } from "net";
// 引入子进程:node 中的进程传参数法
import { ChildProcess, spawn } from "child_process";
// 引入 electron
import electron from 'electron';
// 引入 文件模块
import fs from 'fs'
// 引入esbuild,把 electron 的 ts 打包成 js
import { BuildResult, buildSync } from "esbuild";
// 手动定义一个方法,用于进行打包的工作
const electronBuild2Js = () => {
// 每次都先删除target目录,然后执行新的编译动作
let targetExistFlag = fs.existsSync('targetdev')
if(targetExistFlag){
console.log('targetdev目录存在,执行删除')
fs.rmSync('targetdev',{recursive:true})
}else{
console.log('targetdev目录不存在,无需删除')
}
// 把electron 的 入口 ts 文件进行打包操作
let buildRes :BuildResult = buildSync({
entryPoints:['electron/**/*.ts','electron/**/*.js'],
bundle:true,
outdir:'targetdev/electron',
// 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){
// 打包
electronBuild2Js();
// 监听这个服务,可以获取到服务相关的信息
server.httpServer?.on('listening',()=>{
const addressInfo:AddressInfo = server.httpServer?.address() as AddressInfo;
console.log('服务的信息 : ',addressInfo)
console.log('服务的端口 : ',addressInfo.port)
// 拼接一下当前服务的完整地址,传递给Electron 启动服务的时候使用
const devUrl = `http://localhost:${addressInfo.port}`
console.log('服务的完整地址 : ',devUrl)
// 把服务启动的信息,当作参数,传递给electron的进程中
// 执行 electron 命令,启动一个窗口,且 日志标准重定向到 主程序的控制台中
let electronProcess = spawn(electron,['target/electron/electronMain.js',devUrl],{ stdio: 'inherit' }) as ChildProcess
// 监听 electron 的文件是否有改变,如果有,则自动更新一下
fs.watch('electron',()=>{
console.log(' electron 的文件发生改变了')
// 先将之前的electron进程关闭
electronProcess.kill()
// 在重新打包一下
electronBuild2Js()
// 最后重新启动一下
electronProcess = spawn(electron,['target/electron/electronMain.js',devUrl],{ stdio: 'inherit' }) as ChildProcess
})
})
}
}
}
3、在vite配置文件中引入插件
vite 的配置文件是
vite.config.mts
在该文件中添加上述自定义的插件。
文件内容节选如下:
import { defineConfig } from 'vite'
// 导入自定义的插件
import {ElectronDevPlugin} from './plugins/vite.electron.dev'
export default defineConfig({
// 插件配置
plugins: [
...
ElectronDevPlugin()
],
// 。。。其他的配置内容
})
4、在tsconfig配置文件中添加包含
添加自定义插件 ts 文件的包含配置,否在,在
vite.config.mts
文件中引入时有错误提示。
tsconfig的配置文件是 :tsconfig.node.json
主要修改的内容如下:
{
"extends": "@tsconfig/node20/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*",
"plugins/**/*" // 就是添加了这一行
],
// 其他的常规配置
}
步骤四 : 修改 package.json 文件脚本
主要是 :
1.配置 启动脚本 , 此时实际上就是一个普通的 vite 命令
启动完成 vue 项目后,通过我们自定义的插件,再启动electron服务;
4.删除文件中的 type:“module” 行,否则会有一个警告!
{
"name": "electron03vuetest01",
"version": "1.0.0",
"private": true,
"scripts": {
"devall":"vite", // 我们自定义的脚本命令,一键启动
// 其他的脚本命令 。。。
},
// 其他的依赖 等配置信息
}
步骤五 : 启动测试
在命令行中,直接执行命令 :
npm run devall
效果:
1、vite 正常启动 vue3 项目;
2、electron 的 ts 文件被成功编译;
3、electron 启动成功,窗体展示成功。
启动日志如下 :
> electron-vue@0.0.0 devall
> vite & electron .
targetdev目录存在,执行删除
▲ [WARNING] The glob pattern "electron/**/*.js" did not match any files [empty-glob]
编译 electron ts 文件结果 : {......}
服务的信息 : { address: '127.0.0.1', family: 'IPv4', port: 5178 }
服务的端口 : 5178
服务的完整地址 : http://localhost:5178
VITE v5.2.9 ready in 167 ms
➜ Local: http://localhost:5178/
➜ Network: use --host to expose
运行效果 : electron 启动成功且加载vue页面成功!