electron:vue3+vite打包案例
1、安装electron
首先设置镜像源,否则安装会非常非常慢。
打开npm的配置文件。
npm config edit
修改配置项。
registry=https://registry.npmmirror.com
electron_mirror=https://cdn.npmmirror.com/binaries/electron/
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
镜像源设置好后,就可以npm install electron了。
2、安装concurrently
concurrently是本地运行electron需要用到的插件,npm install concurrently即可。
3、electron的main.js和preload.js文件
在项目根目录下,创建electron文件夹,在该文件夹下创建main.js和preload.js。
main.js代码如下:
const {app,BrowserWindow
} = require('electron')
const path = require('node:path')const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, 'preload.js')}})// 连接本机前端页面的端口号win.loadURL("http://localhost:3000")win.webContents.openDevTools()
}app.whenReady().then(() => {createWindow()
})// 关闭所有窗口时,退出
app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()}
})
preload.js代码如下:
由于本案例只是一个demo,功能简单,preload里并无功能性代码,只是为了保证代码项目结构完整性,对应了main.js里的preload: path.join(__dirname, 'preload.js')
const { contextBridge } = require('electron')contextBridge.exposeInMainWorld('versions', {node: () => process.versions.node,chrome: () => process.versions.chrome,electron: () => process.versions.electron// 除函数之外,我们也可以暴露变量
})
在package.json里设置main的路径,也就是我们在根目录下创建的electron文件下的main.js。script里添加启动命令命令。
"main": "electron/main.js",
"scripts": {"dev": "concurrently \"vite\" \"electron .\""}
运行npm run dev,concurrently 会同时启动vite和electron,只启动electron的话,页面会是一片空白。
本地运行结果如下,打开了调试工具:
4、安装electron-builder
electron-builder是用来将项目打包成exe文件的。
之前已经设置了镜像源,此时只需要npm install electron-builder即可。
打包一共需要两个步骤,先用vite打包成dist,然后用electron-builder打包成exe。
所以在package.json的script里,我们将这两个步骤合并一下:
"scripts": {"dev": "concurrently \"vite\" \"electron .\"","build": "vite build && electron-builder"},
还需要进行其他打包设置,比如设置icon路径,icon也放在根目录下的electron文件夹里,target设置为nsis,会生成安装程序的exe;files是打包后需要包含的文件,dist是vite build生成的文件夹,electron文件夹下有main.js和preload.js,package.json里包含了重要的配置信息,所以把它们都放在打包里;directories的output是electron-builder打包后的文件夹名称,设置为release,跟dist文件夹同级。
"build": {"appId": "electron_multiple_languages","win": {"icon": "electron/icon.ico","target": "nsis"},"files": ["dist/**/*","electron/**/*","package.json"],"directories": {"output": "release"}},
打包后不需要显示调试工具了,main.js里需要判断生产环境还是开发环境:
如果是生产环境,需要从dist文件夹的index.html入口,如果是开发环境,连接本地,打开调试工具。
注意端口号不一定是3000,根据你项目实际的端口号来写。
if(app.isPackaged){win.loadFile(path.join(__dirname, '../dist/index.html'))}else{// 连接本机前端页面的端口号win.loadURL("http://localhost:3000")win.webContents.openDevTools()}
执行npm run build命令。
首次使用electron-builder打包时,会到github上去下载winCodeSign和nsis的二进制文件,由于网络问题经常失败。
可以直接去镜像源地址里下载它们:
winCodeSign-2.6.0
nsis需要下载两个包:
CNPM Binaries Mirror
下载好,解压,放在cache目录下:
打包过程中还会遇到其他问题,比如:
icon的分辨率不合规,必须是256*256;
package.json里缺少author和description;
electron和electron-builder必须在devDependencies里。
具体问题按照错误提示来修改即可。
打包后的目录结构:
5、删除dist和release
每次生成的dist文件夹里文件名不相同,如果想要反复打包,dist里的文件是无法自动覆盖的,最好每次都删除dist和release文件夹,需要借助插件rimraf。
npm install rimraf安装,增加删除命令:
"scripts": {"clean": "rimraf dist release","dev": "concurrently \"vite\" \"electron .\"","build": "npm run clean && vite build && electron-builder"},
7、白屏问题
双击release文件夹下的setup.exe文件,安装程序,会在桌面创建快捷方式,双击启动程序,但是会发现一片空白。
这个问题卡了好几个小时,一遍一遍问deepseek,终于找到了问题所在,打包后文件加载要用相对路径,需要在vite.config.js里设置base:'./'
注意,在vite.config.js里是设置base,如果是vue.config.js,是设置publicPath,根据自己项目实际情况来写。
最终运行结果:
完整代码:
electron文件夹下的main.js
const {app,BrowserWindow
} = require('electron')
const path = require('node:path')const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, 'preload.js')}})if(app.isPackaged){win.loadFile(path.join(__dirname, '../dist/index.html'))}else{// 连接本机前端页面的端口号win.loadURL("http://localhost:3000")win.webContents.openDevTools()}
}app.whenReady().then(() => {createWindow()
})// 关闭所有窗口时,退出
app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()}
})
electron文件夹下的preload.js
const { contextBridge } = require('electron')contextBridge.exposeInMainWorld('versions', {node: () => process.versions.node,chrome: () => process.versions.chrome,electron: () => process.versions.electron// 除函数之外,我们也可以暴露变量
})
package.json
{"name": "electron_multiple_languages","version": "0.0.0","author": "demo@163.com","main": "electron/main.js","scripts": {"clean": "rimraf dist release","dev": "concurrently \"vite\" \"electron .\"","build": "npm run clean && vite build && electron-builder"},"build": {"appId": "electron_multiple_languages","win": {"icon": "electron/icon.ico","target": "nsis"},"files": ["dist/**/*","electron/**/*","package.json"],"directories": {"output": "release"}},"dependencies": {"concurrently": "^9.2.0","rimraf": "^6.0.1","vue": "^3.2.8"},"devDependencies": {"@vitejs/plugin-vue": "^1.6.0","@vue/compiler-sfc": "^3.2.6","electron": "^37.2.5","electron-builder": "^26.0.12","vite": "^2.5.2"}
}
vite.config.js
import {defineConfig
} from 'vite'
import vue from '@vitejs/plugin-vue'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],base: './', // 确保资源使用相对路径
})