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

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

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

前言

Electron 是使用 JavaScriptHTMLCSS 构建跨平台的桌面应用程序的框架,可构建出兼容 MacWindowsLinux 三个平台的应用程序。

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

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

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

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

Native APIElectron 提供原生系统的 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 对象,当新开标签页或弹出窗口后,渲染进程就会创建一个 RenderViewRenderView 对象与它在浏览器进程中对应的 RenderViewHostWebkit 嵌入层通信,渲染出网页网页内容(这里是我们日常主要关注的地方)。

Electron 架构解析

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

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

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

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

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

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

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

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

Node 与 Chromium

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

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

有两种解决方案:

使用 libuv 实现 message bumpChromium 集成到 Node.js

Node.js 集成到 Chromium

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

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

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

下面这张 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