这些零碎的思想,是树叶沙沙之声;它们在我的心里,欢快地低语者。
接到的需求是将我们vue3项目打包成桌面应用,由于我们的项目是用vue-cli创建的,所以当时我用vue-cli-plugin-electron-builder去完成打包操作,中间踩了不少坑,会把遇到的问题记录下来,并分享给大家,但是我们今天核心的分享内容是基于vite的项目,所以vue-cli-plugin-electron-builder一笔带过。
vue-cli-plugin-electron-builder
1. 依赖包之间的版本冲突
我遇到的第一个问题就是版本问题,electron31.2.1要求最低的node版本是18,在项目里有这样一个包@achrinza/node-ipc9.2.3,我倒没有仔细去看是哪个包依赖的(我有点怀疑是vue-cli创建项目带进来的),总之node-ipc支持node的最高版本是17,尴尬了呀,搜索发现也有人遇到了这个问题,大家把node-ipc升级至9.2.5就能完美解决,ok搞定。(自己注意npm缓存哦)
@achrinza/node-ipc
是一个 Node.js 模块。它主要用于在 Node.js 环境中实现进程间通信(IPC)。
2. Error: error:0308010C:digital envelope routines::unsupported
主要是因为 nodeJs V17 版本发布了 OpenSSL3.0 对算法和秘钥大小增加了更为严格的限制,nodeJs v17 之前版本没影响,但 V17 和之后版本会出现这个错误。
在执行指令前加SET NODE_OPTIONS=–openssl-legacy-provider,如下
1
| "build": "SET NODE_OPTIONS=--openssl-legacy-provider && electron:build",
|
1 2
| Linux & Mac OS:export NODE_OPTIONS=--openssl-legacy-provider Windows:set NODE_OPTIONS=--openssl-legacy-provider
|
3. 打包网络问题
electron打包的时候会在github上下载nsis等等包,所以需要我们改一下镜像。(自己注意npm缓存哦)
1 2 3 4
| 在控制台输入 npm config edit 弹出配置文件,把下面的镜像地址加入 electron_mirror=https://npmmirror.com/mirrors/electron/ electron-builder-binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
|
4. 图标更换问题
在目录创建一个icons的文件夹,然后放入256256的ico格式,名为*icon**的文件即可,electron build的时候,会去更换。ico的格式,有在线转换工具的。
ok,接下来用自己家电脑,把vite vue从头打一遍
这里因为是vite vue所以,我选择用electron-build来打。
我们是用electron去打包,而不是基于electron去开发,所以electron相关的包只用于开发过程,所以要装到devDependencies里
1 2
| 安装相关依赖 yarn add electron electron-builder -D
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 在根目录创建main.js文件 const { app, BrowserWindow, } = require('electron') const path = require('path') // 创建一个浏览器窗口 function createWindow() { const mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true, // 允许在渲染进程中使用node api contextIsolation: false, // 禁用上下文隔离,使得渲染进程和预加载脚本运行在同一个上下文中 enableRemoteModule: true, 启用了 remote 模块,使得渲染进程可以访问主进程的功能 }, }) mainWindow.loadFile(path.resolve(__dirname, './dist/index.html')) // 加载指定路径的HTML文件 }
app.whenReady().then(() => { createWindow() // 当 Electron 初始化完成并且准备好创建浏览器窗口时,调用 createWindow 函数 app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit() })
|
1 2 3 4 5 6 7 8 9 10 11 12
| 同样在根目录创建preload.js // 它的主要作用是在渲染进程(即网页)加载之前,预先加载一些必要的代码和资源 window.addEventListener('DOMContentLoaded', () => { const replaceText = (selector, text) => { const element = document.getElementById(selector) if (element) element.innerText = text } for (const dependency of ['chrome', 'node', 'electron']) { replaceText(`${dependency}-version`, process.versions[dependency]) } })
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 在创建一个打包配置文件electron-builder.json { "productName": "electron-build-test", "files": ["./main.js", "./dist"], "directories": { "output": ".build" }, "win": { "target": [ { "target": "nsis", "arch": [ "x64", "ia32" ] } ], "icon": "icons/icon.ico" } }
|
然后根目录创建一个icons文件,放一张icon.ico
1 2 3
| package.json 然后我们需要删除type:module,这会导致打包的时候报错,具体原因我也没仔细研究,嘿嘿 "electron:build": "vite build & electron-builder build --config electron-builder.json"
|
1 2
| vite.config.js base: "./", // 应用的相对路径
|
执行yarn electron:build
,搞定
我们在打包过程中可以看到这个
同样去package.json加上这些属性,而且应用的默认菜单也太丑了,我们去main.js加入mainWindow.setMenu(null)去隐藏默认菜单。
既然打包搞定了,那就再整个electron热更新吧,不然调试起来费劲,每次都要重新打包
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| yarn add concurrently wait-on electron-reload -D concurrently: 命令行工具,用于同时运行多个命令。它允许你在一个终端窗口中并行运行多个脚本。 wait-on: 命令行工具,用于等待某个资源(如文件、端口、HTTP 接口等)可用,然后再执行其它命令。 electron-reload: 用于自动重载的工具,当文件系统中的文件发生变化时,它会自动重载 Electron 应用。
package.json "serve": "concurrently \"vite\" \"wait-on http://localhost:3000 && electron .\"", // 这里我们监听的端口是3000
vite.config.js server: { port: 3000, hmr: true, // 热更新 }, 然后我们再main.js的createWindow函数里新增监听 let isDebug = true; // 配置热更新 if (isDebug) { const elePath = path.join(__dirname, './node_modules/electron') require('electron-reload')('./', { electron: require(elePath), }) // 热更新监听窗口 mainWindow.loadURL('http://localhost:3000') // 打开开发工具 mainWindow.webContents.openDevTools() } else { // 生产环境中要加载文件,打包的版本 // Menu.setApplicationMenu(null) // 加载 index.html mainWindow.loadFile(path.resolve(__dirname, './dist/index.html')) // 新增 }
|
ok,到这里热更新也搞定了,就是打包的时候记得把isDebug修改为false
我的微信公众号: 梨的前端小屋