创建electron+vite+vue项目
create-electron-vite TestProject
运行效果如图所示:
cd TestProject
进入项目根目录后,执行项目依赖包安装指令
npm install
运行结果如下:
执行依赖性安装失败
可能是由于下载源有问题,更换下载源即可。操作如下:
找到 C:\Users\用户名.npmrc 文件,该文件为隐藏文件。在文件末尾加入此段代码
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
electron_custom_dir={{ version }}
electron_mirror=https://cdn.npmmirror.com/binaries/electron/v
registry=https://registry.npmmirror.com/
如下图所示:
项目打包
npm run build
如果打包过程中报错,找不到打包工具,则手动下载打包工具即可。
参考此文章
https://blog.csdn.net/qq_45897239/article/details/138490747?spm=1001.2014.3001.5502
或者直接去此处下载
https://download.csdn.net/download/qq_17129291/89772698
(下载前注意报错提示的版本与此资源描述版本是否一致),下载后将文件解压,直接放在C:\Users\用户名\AppData\Local文件夹下。如图:
加入express
安装express及相关依赖包
npm install express cors morgan cookie-parser get-port axios
在项目根目录加server文件夹
其中app.ts内容如下:
var express = require('express');
var appPath = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var cors = require('cors');
// 加载路由文件
const indexRouter = require(appPath.join(__dirname,'./routes/index.ts'));
var app = express();
// 解决跨域
app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use('/api/index', indexRouter);
// ----------------------
const http = require("http");
const server = http.createServer(app);
// var port = normalizePort(process.env.PORT || "3000");
// 导出启动服务器的函数
async function startServer(port) {
app.set("port", port);
return new Promise((resolve, reject) => {
server.listen(port, () => {
console.log(`Server listening on port ${port}`);
resolve(server);
});
server.on("error", (error) => {
reject(error);
});
});
}
// 停止服务器
async function stopServer() {
return new Promise((resolve) => {
server.close(() => {
console.log("Server stopped");
resolve('');
});
});
}
module.exports = {
startServer,
stopServer
};
routes/index.ts内容如下:
const router = require('express').Router();
router.get('/', function (req, res) {
res.send('hello express !!!');
});
module.exports = router;
更改electron/main.ts如下:
import { app, BrowserWindow } from 'electron'
import { createRequire } from 'node:module'
import { fileURLToPath } from 'node:url'
import path from 'node:path'
// get-port => 查找可用端口
import getPort, { portNumbers } from "get-port";
const require = createRequire(import.meta.url)
const __dirname = path.dirname(fileURLToPath(import.meta.url))
// 导入 express 启动服务函数
const { startServer, stopServer } = require(path.join(__dirname, "../server/app.ts"));
// The built directory structure
//
// ├─┬─┬ dist
// │ │ └── index.html
// │ │
// │ ├─┬ dist-electron
// │ │ ├── main.js
// │ │ └── preload.mjs
// │
process.env.APP_ROOT = path.join(__dirname, '..')
// 🚧 Use ['ENV_NAME'] avoid vite:define plugin - Vite@2.x
export const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL']
export const MAIN_DIST = path.join(process.env.APP_ROOT, 'dist-electron')
export const RENDERER_DIST = path.join(process.env.APP_ROOT, 'dist')
process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL ? path.join(process.env.APP_ROOT, 'public') : RENDERER_DIST
let win: BrowserWindow | null
function createWindow() {
win = new BrowserWindow({
icon: path.join(process.env.VITE_PUBLIC, 'electron-vite.svg'),
webPreferences: {
preload: path.join(__dirname, 'preload.mjs'),
},
})
// Test active push message to Renderer-process.
win.webContents.on('did-finish-load', () => {
win?.webContents.send('main-process-message', (new Date).toLocaleString())
})
if (VITE_DEV_SERVER_URL) {
win.loadURL(VITE_DEV_SERVER_URL)
} else {
// win.loadFile('dist/index.html')
win.loadFile(path.join(RENDERER_DIST, 'index.html'))
}
}
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
win = null;
// 停止 express 服务
stopServer();
}
})
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
// app.whenReady().then(createWindow)
app.whenReady().then(async () => {
try {
// 使用 getPort 查找可用端口 (范围 3000 ~ 3100)
const port = await getPort({ port: portNumbers(3000, 3100) });
// 启动 express 服务
await startServer(port);
createWindow();
} catch (error) {
console.error("Failed to start server:", error);
}
});
更改src/App.vue如下:
<template>
<div>
<a href="https://electron-vite.github.io" target="_blank">
<img src="/electron-vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<HelloWorld msg="Vite + Vue" />
</template>
<script setup lang="ts">
import HelloWorld from './components/HelloWorld.vue'
import { onMounted } from "vue";
import axios from "axios";
onMounted(async () => {
let res = await axios.get('http://localhost:3000/api/index');
console.log(res);
})
</script>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>
启动项目
测试express是否加入成功。
npm run dev
运行后在electron的控制台看到输出则项目搭建完毕。
如图:
其他打包配置
更改tsconfig.json的include参数
"include": ["server/**/*.ts","src/**/*.ts", "src/**/*.tsx", "src/**/*.vue", "electron"]
打包可能由typescript检查模式引起错误,故此处可将其相关设置暂设为false。
tsconfig.json内compilerOptions属性的以下几个子属性。
/* Linting */
"strict": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": false
修改electron-builder.json5的files属性
"files": [
"dist",
"dist-electron",
"server/**/*"
],
参考资料:
https://blog.csdn.net/qq_45897239/article/details/140399147?utm_source=miniapp_weixin