说到electron,就绕不开nw.js (原名 node-webkit) ,这两者太过相似,都提供了一个能通过 JavaScript 和 HTML 创建桌面应用的平台,同时集成 Node 来授予网页访问底层系统的权限。
NW.js的内部原理
NW.js加载APP的组件架构示意图:
根据上图所示,用户很容易看到,Node.js负责一些跟OS打交道的后端功能,而Blink(Chromium渲染引擎)则用来渲染应用的前端部分。在这两者中间,Node.js 和 Blink 都使用 V8 来执行 JavaScript 代码,并且这也是能让 Node.js 和 Chromium一起工作的很重要的一点。要让 Node.js 和 Chromium 一起工作,必须满足如下三点要求:
- 使Node.js和Chromium使用V8的相同实例
- 使用相同的事件循环
- 桥接Node和Chronium的js上下文
使用同一个V8实例
Node.js 和 Chromium 都使用 V8 来执行 JavaScript。要让这两者能够在一起工作,要求以下几件事要依次发生:首先,NW.js 要做的就是加载 Node.js 和Chromium,这样它们各自的 JavaScript 上下文就能载入V8引擎了。Node.js 的JavaScript 上下文会暴露一些全局对象和函数,比如module、process、require等。Chromium的 JavaScript 上下文也会暴露一些像window、document以及console这样的全局对象和函数。如下图所示,两者之间还有一些重合,因为Node 和 Chromium 都有 console对象。
集成事件循环
JS采用了异步非阻塞的方式执行代码,无论是nodejs还是跑在浏览器中的js都是一样,但他们的实现方式并不同。
Node.js和Chromium使用的是不同的软件代码库(Node.js 使用 libuv,Chromium使用的则是自定义的C++ 代码库,名为MessageLoop以及MessagePump)。要让 Node.js 和 Chromium 在一起工作,必须将这两个事件循环进行集成。
当 Node.js 的 JavaScript 上下文复制到 Chromium 的 JavaScript 上下文的时候, Chromium 的事件循环会被调整为使用一个自定义版本的 MessagePump,它是构建在 libuv 之上的,这样一来,它们就可以在一起工作了。
对Node打补丁
要完成 Node 和 Chromium 的整合,下一步需要将 Node 的start函数和Chromium 的渲染进程进行集成。Node.js 通过执行一个start函数来处理代码的执行。要让 Node.js 和 Chromium 在一起工作,需要将start函数分割成多个部分,这样才能在 Chromium 的渲染进程中进行执行。这部分牵涉NW.js 自己实现的代码,对 Node.js 的start函数打了一些补丁。
这部分完成后,Node 就可以和 Chromium 一起工作了。NW.js 就是通过这种方式让 Node.js 代码在由 Chromium 负责的前端代码中也可以工作
Electron的内部原理
Electron 的架构将 Chromium 源代码和应用切分得很清楚。这样做的好处就是使升级 Chromium 组件变得很容易,同时这也意味着通过源代码编译 Electron 也很容易。
渲染进程与主进程
目前 Electron 框架通过在一个单独的线程中(Node_bindings.cc源码)轮询 Node 的事件循环的方式来实现 Chromium 与 Node.js 融合
在 NW.js 中,通过将 Node.js 和Chromium 的事件循环集成起来,把 Node.js 的 JavaScript 上下文复制到Chromium的 JavaScript 上下文中,可以让桌面应用中的前后端代码进行状态共享。这种方案带来的一个结果就是使用 NW.js 开发的应用中的视窗可以共享对JavaScript 状态的同一份引用。
而在 Electron 中,不论是想在前端代码中共享后端代码的状态,或者反过来,都需要经过 ipcMain 和 ipcRenderer 模块。这种方式意味着 main 进程中的JavaScript上下文和 renderer 进程中的 JavaScript 上下文是互相隔离的,但是数据可以通过一种显式的方式在两个进程之间进行传递。ipcMain和ipcRenderer模块其实都是事件分发器,负责在应用后端代码(ipcMain)和前端代码(ipcRenderer)之间进行通信。
总结
虽然说二者很相似,但还是有不少差异的。
在NW.js中,应用的主入口是网页或者JS脚本。 你需要在package.json中指定一个html或者js文件,一旦应用的主窗口(在html作为主入口点的情况下)或脚本被执行,应用就会在浏览器窗口打开。
在 Electron 中,入口是一个 JavaScript 脚本。 不同于直接提供一个URL,你需要手动创建一个浏览器窗口,然后通过 API 加载 HTML 文件。
简单地说,electron和传统的前后端开发更相似,分为主进程(后端)和渲染进程(前端)。而NW.js则是一个集成了node能力的浏览器,你在上面进行前端开发的同时能调用node能力。
一些八卦
这里插个八卦,据zcbenz(nw的早期开发者,后面转投Electron)说,当他在intel实习把nw做起来并准备转正后
彻底失去了node-webkit的自治权,开始收到命令去完成指定的开发工作,被禁止随意去增加功能,也不允许去随意修复bug,而发布新版本、和客户交流的工作也被转移给更高级别的工程师手上。
当然,nw的开发人员也反驳了。反驳链接,github issue
作为吃瓜群众我们还是不用太关注这些,哪个好用用哪个就完事了。