跨平台客户端开发方案 Electron 使用感受

前言

桌面客户端技术在编程圈子里一直是一个迷人又可憎的存在。迷人在于无论是普通用户还是开发者,有漂亮的界面的本地软件更有“成品”感,它就像一个实实在在的“东西”,而不是需要浏览器打开的网站或者只能显示文字的黑框(CLI 程序)。
几乎直到近年来 HTML5 的普及,才将网站和“应用”挂钩上了。要说以前,特别是普通用户他们一定不会认为其实网站也是软件,而现在前端技术的发展才让“Web应用”一词被众人接受,例如那个典型的外行错误叫法“H5应用”。

可憎在于通常 GUI 技术方案和系统是绑定的(特别是 Windows 系统),这导致跨平台的桌面软件少之又少。当然我也能列举出一些跨平台的著名桌面软件:例如我最常用的通信工具 Telegram、金山的 WPS Office、Google 地球、VLC 播放器还有 FreeCAD 等,它们的共同特点是使用了一款跨平台 GUI 框架 Qt。如果不使用这种跨平台的 GUI 方案,想让程序的图形部分共享一套代码是极难的。

当然本文并不讨论 Qt,毕竟它已经是年代久远的成熟品,资料够多了,我没必要再在互联网上再添加一堆废话了。

Electron

摘自 Wiki pedia:

Electron(最初名为Atom Shell)是GitHub开发的一个开源框架。它允许使用Node.js(作为后端)和Chromium(作为前端)完成桌面GUI应用程序的开发。Electron现已被多个开源Web应用程序用于前端与后端的开发,著名项目包括GitHub的Atom和微软的Visual Studio Code。

我是从 Atom 还未发布正式版本的时候就使用它了,所以是眼看着这三者成长起来的。虽然现在 Atom 已经被 VSCode 打败了(新的编辑器在开发中)。无论怎样它们已经能完全证明 Electron 开发复杂桌面应用的可行性。
PS:如果你认为这两款编辑器是类似 Windows 上记事本那种软件那就错了,其复杂程度远远超出常规软件(你可以脑补成 VIM/Emacs 那一类)。

至于本文我为什么要接触 Electron?因为它能带给你更优的开发体验和享受前端项目技术同构带来的好处,并且直到现在它仍然很新鲜。不过,最重要的还是我的某款个人软件正在开发 Electron 版本,最近写了大量的基于 Electron 运行环境的代码,很有感触。

附加:之前有用文章介绍过 Discord 也是使用 Electron 开发的,它真的非常优秀。如果你真的想知道 Electron 能做到多么美好的体验,一定不要错过对它的尝试。

使用经历

在 Electron 还不是很成熟的时候,我小小的接触了一下它。当时因为整个 Node.js 圈子还不是很稳定,我认为这个东西只能尝个鲜不能正式使用,毕竟你个人没有 Github 或者微软那样的开发力去解决遇到的问题(坑)。你只能抛给社区,等待他们解决(直到现在 Electron 仍然有 900+ 处于 Open 状态的 Issure)。

当时的感觉是很神奇,很有才。原来不止能用 V8 引擎创造出后端运行环境 Node.js,还能用渲染技术构建前台界面,Chromium 真是一点都没有浪费呢。但是也仅限于轻度接触的状态,虽然也打算把自己的一些软件用 Electron 重构,但是最终都没有继续下去。

直到最近我打算将曾经自己开发过的一个安卓软件“复活”,但是不想继续用旧前端代码了,于是便有了先用 Electron 出桌面版的想法。而“成品”几乎已经完成了,所以我可以用自己的实际经验来证明 Electron 已经足够完善了。

注:我描述的那款软件之后会发文介绍,并且会提供专门的展示页和域名供大家使用。它是一个集中了多个平台的“资源浏览器”,可以直接播放视频和浏览图片。重点是:它基于 Electron

我暂时先放个视频,待我支持十五个以上的视频平台的时候就会发布第一个版本(目前已经支持数个)。

