前言
前几天写了一篇 《why ElectronLab?》来吹嘘自己写的 electron-lab 方案,主要的竞争对手是 electron-forge。从该文可以看出,electron-forge 的竞争力从现在看已经不太足了。随后,在 Umi Contributor 群里给大家 review 了这个方案,大家提的问题主要是和 umi 的生态较为隔离。于是我创建了一个新的 umi 插件,把 electron-lab 的能力直接迁移到 umi 生态,也就是 @umijs/plugin-electron。
有意思的是,发布完 v0.1.0-0 之后,我在 npm 搜了一下关键字「plugin-electron」,居然发现了一个现代前端研发框架 modern-js 的 electron 插件:
这个名字起得太有默契了
本着友好交流、共同进步的原则,本文关注 umi 和 modern-js 的 electron 插件能力对比,也学习同行的优秀设计、规划 @umijs/plugin-electron 的下一步发展。
能力比对
1. 构建流程
umi | morden-js |
---|---|
![]() |
![]() |
总结:
- umi 和 morden-js 都针对依赖作了优化,避免打包多余依赖。
- modern-js 因为根据依赖重新构建了 package.json,用户使用更无感。
- umi 额外产出了 md5 和 version 等信息,可以供用户使用。
2. runtime 能力
electron runtime 能力主要解决了一些底层能力封装的问题:
- 多窗口管理
- 多进程通讯管理
在 electron-lab 0.1.x 时,我也做了一些 runtime 的能力,放置在 electron-lab/src/index.ts 中。后来因为专注打包问题,在 0.2.x 中暂时删除了,因此 @umijs/plugin-electron 暂时还没有 runtime 能力。
modern-js dev 时从 @modern-js/runtime/electron 引入包,但是实际上这个包是 declare 来的,实际包为 @modern-js/electron-runtime。在打包时的 package.json 里使用的也是这个包。
另一些没做 runtime 的原因是:
- 为了可以在常规的社区上找到一些问题。一个不太活跃的生态是没有这些内容沉淀的。
- 一些窗口管理能力其实很简单,就是一个 map
,通讯时找到对应的 key 传输就行
话虽然是这样说,但是 runtime 迟早是要做的,同行的设计也可以参考一下,吸取一些优秀的地方。
截止到 2021.12.14,demo 项目无法跑通
2.1 主进程模块概述
在 modern-js 中,把主进程的各个能力归类,然后封装为一系列 services 供用户调用。另外,进程之前的通讯也抽象为 services,在 main_process > renderer_process > webview 的三层进程中,每一层的进程通讯都是将自己看作 services 供其他层调用;也可以调用其他层的 services(当然 main_process 和 webview 之间不能直接调用)。
2.1.1 Runtime
Runtime 负责初始化设置,包括:
- 窗口列表
- 主进程的服务
- 菜单设置
- …
在 app.ready 的时候,需要手动 await runtime.init();
2.1.2 winServices
窗口管理的一系列 api,内部应该是一个 map<key,BrowserWinodw>
。提供了比如:
sendTo(receiver,channel)
发送消息到指定窗口的指定进程。closeWindowById(id)
关闭指定 id 的窗口。2.1.3 updateServices
更新服务。2.1.4 lifecycleServices
生命周期管理,实际上提供了quit
、kill
、relunch
方法。2.1.5 testServices
可以测试服务。
2.2 渲染进程模块概述
整体看下来,渲染进程也没有太多的新意,工作和主进程基本一致,额外多了一些 services。
2.2.1 browserWindowPreloadApis 和 exposeInMainWorld
对 electron 原生的能力进行了封装,通过 preload.js 对渲染进程暴露主进程能力。
2.2.2 webviewService
webview 的管理服务,针对 webview 方法进行了一些封装。
一句话总结:
- modern-js 的 runtime 对开发常用的能力进行了封装,但是程度有限,主要的思路是将原生能力归类,然后进行一层 oop 封装。
这个 runtime 封装的代码分离不太稳定,我一直没法正常使用。
3. 构建
modern-js 提供了三种构建方法:
构建主进程:
modern build electron-main
- 构建渲染进程:
modern build electron-render
- 构建应用:
modern build electron-app
单独构建可以用在热更新上,目前 umi 只能完整构建一个 app。
但是也可以执行一次完整构建,然后只获取某个构建产物。
4. 升级
总结&规划
- 在打包上,modern 的模式更静默、心智负担轻。
- runtime 是必须要做的,但是也要照顾不爱用 runtime 的用户感受。umi 接下来可以在现有基础上增加对 runtime 的支持。
- 看完 modern-js 的工作之后,感觉 electorn 框架目前还是处于一个很基础的状态。字节走了 OOP,我们也可以在 rxjs、hooks 之类的方向去思考。
- 之前做了一些更高级的封装,例如 Title-Bar,目前 modern-js 还没有。这个还是很有必要的,最近玩构建丢掉了,未来要捡起来继续迭代。
- 周边生态还要搞亿搞。之前拉实习生 @礼检 做了
create-electron-lab
,已经规划让他转到create-umi
上了。 - 之前用 father-build 搞了个魔改版:father-build@1.20.5-5。主要是加了入口路径、出口路径、配置文件路径的支持,期望 @辟起 老师可以在正式版搞定这个需求。