首先使用vite
工具创建一个vue3+ts
的项目
npm create vite
创建好vue+ts项目后
启动项目
cd electron-vue3-ts-vite
npm install
npm run dev
访问http://127.0.0.1:5173/
地址可以看到项目已经启动成功
安装Electron
接下来我们安装electron
,使用以下命令
npm i -D electron
同时,在根目录创建一个electron
文件夹,并在里面新建两个文件,分别是main.ts
和preload.ts
。
// main.ts
// 控制应用生命周期和创建原生浏览器窗口的模组
const { app, BrowserWindow } = require("electron");
const path = require("path");
function createWindow() {
// 创建浏览器窗口
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
// 引入预加载文件
preload: path.join(__dirname, "preload.js"),
},
});
// 加载vite启动的本地服务
// mainWindow.loadURL("http://localhost:5173");
// 判断当前环境是否为开发环境
if (process.env.NODE_ENV === "development") {
// 当处于开发环境时,页面加载本地服务,并自动打开开发者工具
mainWindow.loadURL("http://127.0.0.1:5173");
mainWindow.webContents.openDevTools();
} else {
// 否则页面加载打包后的index.html文件
mainWindow.loadFile(path.join(__dirname, "./index.html"));
}
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow();
app.on("activate", function () {
// 通常在 macOS 上,当点击 dock 中的应用程序图标时,如果没有其他
// 打开的窗口,那么程序会重新创建一个窗口。
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});
// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此,通常对程序和它们在
// 任务栏上的图标来说,应当保持活跃状态,直到用户使用 Cmd + Q 退出。
app.on("window-all-closed", function () {
if (process.platform !== "darwin") app.quit();
});
// preload.ts
// 这里我们随便写一句话
console.log("preload");
由于main.ts
和preload.ts
均为ts文件,需要编译为js
文件,因此在tsconfig.json
中进行配置:
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": false, // 这里设为false
"resolveJsonModule": true,
"isolatedModules": false, // 这里设为false
"noEmit": false, // 这里设为false
"outDir": "dist", // 这里设置输出文件和vite打包后的文件一致,保证main.js和preload.js和打包后的index.html在同一路径
"jsx": "preserve",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
// "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"include": ["electron/*.ts"], // 要编译的文件
"references": [{ "path": "./tsconfig.node.json" }]
}
之后再package.json
中进行配置:
{
"name": "test-project",
"private": true,
"version": "0.0.0",
"main": "dist/main.js", //设置入口文件,即main.ts编译后的文件
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build", // 这里需要在vue-tsc后面加上 --noEmit
"preview": "vite preview",
"electron:dev":"tsc && electron ." // 这里是启动electron命令,先通过tsc编译ts文件,再运行electron .
},
···
}
由于我们在main.ts
使用加载本地服务的方式来访问vue
页面,因此我们需要先启动本地服务。
npm run dev
等待服务开启,运行以下命令即可打开electron窗口:
npm run electron:dev
至此,一个简单的electron+vue3+ts+vite
应用就创建完成了。
当我们重新启动项目时会发现页面为空白,也不能自动打开开发者工具
// main.ts
···
// 判断当前环境是否为开发环境
if (process.env.NODE_ENV === "development") {
// 当处于开发环境时,页面加载本地服务,并自动打开开发者工具
mainWindow.loadURL("http://localhost:5173");
mainWindow.webContents.openDevTools();
} else {
// 否则页面加载打包后的index.html文件
mainWindow.loadFile(path.join(__dirname, "./index.html"));
}
···
在main.ts文件中,process.env.NODE_ENV
并不等于development
,因此页面会去加载同一层级的index.html
,这是因为我们在运行命令时并没有把NODE_ENV
加进来,但由于跨平台,直接在命令前添加NODE_ENV=development
会报错,因此我们需要使用cross-env
这个工具来解决。
安装cross-env
npm i -D cross-env
然后,我们需要修改package.json
文件中的electron:dev
命令:
···
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"electron:dev": "tsc && cross-env NODE_ENV=development electron ." // 在 electron . 前增加 cross-env NODE_ENV=development
},
···
修改完之后,我们再次运行npm run electron:dev
命令,发现页面可以正常加载,并且自动打开开发者工具。
在启动项目时,每次都需要先开启本地vite
服务,等待服务开启之后,才能进行启动electron
并加载合适的页面,但这不免有些麻烦,这时有些小伙伴可能会提出,我们把这些命令写在一行,用&&
符号连接起来不就好了,这看似很合理,但其实不行,这是因为当我们运行完 npm run dev
时,后面的命令并不会继续执行,不信的小伙伴可以尝试一下。
为了解决这个问题,我们需要concurrently
和 wait-on
这两个工具,其中:
concurrently
可以帮助我们同时运行多个命令wait-on
可以帮助我们等待某个命令执行完之后再去执行后面的命令
因此我们来安装这两个工具:
npm i -D concurrently wait-on
同时,我们需要修改package.json
文件:
···
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"electron":"wait-on tcp:5173 && tsc && cross-env NODE_ENV=development electron .", // 等待5173端口服务开启,再去运行之后的命令
"electron:dev": "concurrently -k \"npm run dev\" \"npm run electron\"" // 同时运行多个命令
},
···
修改好之后,再去运行npm run electron:dev
命令,就可以一键启动electron
项目了
electron
项目的打包
electron
打包主要用到的工具为electron-builder
,首先安装该工具:
npm i -D electron-builder
然后,在package.json
文件中增加build
配置项,并进行如下配置:
···
"build":{
"appId": "my-app", // app的id
"productName": "el-vue-test", // 项目名称
"copyright": "Copyright © 2021 <condingandsleeping>", // 版权信息
"mac": { // mac中的相关打包配置
"category": "public.app-category.utilities"
},
"nsis": { // windows中安装程序配置
"oneClick": false,
"allowToChangeInstallationDirectory": true
},
"files": [
"dist" // 要打包的文件夹
],
"directories": {
"buildResources": "assets",
"output": "build" // 输出文件夹
}
}
···
除了以上配置之外,还有很多相关配置,具体可以查阅electron-builder
的官方文档。
同时,在package.json
文件中增加命令electron:build
:
···
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"electron": "wait-on tcp:5173 && tsc && cross-env NODE_ENV=development electron .",
"electron:dev": "concurrently -k "npm run dev " "npm run electron"",
"electron:build":"npm run build && tsc && electron-builder" // 打包命令,执行顺序为 vite打包、tsc编译、electron打包
},
···
最后,修改vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
base:"./", // 增加相对路径配置项,保证index.html可以找到打包后的js和css文件
plugins: [vue()],
})
执行npm run electron:build
进行打包,打包后会增加两个文件夹,具体的文件目录为
···
dist
-assets
-index.html
-main.js
-preload.js
-vite.svg
build
-win-unpacked
-builder-debug.yml
-builder-effective-config.yaml
-test-project Setup 0.0.0.exe
-test-project Setup 0.0.0.exe.blockmap
···
至此,一个完整的electron项目就打包完成了
完整的配置文件如下:
// package.json
{
"name": "test-project",
"private": true,
"version": "0.0.0",
"main": "dist/main.js",
"scripts": {
"dev": "vite",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"electron": "wait-on tcp:5173 && tsc && cross-env NODE_ENV=development electron .",
"electron:dev": "concurrently -k "npm run dev " "npm run electron"",
"electron:build":"npm run build && tsc && electron-builder"
},
"dependencies": {
"vue": "^3.2.47"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.1.0",
"concurrently": "^8.0.1",
"cross-env": "^7.0.3",
"electron": "^24.2.0",
"electron-builder": "^23.6.0",
"typescript": "^4.9.3",
"vite": "^4.2.0",
"vue-tsc": "^1.2.0",
"wait-on": "^7.0.1"
},
"build":{
"appId": "my-app",
"productName": "test-project",
"copyright": "Copyright © 2021 <xxx>",
"mac": {
"category": "public.app-category.utilities"
},
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
},
"files": [
"dist"
],
"directories": {
"buildResources": "assets",
"output": "build"
}
}
}
// tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": false,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": false,
"outDir": "dist"
},
"include": ["electron/*.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
base:"./",
plugins: [vue()],
})