感受

  1. Electron 会不会给你强烈带来“打开了一个浏览器”的感觉?

    这完全取决于开发者的优化能力。如果用户认为我就是打开了一个浏览器然后加载了你们网站的网页,这就是一个网站套壳的“假软件”糊弄人,也不是不可能的。因为 Electron 完全使用浏览器的界面方案(即 HTML + CSS)。
    如果你能将界面元素的样式定制得不那么网页原生化的话,其实是不存在上面的问题的。除非你告诉我你从来不定制样式,按钮/输入框/链接等元素原生是怎么样就是怎样,那我也救不了你了。
    同时正是因为使用了 Web 前端的技术,它几乎比任何 GUI 技术都要强大、灵活和易用。并且没有比 Web 前端更能跨平台的图形技术存在了。

  2. 现在的浏览器都太“庞大”了,启动速度和资源消耗都不容乐观。从选择 Electron 开始岂不是就相当于承受了这些负担?

    从这个角度考虑,这种想法是没有问题的。但是 Electron 等价于 Chromium 吗?不,当然不是。其实不止是 Chromium,几大浏览器都是如此。现代浏览器其实就是一个便携式的“操作系统”,多余的部分实在太多了,所以 Electron 能精简的地方太多了。
    同时浏览器又是一个典型的具有超高图形性能的软件(别忘了浏览器比的就是速度),要知道网页的变化多端在浏览器即时渲染下都能保持如此快的响应速度,是非常厉害的。并且 Chromium 有多进程渲染网页的能力。所以使用 Electron 也等于接受了它的这些优点。
    PS:实测启动 Electron 的 Demo 应用比一个纯净的 Chrome 和 Firefox 要快得多,并且资源消耗至少是好几分之一(一般在 70MB 上下)。

  3. 如果随着应用的复杂性提高而导致启动时渲染完成速度变长,导致带来不好的体验(例如黑屏几秒再出现界面内容)怎么办?

    这个完全可以用简单的手法优化掉。例如 Discord 启动时会出现一个旋转的载入小窗口,然后再直接展示出完整界面,这样窗口的加载过程就看不到了。

另外 Electron 的强大优势:

  • 完全使用 Web 前端技术导致可以在网页上也能一定程度的公用一套代码,例如我正在开发的软件就使用了 React,请求库使用的是 corss-fetch(它同时兼容 Node.js 后端环境、浏览器环境和 Electron)。除了渲染进程和主进程通信的部分(IPC),其余代码几乎全部可以直接使用在网页上,得到完全一样的界面和功能,而那一部分代码只需要提供一套兼容层 API,分别在 Electron 主进程和浏览器环境实现两次就能做到完全的复用。

  • Electron 本质上仍然是 Chromium 运行本地网页应用,但是却解除了诸多限制,例如跨域。在 Electron 中,渲染进程网页中的脚本也能随意发起跨域请求。还有例如很多网站对资源的“防盗链”限制,这个在浏览器上是解除不了的,但是在 Electron 中却可以 intercept 所有请求,随意改写 Referer 等协议头的内容。再加上 Electron 和 Node.js 提供了更多的环境 API,给予了 Electron 应用最大的发挥,几乎不存在限制。

遇到过的坑

遇到的小坑有点多,但都在于我先前对文档的阅读不够充分和一部分内容理解错误。是最后软件基本成型的时候,我在 Windows 下确实遇到麻烦了。假设说,界面上有四个一样的控件,长度是 10px,边距是 4px。那么窗口的宽度只需要使用算法:(控件数量 + 1) * 边距长度 + 控件数量 * 控件宽度即可,也就是 (4+1)*4 + 4*10 = 30。

那么启动窗口 loadURL 的宽度参数用预先定义好的变量使用这个公式即可,无论怎么调整最终都是完美的宽度和显示效果。
但是 Windows 下的缩放机制(例如 Windows10 默认的 125%)导致实际像素并不一致,布局并不会是想象的样子。而这个问题 Electron 也正在解决中…… 所以你最好设计成弹性的布局,哪怕你的应用是固定宽度甚至不允许缩放窗口的。

结束语

之后我会发文描述我是怎么在 Electron 中使用 React 的,如何和 Web 前端公用一套代码。本文想表达的观点其实是 Electron 已经足够完善了,激进的开发者应该接纳它,创造出更多的跨平台 GUI 软件。现在国外已经很普遍了,但是国内仍然未起步。不过稍微看到点苗头,例如微信桌面客户端(经评论指出微信桌面版的界面技术跟 Chromium 无关)和网易云音乐都是基于 Chromium 技术构建的,不过能看出来只是大公司的轻度试水罢了,因为它们的体验“很烂”。