首页>>前端>>JavaScript->从 Electron 架构出发,深究 Electron 跨端原理

从 Electron 架构出发,深究 Electron 跨端原理

时间:2023-12-02 本站 点击:0

前言

Electron 是使用 JavaScript,HTML 和 CSS 构建跨平台的桌面应用程序的框架,可构建出兼容 Mac、Windows 和 Linux 三个平台的应用程序。

一个跨端框架的设计,有三个问题需要考虑,分别是 UI 渲染、原生 API 以及客户端构建方式。Electron 是如何解决上述问题的呐?

Electron 的跨端原理并不难理解:它通过集成浏览器内核,使用前端的技术来实现不同平台下的渲染,并结合了 Chromium 、Node.js 和用于调用系统本地功能的 API 三大板块。

Chromium 为 Electron 提供强大的 UI 渲染能力,由于 Chromium 本身跨平台,因此无需考虑代码的兼容性。最重要的是,可以使用前端三板斧进行 Electron 开发。

Chromium 并不具备原生 GUI 的操作能力,因此 Electron 内部集成 Node.js,编写 UI 的同时也能够调用操作系统的底层 API,例如 path、fs、crypto 等模块。

Native API 为 Electron 提供原生系统的 GUI 支持,借此 Electron 可以调用原生应用程序接口。

总结起来,Chromium 负责页面 UI 渲染,Node.js 负责业务逻辑,Native API 则提供原生能力和跨平台。

上面粗略讲解了 Electron 的跨端原理,下面我们来深究一下。

Chromium 架构

JavaScript 是单线程语言,但浏览器是多线程的,Chromium 作为 Chrome 的实验版,自然也是基于多线程工作机制。(图源: Chromium 官网)

Chromium 的多进程模式主要由三部分组成: 浏览器端(Browser)、渲染器端(Render)、浏览器与渲染器的通信方式(IPC)

1.浏览器进程

浏览器进程 Browser 只有一个,当 Chrome 打开时,进程启动。浏览器为每个渲染进程维护对应的 RenderProcessHost,负责浏览器与渲染器的交互。RenderViewHost 则是与 RenderView 对象进行交互,渲染网页的内容。浏览器与渲染器通过 IPC 进行通信。

2.渲染进程管理

每个渲染进程都有一个全局 RenderProcess 对象,可以管理其与父浏览器进程之间的通信,并维护其全局状态。

3.view 管理

每个渲染器可以维护多个 RenderView 对象,当新开标签页或弹出窗口后,渲染进程就会创建一个 RenderView,RenderView 对象与它在浏览器进程中对应的 RenderViewHost 和 Webkit 嵌入层通信,渲染出网页网页内容(这里是我们日常主要关注的地方)。

Electron 架构解析

Electron 架构参考了 Chromium 的多进程架构模式,即将主进程和渲染进程隔离,并且在 Chromium 多进程架构基础上做一定扩展。

将上面复杂的 Chromium 架构简化:

Chromium 运行时由一个 Browser Process,以及一个或者多个 Renderer Process 构成。Renderer Process 负责渲染页面 Web ,Browser Process 负责管理各个 Renderer Process 以及其他功能(菜单栏、收藏夹等)

下面我们看一下啊 Electron 架构有那些变化?

Electron 架构中仍然使用了 Chromium 的 Renderer Process 渲染界面,Renderer Process 可以有多个,互相独立不干扰。由于 Electron 为其集成了 Node 运行时,Renderer Process 可以调用 Node API。主要负责: 利用 HTML 和 CSS 渲染页面;利用 JavaScript 实现页面交互效果。

相较于 Chromium 架构,Electron 对 Browser 线程做了很多改动,将其更改名 Main Process,每个应用程序只能有一个主线程,主线程位于 Node.js 下运行,因此其可以调用系统底层功能。其主要负责:渲染进程的创建;系统底层功能及原生资源的调用;应用生命周期的控制(包裹启动、推出以及一些事件监听)

经过上面的分析,Electron 多进程的系统架构可以总结为下图:

可以发现,主线程和渲染线程都集成了 Native API 和 Node.js,渲染线程还集成 Chromium 内核,成功实现跨端开发。

Node 与 Chromium

Node 的事件循环与浏览器的事件循环有明显不同,Chromium 既然是 Chrome 的实验版,自然与浏览器实现相同。

Node 的事件循环基于 libuv 实现,而 Chromium 基于 message bump 实现。主线程只能同时运行一个事件循环,因此需要将两个完全不同的事件循环整合起来。

有两种解决方案:

使用 libuv 实现 message bump 将 Chromium 集成到 Node.js

将 Node.js 集成到 Chromium

Electron 最初的方案是第一种,使用 libuv 实现 message bump,但不同的 OS 系统 GUI 事件循环差异很大,例如 mac 为 NSRunLoop,Linux 为 glib,实现过程特别复杂,资源消耗和延迟问题也无法得到有效解决,最终放弃了第一种方案。

Electron 第二次尝试使用小间隔的定时器来轮询 GUI 事件循环,但此方案 CPU 占用高,并且 GUI 响应速度慢。

后来 libuv 引入了 backend_fd 概念,backend_fd 轮询事件循环的文件描述符,因此 Electron 通过轮询 backend_fd 来得到 libuv 的新事件实现 Node.js 与 Chromium 事件循环的融合(第二种方案)。

下面这张 PPT 完美的描述了上述过程(图源:Electron: The Event Loop Tightrope - Shelley Vohr | JSHeroes 2019)

参考链接

Multi-process Architecture

Essential Electron

跨平台技术实战!百度文库跨平台技术快速落地全过程

Electron Internals: Message Loop Integration

Electron 开发实战文档资料

?奖品大放送

小包又来了,本次活动的奖励有两份: 妖娆托举猫和马赛克线圈毛巾

参与方式: 点赞或评论即可(友情提示,如果回复跨端相关的评论,运气可能会更好哦)

后语

我是 战场小包 ,一个快速成长中的小前端,希望可以和大家一起进步。

如果喜欢小包,可以在 掘金 关注我,同样也可以关注我的小小公众号——小包学前端。

一路加油,冲向未来!!!

疫情早日结束 人间恢复太平

原文:https://juejin.cn/post/7103337772424888356


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:/JavaScript/9507.html