揭秘Electron架构原理

# Chromium架构

上一节我们说过electron是基于chromium做的,因此想要了解electron,需要了解Chromium的架构。

Chromuim本质是Chrome的开源版,也是一个浏览器,浏览器其实也是一个桌面应用,它需要去创建窗口,右键菜单,管理浏览器Tab页面还有扩展程序等等,而处理这些事项的进程我们称之为主进程,也就是下图第一个黑框Browser;而具体每一个页面的进程我们称之为渲染进程,对应的就是Render。可以看我们的一个浏览器里面,它会有一个browser,然后多个Render。

进程之间是需要通信交互才能运转的,如果大家对Linux或者是进程有一定了解的话,两个进程需要交互就需要跨进程通信,也就是我们所说的IPC。主进程中的RenderProcessHost和RenderProcess就是专门用来处理IPC事件的。

下面具体看看渲染进程具体的内容,RenderView,我们最熟悉的页面就是在RenderView中,基于webkit的排版展示出来的。ResourceDispatcher,用于处理资源的请求,当我们的页面需要请求资源的时候,会通过ResourceDispatcher创建一个请求ID,通过IPC转发到Broswer进程中处理,然后返回。

★★★结:

  • Chromium是多进程架构,包括Broswer和多个Render
  • 进程间是需要IPC进行通信
  • web关注的只是很小的一部分

# Electron架构

由于Electron使用了Chromium来展示web页面,所以Chromium的多进程架构也会被使用到Electron中,在Electron中也分为主进程和渲染进程,但是和Chromium不一样的有两点。第一,Electron在各个进程里暴露了一些Native API;第二,引入了Node.js。于是,我们可以在Electron中可以使用Chromium和Node,比如我们可以通过Node去管理窗口,在页面中我们可以使用Node库。这其实是非常不容易的,因为在主线程中同一时间下,只能运行一个事件循环,但是Node.js它的事件循环是基于libuv,而Chromium是基于messagebump,这就是Electron原理的重点,就是如何整合事件循环?

具体如何整合,主要的思路有两种:

  1. Chromium集成到Node.js: 用libuv实现messagebump(nw) 2.Node.js 集成到Chromium 方案一,electron也曾经尝试过,在渲染进程里实现比较简单,但是在主进程里面就比较困难了,因为各个系统的GUI实现都不一样,比如Mac是NSRunLoop、linuv是glib,工程量很浩大,很多边界条件处理不好。后来作者使用一个小间隔定时器去轮询GUI事件,但是发现GUI响应特别慢。

后来,随着libuv引入了backend_fd的概念,相当于libuv轮询事件的文件描述符,通过轮询backend_fd,可以知道libuv的一个新事件,所以electron的做法就是将Node集成到chromium。

Electron起了一个新的安全线程去轮询backend_fd,当node.js有了一个新的事件之后,通过postTask转发到我们的Chromium的事件循环当中,这样子就完成了Electron的事件融合。