具体使用版本:vite v2.4.3+electron v13.1.7+vue v3.0.5
目录结构如下:
node_modules 依赖包 public vite创建的目录,为vue服务的,实际没多大用 release 打包后编译输出的目录,该目录的根目录下存放打包后的安装包 bundled 该目录存放vue打包后的文件(html js css img等) win-unpacked 该目录存放编译后生成的可执行文件及相关的dll,不包含安装包 resource 资源目录 script 此目录存放各种脚本,比如编译脚本,启动脚本,签名脚本等 src 源码目录 render 渲染进程源码目录 preload (好像不需要也行。估计vue-cli搭建的才需要)vue页面中不能使用nodejs和electron,electron手册中要求通过preload.js隔离vue页面和main.js的交互 main 主进程源码目录 common 两个进程都会用到的共用源码目录 package.json 项目配置文件 index.html vue3的入口页面 .env 配置文件 .gitignore git目录过滤文件
第一步:
通过vite 相关命令 新建一个vue3的项目
参考:https://cn.vitejs.dev/guide/#scaffolding-your-first-vite-project
省略这一步的安装过程
第一步的注意点:
1、cmd 控制台需要管理员权限
第二步:
到项目根目录(vite命令搭建好的项目根目录):
cmd(管理员身份)
cd /d 项目根目录
执行添加 electron 模块
npm i -D electron@latest
第三步:
添加 dotenv 依赖模块
# with npm npm install dotenv # or with Yarn yarn add dotenv
在src/main目录下新建一个 app.ts 文件内容如下:
/**
* electron 主文件
*/
import { join } from 'path'
import { app, BrowserWindow } from 'electron'
import dotenv from 'dotenv'
dotenv.config({ path: join(__dirname, '../.env') })
let win: BrowserWindow;
function createWindow() {
// 创建浏览器窗口
win = new BrowserWindow({
width: 1024,
height: 768,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
//preload:join(__dirname, '../preload/preload.js')
},
})
win.webContents.openDevTools();
const URL = app.isPackaged
? `file://${join(__dirname, '../index.html')}` // vite 构建后的静态文件地址
: `http://localhost:${process.env.PORT}` // vite 启动的服务器地址
win.loadURL(URL);
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
}
)})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})第四步:
添加 @rollup/plugin-node-resolve 依赖:
npm install @rollup/plugin-node-resolve --save-dev
添加 @rollup/plugin-commonjs 依赖:
npm install --save-dev rollup-plugin-commonjs
添加 @rollup/plugin-typescript 依赖:
npm install --save-dev @rollup/plugin-typescript
添加 @rollup/plugin-alias 依赖:
npm install --save-dev @rollup/plugin-alias
添加 @rollup/plugin-json 依赖:
npm install --save-dev @rollup/plugin-json
在script目录下新建rollupjs的配置文件,用于指定编译ts文件转js文件 (rollup.config.ts)
import { join } from 'path';
import { RollupOptions } from 'rollup';
// 为了支持import xx from 'xxx'
import nodeResolve from '@rollup/plugin-node-resolve';
// 为了让rollup识别commonjs类型的包,默认只支持导入ES6
import commonjs from '@rollup/plugin-commonjs';
// ts转js的编译器
import typescript from '@rollup/plugin-typescript';
import alias from '@rollup/plugin-alias';
// 支持加载json文件
import json from '@rollup/plugin-json';
// 读取package.json
import pkg from '../package.json';
import { builtins } from './utils';
export default (env = 'production') => {
const options: RollupOptions = {
input: join(__dirname, '../src/main/app.ts'),
output: [{
file: pkg.main,
format: 'cjs',// 使用 CommonJs 模块化
name: 'ElectronMainBundle',
sourcemap: true,
}
// , {
// file: "dist/preload/preload.js",
// format: 'cjs',// 使用 CommonJs 模块化
// name: 'preload',
// sourcemap: true,
// }
],
plugins: [
typescript({
exclude: 'node_modules/**',
typescript: require('typescript'),
}),
json(),// 支持引入 json 文件
commonjs({
// 支持 CommonJs 模块
include: 'node_modules/**'
}),
nodeResolve(),// 支持 node_modules 下面的包查找
alias({
//路径别名
entries: [
{ find: '@render', replacement: join(__dirname, '../src/render') },
{ find: '@main', replacement: join(__dirname, '../src/main') },
{ find: '@src', replacement: join(__dirname, '../src') },
{ find: '@root', replacement: join(__dirname, '..') },
]
}),
],
external: [
// 打包避开内置模块
...builtins(),
'electron',
],
}
return options
}添加 chalk 依赖模块:
npm install chalk
添加 http 依赖模块:
npm i http
在script新建utils.ts文件 用于监听vite 启动再启动electron
import { builtinModules } from 'module'
import { get } from 'http'
import { green } from 'chalk'
/** 轮询监听 vite 启动 */
export function waitOn(arg0: { port: string | number; interval?: number; }) {
console.log("轮询监听 vite 启动");
return new Promise(resolve => {
const { port, interval = 149 } = arg0
const url = `http://localhost:${port}`
let counter = 0
const timer: NodeJS.Timer = setInterval(() => {
get(url, res => {
clearInterval(timer)
console.log('[waitOn]', green(`"${url}" are already responsive.`), `(${res.statusCode}: ${res.statusMessage})`)
resolve(res.statusCode)
}).on('error', err => {
console.log('[waitOn]', `counter: ${counter++}`)
})
}, interval)
})
}
/** node.js builtins module */
export const builtins = () => builtinModules.filter(x => !/^_|^(internal|v8|node-inspect)\/|\//.test(x))添加minimist 依赖模块:
npm install -g @types/minimist
在script目录下新建 build-main.ts 文件 根据rollup.config.ts配置文件指定的ts文件转js文件
/**
* electron 打包
*/
import { join } from 'path';
import { spawn, ChildProcess } from 'child_process';
import { watch, rollup, OutputOptions } from 'rollup';
import minimist from 'minimist';
import chalk from 'chalk';
import ora from 'ora';
import electron from 'electron';
import dotenv from 'dotenv';
import { waitOn } from './utils';
import options from './rollup.config';
import { main } from '../package.json';
dotenv.config({ path: join(__dirname, '../.env') });
const argv = minimist(process.argv.slice(2));
const opts = options(argv.env);
const TAG = '[build-main.ts]';
const spinner = ora(`${TAG} Electron build...`);
if (argv.watch) {
waitOn({ port: process.env.PORT as string }).then(msg => {
const watcher = watch(opts)
let child: ChildProcess
watcher.on('change', filename => {
const log = chalk.green(`change -- ${filename}`)
console.log(TAG, log)
});
watcher.on('event', ev => {
if (ev.code === 'END') {
if (child) child.kill()
child = spawn(
electron as any,
[join(__dirname, `../${main}`)],
{
stdio: 'inherit',
env: Object.assign(process.env, { NODE_ENV: argv.env }),
})
} else if (ev.code === 'ERROR') {
console.log(ev.error)
}
});
});
} else {
spinner.start();
rollup(opts)
.then(build => {
spinner.stop()
console.log(TAG, chalk.green('Electron build successed.'))
build.write(opts.output as OutputOptions)
})
.catch(error => {
spinner.stop()
console.log(`\n${TAG} ${chalk.red('构建报错')}\n`, error, '\n')
});
}第五步:
配置 package.json 文件
首先添加 concurrently 依赖模块
npm install -g concurrently
然后修改package.json如下:

{
"name": "electron-vue",
"version": "0.0.0",
"main": "dist/main/app.js",
"license": "MIT",
"scripts": {
"dev": "concurrently -n=vue,ele -c=green,blue \"npm run dev:vue\" \"npm run dev:ele\"",
"dev:vue": "vite",
"dev:ele": "node -r ts-node/register script/build-main --env=development --watch",
"build": "vue-tsc --noEmit && vite build",
"serve": "vite preview"
},
"dependencies": {
"chalk": "^4.1.1",
"concurrently": "^6.2.0",
"dotenv": "^10.0.0",
"fs-extra": "^8.1.0",
"ora": "^5.4.1",
"vue": "^3.0.5"
},
"devDependencies": {
"@rollup/plugin-alias": "^3.1.4",
"@rollup/plugin-commonjs": "^19.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.0.2",
"@rollup/plugin-typescript": "^8.2.3",
"@types/minimist": "^1.2.2",
"@vitejs/plugin-vue": "^1.2.5",
"@vue/compiler-sfc": "^3.0.5",
"electron": "^13.1.7",
"electron-chromedriver": "^13.0.0",
"ts-node": "^10.1.0",
"typescript": "^4.3.2",
"vite": "^2.4.3",
"vue-tsc": "^0.0.24"
},
"keywords": [
"vite",
"electron",
"vue3",
"rollup"
]
}第六步:
配置 tsconfig.json

{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
// 目标文件所在路径
"outDir": "./dist",
"baseUrl": "./",
"lib": ["esnext", "dom","ES6"],
"paths": {
"@render/*": ["src/render/*"],
"@main/*": ["src/main/*"],
"@src/*": ["src/*"],
"@root/*": ["./*"]
},
"allowSyntheticDefaultImports": true
},
"ts-node": {
"compilerOptions": {
"module": "CommonJS"
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "script/*.ts"]
}第七步:
配置 vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { join } from 'path';
require('dotenv').config({ path: join(__dirname, '.env') })
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
server: {
port: parseInt(process.env.PORT),
},
build: {
outDir: join(__dirname, 'dist/render'),
assetsDir: '', // 相对路径 加载问题
rollupOptions: {
output: {
format: 'cjs', // 配置 Rollup 打包输出 CommonJs 格式
},
external: ['electron'], // 告诉 Rollup 不要去打包 electron
},
},
optimizeDeps: {
exclude: ['electron'], // 告诉 Vite 不要转换 electron 模块
},
});第八步:
修改根目录的index.html

然后运行:
npm run dev
效果:

第九步:引用electron API或者Node API
vue组件内:
const electron = window.require('electron');
const fse = window.require('fs-extra')
const fs = window.require('fs')效果:

.env文件内容:

评论区