背景
Electron和Vite都有各自的应用场景。单独运行Electron或者Vite工程是非常容易的,官方文档有详细的教程。但是把两者结合起来有一些要注意的地方。本文通过搭建一个Electron + Vite的示例应用来说明两者结合的方式及存在的问题。
1、启动Vite
用Vite脚手架创建一个工程,指定工程名称,其余保持默认即可。
npm create vue@latest
命令行安装Vite
进入工程文件夹,安装依赖
npm install
执行启动命令
npm run dev
命令行启动Vite
通过链接可访问Vite工程,可以看到这是一个传统的Web前端页面。
Vite启动页面
2、启动Electron
npm install --save-dev electron
这里electron作为开发依赖就可以,为什么生产环境不需要,官方给出了解释
要运行electron工程,必须在package.json中指定入口点文件(main),此外为了方便增加一条启动electron工程的命令
Electron配置
此时已存在src/main.js,但这是Vite的main.js
Vite的main.js
在根目录下创建electron的main.js
const { app, BrowserWindow } = require('electron')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
win.loadFile('index-electron.html')
}
app.whenReady().then(() => {
createWindow()
})
Electron的main.js
创建electron窗口加载的网页,由于vite已经有了一个index.html,electron的html我们叫它index-electron.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<meta
http-equiv="X-Content-Security-Policy"
content="default-src 'self'; script-src 'self'"
/>
<title>Hello from Electron renderer!</title>
</head>
<body>
<h1>Hello from Electron renderer!</h1>
<p>👋</p>
</body>
</html>
Electron加载的html页面
执行以下命令启动Electron桌面端应用程序
npm run start:electron
Electron桌面应用
3、Electron + Vite
Vite启动拿到的是一个url,正好electron有加载URL地址的api。这样Electron就可以通过Vite工程的地址将Vite包含进来。
Electron加载URL的API
对main.js做如下修改
Electron加载Vite发布的URL
启动两个命令行窗口,一个启动vite,另一个启动electron,可以看到electron成功加载了vite的网页
Vite加载到Electron的效果
启动两个命令行窗口毕竟麻烦,这里可以安装npm-run-all三方库来并行执行
npm install npm-run-all --save-dev
在package.json里加入并行执行的命令,需要时执行即可
"dev:all": "npm-run-all -p dev start:electron"
并行启动Electron和Vite
开发环境下可以这么用,生产环境下需要调整。在执行npm run build之后会生成一个dist文件夹,生产环境下调用该文件夹的网页内容
npm run build
生产环境Vite的dist文件夹
因此,为了兼顾生产环境需要在main.js中做如下修改
Electron中区分开发环境和生产环境
main.js最终代码文本如下
const { app, BrowserWindow } = require('electron')
const isDev = app.isPackaged !== 'true';
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600
})
// win.loadURL('http://localhost:5173/')
if (isDev) {
win.loadURL('http://localhost:5173/');
} else {
win.loadFile(path.join(__dirname, 'dist', 'index.html'));
}
}
app.whenReady().then(() => {
createWindow()
})
Electron的main.js文件
执行npm run dev:all可以看到结合的效果
npm run dev:all
Electron结合Vite
4、Vite中使用Node.js(不推荐)
Electron桌面应用往往需要调用Node.js的API,而我们这种方案其实只是把Electron当一个“壳”,内容全靠Vite提供。那么要调用Node.js的API只能在Vite(网页)中完成。
通过rollup-plugin-node-polyfills插件可以让浏览器支持部分Node.js API,但支持的很不全,基本上没有实用价值。
结语
经过一段时间的实践,发现Electron结合Vite的方案实用性有所不足,不能很方便的操作Node.js和Electron提供的本地桌面应用开发能力。(花时间走通的方案又被自己否定了,有点小小的可惜)
后来我在实际应用中没有用Vite脚手架,而是引入Vue的预编译包,把Vue当作一个界面库来用。Electron部分把主进程(main)、渲染器进程(renderer)、预加载脚本(preload)、网页(html)、样式(css)、静态库(public)等几个部分分离开来。组织结构如下图所示。
实际开发中的组织结构
如果只是想给网页套个桌面的壳子,可以使用本文介绍的这种Electron + Vite的方案;如果想深入的开发本地桌面应用程序,还是自己组织模块然后用webpack + Electron Forge打包为好。