前言

前几天写了一篇 《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 插件:
image.png

这个名字起得太有默契了

本着友好交流、共同进步的原则,本文关注 umi 和 modern-js 的 electron 插件能力对比,也学习同行的优秀设计、规划 @umijs/plugin-electron 的下一步发展。

能力比对

1. 构建流程

umi morden-js
image.png image.png

总结:

  1. umi 和 morden-js 都针对依赖作了优化,避免打包多余依赖。
  2. modern-js 因为根据依赖重新构建了 package.json,用户使用更无感。
  3. umi 额外产出了 md5 和 version 等信息,可以供用户使用。

2. runtime 能力

electron runtime 能力主要解决了一些底层能力封装的问题:

  1. 多窗口管理
  2. 多进程通讯管理

在 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 的原因是:

  1. 为了可以在常规的社区上找到一些问题。一个不太活跃的生态是没有这些内容沉淀的。
  2. 一些窗口管理能力其实很简单,就是一个 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 负责初始化设置,包括:

  1. 窗口列表
  2. 主进程的服务
  3. 菜单设置

在 app.ready 的时候,需要手动 await runtime.init();

2.1.2 winServices

窗口管理的一系列 api,内部应该是一个 map<key,BrowserWinodw>。提供了比如:

  1. sendTo(receiver,channel) 发送消息到指定窗口的指定进程。
  2. closeWindowById(id) 关闭指定 id 的窗口。

    2.1.3 updateServices

    更新服务。

    2.1.4 lifecycleServices

    生命周期管理,实际上提供了 quitkillrelunch 方法。

    2.1.5 testServices

    可以测试服务。

2.2 渲染进程模块概述

整体看下来,渲染进程也没有太多的新意,工作和主进程基本一致,额外多了一些 services。

2.2.1 browserWindowPreloadApis 和 exposeInMainWorld

对 electron 原生的能力进行了封装,通过 preload.js 对渲染进程暴露主进程能力。

2.2.2 webviewService

webview 的管理服务,针对 webview 方法进行了一些封装。

一句话总结:

  1. modern-js 的 runtime 对开发常用的能力进行了封装,但是程度有限,主要的思路是将原生能力归类,然后进行一层 oop 封装。
  2. 这个 runtime 封装的代码分离不太稳定,我一直没法正常使用。

    3. 构建

    modern-js 提供了三种构建方法:

  3. 构建主进程:modern build electron-main

  4. 构建渲染进程:modern build electron-render
  5. 构建应用:modern build electron-app

单独构建可以用在热更新上,目前 umi 只能完整构建一个 app。

但是也可以执行一次完整构建,然后只获取某个构建产物。

4. 升级

字节应该内部有一个更新服务器,蚂蚁内没有资源做,pass。

总结&规划

  1. 在打包上,modern 的模式更静默、心智负担轻。
  2. runtime 是必须要做的,但是也要照顾不爱用 runtime 的用户感受。umi 接下来可以在现有基础上增加对 runtime 的支持。
  3. 看完 modern-js 的工作之后,感觉 electorn 框架目前还是处于一个很基础的状态。字节走了 OOP,我们也可以在 rxjs、hooks 之类的方向去思考。
  4. 之前做了一些更高级的封装,例如 Title-Bar,目前 modern-js 还没有。这个还是很有必要的,最近玩构建丢掉了,未来要捡起来继续迭代。
  5. 周边生态还要搞亿搞。之前拉实习生 @礼检 做了create-electron-lab,已经规划让他转到 create-umi 上了。
  6. 之前用 father-build 搞了个魔改版:father-build@1.20.5-5。主要是加了入口路径、出口路径、配置文件路径的支持,期望 @辟起 老师可以在正式版搞定这个需求。