如果想 开发一个桌面 GUI 应用软件,希望其能同时在 Windows、Linux 和 Mac 平台上运行,可选的技术框架并不多,在早期人们主要用 wxWidgetsGTKQt 来做这类工作。这三个框架都是用 C/C++ 语言开发的,受语言开发效率的限制,开发者想通过它们快速地完成桌面应用的开发工作十分困难。

    近几年相继出现了针对这些框架的现代编程语言鄉定库,诸如 Python、C#、Go 等,大部分都是开源社区提供的,但由于历史原因,要想用到这些框架的全部特性,还是需要编写 C/C++ 代码。并且由于几乎没有高质量的 Node.js 的绑定库,前端程序员想通过这三个框架开发桌面应用更是难上加难。

    Stack Overflow 的联合创始人 Jeff Atwood 曾经说过,凡能用 JavaScript 实现的,注定会被用 JavaScript 实现。桌面 GUI 应用也不例外,近几年两个重量级框架 NW.jsElectron 横空出世,给前端开发人员打开了这个领域的大门。

    :::tips 扩展:
    这两个框架都与中国人有极深的渊源,2011 年左右,中国英特尔开源技术中心的 王文睿(Roger Wang)希望能 用 Node.js 来操作 WebKit,而创建了 node-webkit 项目,这就是 NW.js 的前身,但当时的目的并不是用来开发桌面 GUI 应用。

    中国英特尔开源技术中心大力支持了这个项目,不仅允许王文睿分出一部分精力来做这个开源项目,还给了他招聘名额,允许他招聘其他工程师来一起完成。

    2012 年,故事的另一个主角 赵成(Cheng Zhao)加入王文睿的小组,并对 node-webkit 项目做出了大量的改进。

    后来赵成离开了中国英特尔开源技术中心,帮助 GitHub 团队尝试把 node-webkit 应用到 Atom 编辑器上,但由于当时 node-webkit 并不稳定,且 node-webkit 项目的走向也不受赵成的控制,这个尝试最终以失败告终。

    但赵成和 GitHub 团队并没有放弃,而是着手开发另一个类似 node-webkit 的项目 —— Atom Shell,这个项目就是 Electron 的前身。赵成在这个项目上倾注了大量的心血,这也是这个项目后来广受欢迎的关键因素之一。再后来 GitHub 把这个项目开源出来,最终更名为 Electron。

    你可能从没听说过这两个人的名宇,但开源界就是有这么一批“英雄”,他们不为名利而来,甘做软件行业发展的铺路石,值得这个领域的所有从业者尊敬。 :::

    两个框架都是基于 Chromium 和 Node.js 实现的,这就使得前端程序员可以使用 JavaScript、HTML 和 CSS 轻松构建跨平台的桌面应用。

    NW.js 和 Electron 问世之后,之前很多传统桌面应用开发的难点变得异常容易,比如简单界面绘图可以使用 HTML 的 SVG 或 Canvas 技术实现,简单动效可以用 CSS Animations 或 Web Animations API 来实现(复杂的动效、图形处理、音视频处理等可以借助 Node.js 的原生 C++ 模块实现)。

    为了弥补 Node.js 和前端技术访问系统 API 方面的不足,这两个框架内部都对系统 API 做了封装,比如系统对话框、系统托盘、系统菜单、剪切板等。开发者基于 Electron 开发应用时,可以直接使用 JavaScript 访问这些 API。

    其他 API,诸如网络访问控制、本地文件系统的访问控制等则由 Node.js 提供支持。

    两个框架对于开发者来说差别并不是特别大,最主要的差别无过于 Electron 区分主进程和渲染进程主进程负责创建、管理渲染进程以及控制整个应用的生命周期,渲染进程负责显示界面及控制与用户的交互逻辑。在 Electron 中主进程和渲染进程间通信需要经由 ipcMain 和 ipcRenderer 传递消息来实现。NW.js 则无须关注这些问题,它需要关注的是所有窗口共享同一个 Node.js 环境带来的问题。

    :::tips 扩展:
    NW.js 和 Electron 都是基于 Chromium 和 Node.js 实现的,Chromium 和 Node.js 的应用场景完全不同,它们的底层虽有一部分是相同的,但要想把它们两个整合起来并非易事。

    显然 NW.js 和 Electron 都做到了,然而它们底层使用的整合技术却截然不同。NW.js 通过修改源码合并了 Node.js 和 Chromium 的事件循环机制,Electron 则是通过各操作系统的消息循环打通了 Node.js 和 Chromium 的事件循环机制(新版本的 Electron 是通过一个独立的线程完成这项工作的)。

    NW.js 的实现方式更直接,但这也导致 Node.js 和 Chromium 耦合性更高。Electron 的实现方式虽然保证了Node.js 和Chromium 的松耦合,但也间接地创造出了主进程和渲染进程的概念,给开发人员实现应用带来了一定的困扰。 :::

    除此之外,其他方面的比较如表 1-1 所示。

    image.png

    可以说 NW.js 和 Electron 各有优劣,我个人认为 Electron 更胜一筹,更值得推荐。

    Electron 最初由赵成和 GitHub 的工程师于 2013 年 4 月创建,当时名字为 Atom Shell,用来服务于 GitHub 的开发工具 Atom,2014 年 5 月开源,2015 年 4 月才正式更名为 Electron。

    目前 GitHub 公司内部仍有一个团队在维护这个开源项目,且社区内也有很多的贡献者。Electron 更新非常频繁,平均一到两周就会有新版本发布,Issue 和 Pull request 的回复也非常及时,一般关系到应用崩溃的问题(Crash Issue)一两天就能得到回复,普通问题一周内也会有人跟进。社区活跃程度由此可见一斑。