五天速成electron——day0
2ChaosElectron 的由来
如果想开发一个桌面 GUI 应用软件,希望其能同时在 Windows、Linux 和 Mac 平台上运行,可选的技术框架并不多,在早期人们主要用 wxWidgets、GTK 或 Qt 来做这类工作。
这类框架大都是以 C/C++语言开发,受语言开发效率的限制,开发者想通过它们快速的完成桌面应用的开发工作十分困难。近几年相继出现了现代编程语言针对这些框架的绑定库,诸如 Python、C#、Go 等,大部分都是开源社区提供的,但由于历史原因,要想用到这些框架的全部特性,还是需要编写 C/C++代码。并且高质量的 Node.js 的绑定库几乎没有,前端程序员想通过这类框架开发桌面应用更是难上加难。
Stack Overflow 的联合创始人 Jeff Atwood 曾经说过,凡能用 JavaScript 实现的,注定会被用 JavaScript 实现。桌面 GUI 应用也不例外,近几年两个重量级框架 NW.js 和 Electron 横空出世,给前端开发人员打开了这个领域的大门。
这两个框架都与中国人有极深的渊源,2011 年左右,中国英特尔开源技术中心的王文睿(Roger Wang)希望能用 Node.js 来操作 WebKit,而创建了 node-webkit 项目,这就是 NW.js 的前身。英特尔公司大力支持了这个项目,不但允许王文睿分出一部分精力来做这个开源项目,还给了他招聘名额,允许他招聘其他工程师来一起完成这个项目。
2012 年,故事的另一个主角赵成(Cheng Zhao)加入到王文睿的小组,并对 node-webkit 项目做出了大量的改进。后来赵成离开了英特尔,帮助 github 团队尝试把 node-webkit 应用到 Atom 编辑器上,但由于当时 node-webkit 还并不稳定,且 node-webkit 项目的走向也不再受赵成的控制了,这个尝试最终以失败告终。
但赵成和 github 团队并没有放弃,而是着手开发另一个类似 node-webkit 的项目:Atom Shell,这个项目就是 Electron 的前身,赵成在这个项目上倾注了大量的心血,这也是这个项目后来广受欢迎的关键因素之一,再后来 github 把这个项目开源出来,最终更名为 Electron。
Electron 的价值
Electron 和 NW.js 框架都是基于 Chromium 和 Node.js 实现的,这就使得前端程序员可以使用 JavaScript、HTML 和 CSS 知识轻松构建跨平台的桌面应用。
传统桌面应用开发的难点,现在看来也变得异常容易,比如绘制漂亮的界面可以使用更灵活的 HTML 和 CSS 提供的能力、实现简单的动效可以用 CSS Animations 或 Web Animations API 来实现。
为了弥补 Node.js 和前端技术访问系统 API 方面的不足,这两个框架内部都对系统 API 做了封装,比如:系统对话框、系统托盘、系统菜单、剪切板等。开发者基于 Electron 开发应用时,可以直接使用 JavaScript 访问这些 API。其他诸如网络访问控制、本地文件系统的访问控制则由 Node.js 提供支持。这样开发者就可以使用前端技术开发绝大多数桌面应用的需求了。
前端技术是现如今软件开发领域应用最广泛的技术之一。入门门槛非常低、周边生态繁荣而且历史悠久。相对于基于 C++库开发桌面软件来说,基于 Electron 开发更容易上手且开发效率更高。由于 JavaScript 语言是一门解释执行的语言,所以 C++语言固有的各种问题都不再是问题,比如:C++没有垃圾回收机制,开发人员要小心翼翼的控制内存,以免造成内存泄露。C++语言特性繁多且复杂,学习难度曲线陡峭,需要针对不同平台进行编译,应用分发困难等,使用 Electron 开发桌面应用就不用担心这些问题。
执行效率上,如果前端代码写的足够优秀,完全可以做到与 C++应用相媲美的用户体验,Visual Studio Code 就是先例。另外 Node.js 本身也可以很方便的调用 C++扩展,Electron 应用内又包含 Node.js 环境,对于一些音视频编解码或图形图像处理需求,可以使用 Node.js 的 C++扩展来完成。
随着几十年 Web 应用大行其道,Web 前端开发领域的技术生态足够繁荣。Electron 可以使用几乎所有的 Web 前端生态领域及 Node.js 生态领域的组件和技术方案。目前发布到 http://npmjs.com 平台上的模块已经超过 90 万个,覆盖领域广、优秀模块繁多且使用非常简单方便。
在完成 Web 前端开发工作时,开发者需要考虑很多浏览器兼容的问题,比如:用户是否使用了低版本的 IE 浏览器,是否可以在样式表内使用 flexbox 弹性盒模型等问题。最终会导致前端开发者束手束脚,写一些丑陋的兼容代码以保证自己的工作能在所有终端表现正常。但由于 Electron 内置了 Chromium 浏览器,该浏览器对标准支持非常好,甚至有些标准尚未通过,Chromium 浏览器就已经支持了,所以基于 Electron 开发应用不会遇到这些问题。开发者的自由度得到了最大程度的保护,你几乎可以在 Electron 中使用所有 HTML5、CSS3 、ES6 标准中定义的 API。
Electron 的原理
Electron 是一个集成项目,它做了如下几个重要的工作:
订制 Chromium,并把订制版本的 Chromium 集成在 Electron 内部
订制 Node.js,并把订制版本的 Node.js 集成在 Electron 内部
通过消息轮训机制打通 Node.js 和 Chromium 的消息循环
通过 Electron 的内置模块向开发者提供桌面应用开发必备的 API
Electron 框架的内部原理图如下所示:
其中 Chromium 基础能力 API 可以让应用渲染开发者提供的 HTML 页面,让应用可以在 Cookie 或 IndexedDB 中存取数据,前端开发者都非常熟悉这些能力。
Node.js 基础能力 API 可以让开发者读写本地磁盘的文件、通过 socket 访问网络、创建和控制子进程等,Node.js 开发者非常熟悉这些能力。
Electron 内置模块可以让开发者创建操作系统的托盘图标、访问操作系统的剪切板、发送系统通知,同时它还提供了一系列的 API,允许开发者使用 JavaScript 访问 Chromium 的底层能力。
下面我们来看一下 Electron 应用的结构:
每个 Electron 都是由 1 个主进程、 1 个或多个渲染进程组成的,开发者的主要工作就是完成主进程的逻辑和渲染进程的逻辑。
Electron 应用启动时,首先会加载主进程的逻辑,主进程会创建一个或多个窗口,我们暂时可以粗浅的认为一个窗口就代表一个渲染进程,主进程负责管理所有的渲染进程。
窗口内加载的页面就是开发者要实现的渲染进程的逻辑,我们可以让渲染进程与主进程通信,他们之间是通过 IPC 消息管道进行通信的。虽然有一些特殊的手段让两个渲染进程直接通信(后面的章节我们会介绍),但大部分时候还是通过主进程来中转消息以达到渲染进程间通信的目的。
Electron 提供的一系列内置模块大部分是专门为主进程的逻辑服务的,比如 app 模块、BrowserWindow 模块和 session 模块等,少量模块是专门为渲染进程的逻辑服务的,比如 ipcRenderer 模块、webFrame 模块等,只有少量模块是两个进程可以同时使用的,比如:clipboard 模块、desktopCapturer 模块等。我们应该清楚这些模块的势力范围,不能在主进程中使用渲染进程的模块,反之也不行。
Electron 的不足
基于 Electron 开发桌面 GUI 应用并不是完美的方案,它也有它的不足,综合起来说有以下几点:
第一:打包后的应用体积巨大
一个功能不算多的桌面应用,通过 electron-builder 压缩打包后至少要 50M。而且如果开发者不做额外的 Hack 工作的话,用户每次升级应用程序,还要让用户再下载一次同样体积的安装包。这对于应用分发来说是一个不小的负担。但随着网络环境越来越好,用户磁盘的容积越来越大,此问题给用户带来的损失会慢慢被削弱。
第二:版本发布过快
为了跟进 Chromium (和 Node.js) 的版本发布节奏,Electron 也有非常频繁的版本发布机制,每次 Chromium 的改动,都可能导致 Electron 冒出很多新的问题,甚至稳定版本都有很多未解决的问题。好在关键核心功能一直以来都是稳定的。
第三:安全性问题
Electron 把一些有安全隐患的模块和 API 都设置为默认不可用的状态,但这些模块和 API 都是非常常用的,有的时候开发者不得不打开这些开关,一旦处理不当,就可能导致他们开发的应用存在安全隐患,给开发者乃至终端用户带来伤害。安全问题有很多值得关注的技术细节,以至于 Electron 官方文档中专门开辟出来一个章节号召程序员重视安全问题。
第五:资源消耗较大
Electron 底层基于 Chromium 浏览器,资源占用较多一直以来都是 Chromium 被人诟病的问题,目前来看这个问题还没有很好的解决办法,只能依赖 Chromium 团队对 Chromium 的优化工作了。
第六:性能问题
Electron 本身是多进程多线程的框架,但 JavaScript 是单线程运行的,如果产品的需求中有大量音视频编解码、复杂数据格式化这类 CPU 消耗性的需求,那么不应该在 Electron 内使用 JavaScript 来实现这些需求,而应该使用 Node.js 的原生模块来实现这些需求。与其说这是一个 Electron 的不足,不如说这是 JavaScript 的不足。
除了以上这些问题外,Electron 还不支持老版本的 Windows 操作系统,比如 Windows XP,在中国还有一些用户是使用 Windows XP 的,开发者如果需要面向这些用户,应该考虑使用其他技术方案了。



