具体使用版本: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文件内容:
评论区