electron制作小程序上传工具总结
上个月写了个小程序的打包上传小工具,技术栈是 electron+vite3+vue3+ts+pinia+element-plus,将这次开发的经历做下记录,如下。
# 起因
我们的小程序项目是有沉重历史包袱的 uniapp 项目,承载了两百多个页面,即使使用了分包,主包大小也快接近 2M 了(包含插件),总包大小约 5M 多。我们在修改完一条测试 bug 时,打包过程如下:
uniapp 打包小程序包,约 2min。
使用开发者工具打开该项目,约 30s(个别电脑会更慢)。
点击上传,开发者工具进行打包和上传,约 2min。
完成。
可以看到,主要耗时在于第 2 步和第 3 步,开发者在修复 bug 和开发联调中,不得不中途打开开发者工具打开项目,然后再打包上传。这个操作不仅中断了开发节奏,降低开发效 率,也会让人在等待中心情烦躁。
基于此,我终于忍无可忍,决定干点什么。如果开发者只需要关注 bug 修复后,直接点击一个按钮,就可以完成 123,岂不美哉。
# 技术选型
需求已经明确了,就是让自动替代手动,那么摆在面前的是以下几个方案:
命令行工具
桌面端应用
vscode 插件
对于需求实现而言,这 3 个方案都不错,对比如下。
优点 | 缺点 | |
---|---|---|
命令行工具 | 操作简单,一行命令搞定 | 需要切换 npm 源;配置参数多了之后让操作变得复杂 |
桌面端应用 | 可视化 UI 界面,点击按钮即可操作;方便管理和查看项目信息 | 需要安装应用(约 100 多 M) |
vscode 插件 | 直接在 vscode 快捷键操作,最简便 | 难以管理项目信息 |
尽管命令行和 vscode 插件操作简便,但难以管理多个项目;我最终选择了基于 electron 的桌面端应用。既然是前端项目,当然是选择前沿且成熟的技术了,最终在 github 找了个 不错的模板 (opens new window)。所应用的技术都是最新的,包括
electron
vite3
vue3
typescript
pinia
element-plus
# 功能展示
- [ ] 管理前端项目,包括新建和删除项目、安装必要依赖、配置项目信息和打包上传参数等
[ ] 展示项目列表和项目详情及当前状态信息
[ ] 管理小程序信息
[ ] 打包项目(演示)
[ ] 上传小程序到微信小程序平台(演示)
- [ ] 增量更新
[ ] 打包上传完成后桌面通知
[ ] 终端日志滚动显示
# 踩坑记录
安装 electron 慢
本人就在安装时遇到了慢的问题,即使是翻墙也无法提高下载速度。尝试了下载淘宝的安装包到本地缓存也没成功,最终是设置镜像解决。
npm config set ELECTRON_MIRROR http://npm.taobao.org/mirrors/electron/
渲染进程如何调用 Node API
比如说,想在渲染进程使用
const path = require('path')
,结果报错了Uncaught ReferenceError: require is not defined
1需要在主进程中开启设置。见文档 (opens new window)。
new BrowserWindow({ height: 800, useContentSize: true, width: 600, webPreferences: { contextIsolation: false, nodeIntegration: true, // 渲染进程可以使用Node API webSecurity: false, // 如果是开发模式可以使用devTools devTools: process.env.NODE_ENV === 'development', // 在macos中启用橡皮动画 scrollBounce: process.platform === 'darwin' } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15减小安装包体积
使用 electron-builder 打包后,发现安装包特别大,因为:
- electron 应用集成了整个 V8 引擎和 Chromium 内核
- 项目中的 node_modules 会被打包进安装包
这样,即使是打包了一个空应用,安装包体积也能达到 60M,解压后更是超过 100M。第一点我们无法改变,但可以针对第二点进行优化。
electron-builder 会将 dependencies 中的所有依赖全部打包,所以渲染进程中的依赖不要放在该对象下,而是放在 devDependencies 中, 见文档 (opens new window)。
此外,由于小程序上传库miniprogram-ci (opens new window)所包含的依赖非常大,且包含大量的 dependencies 依赖,会导致 2 个问题:
- electron 打包非常慢,每次打包都要将 node_modules 打包到安装包,打包时间由 2min 延长至 10min+。
- 打包的安装包非常大,仅安装包就达到 100M,远超之前的 65M,安装时长由 1min 延长至 10min。
为了解决这个依赖包体积问题,我设想过几个方案:
既然打包时是在 dependencies,那放到 devDependencies 中,然后在 renderer 进程中打包就好了。(结果是想法太天真,miniprogram-ci 有大量的 node 运行时调用,这些依 赖没有经 electron 打包,打开安装包后会运行报错)
牺牲打包体验,牺牲第一次安装体验,后续做成增量更新后,几乎是秒级更新。
抛弃 miniprogram-ci 上传方式,采用http 调用 (opens new window)方案。
miniprogram-ci 有命令行模式,需要全局安装,所以需要使用者预先执行命令进行全局安装 miniprogram-ci,之后在上传时采用命令行方式进行编译上传,如下:
// 转化为miniprogram-ci 命令行 const generateCommand = (miniInfo) => { let command = 'miniprogram-ci upload' const map = { projectPath: '--pp', appid: '--appid', privateKey: '--pkp', version: '--uv', robot: '-r', desc: '--ud' } for (let item of Object.keys(miniInfo)) { command += ` ${map[item]} ${miniInfo[item]}` } console.log(command) return command } const miniInfo: MiniProjectInfo = { projectPath, appid: projectInfo.appid, privateKey: `${privateKeyPath}/private.${projectInfo.appid}.key`, version: projectInfo.version, robot: projectInfo.robot, desc: projectInfo.desc, } const command = generateCommand(miniInfo) await runCommand(command)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22既然全局命令行可以,那放到安装包解压缩的地方是否也可以?答案是肯定的。那就采用该方案,只需要做好上传前的弹窗引导即可。
总结下,该方案就是将 miniprogram-ci 这个超大的依赖作为插件的方式交给使用者去安装,这样就解决了前面提到的 2 点问题。
mac 兼容性问题
打包后,mac 下无法识别 shell 命令问题描述:
/bin/sh: node: command not found
1见issue (opens new window)。 社区的解决方案是fix-path (opens new window)。
文件路径问题见文件路径-区分 windows 和 linux 系统的斜杠 (opens new window),所以在获取到文件路径后,如果要获取到 文件名,需要注意替换斜杠。
// 兼容window/linux form.name = form.path.slice(form.path.replaceAll('\\', '/').lastIndexOf('/') + 1)
1
2
# 心得体会
- 面临重复且耗时的操作,是否有更好的方案解决,just do。
- 如何在开发体验和用户体验之间找到平衡点,技术上的问题首先用技术解决,然后才是交互降级。
- 路漫漫其修远兮,持续学习前沿技术。
# 相关链接
electron 文档 (opens new window)
解决 electron 安装慢的问题 (opens new window)
electron-builder (opens new window)