本文首发同名微信公众号:前端徐徐
大家好,我是徐徐。今天我们来浅析一下 Electron 的原理。
前言
Electron 的原理是每个开辟 Electron 应用的开辟者都需要了解的知识内容,因为知道整个原理全貌后你才能在设计一个应用的时间更加的合理,遇到题目才知道从哪个方面去分析。这篇文章将主要从架构层面,协作方式,底层支持,源码层面,API设计等方面来剖析 Electron 的原理。
架构层面
两个组件
Electron 的核心架构是基于 Chromium 和 Node.js 两个主要组件,各自饰演不同的角色。
Chromium
Chromium 是一个开源的浏览器项目,Google Chrome 就是基于它构建的。Electron 使用 Chromium 作为其渲染引擎,这意味着 Electron 应用可以利用现代 web 尺度和技术,如 HTML5、CSS3 和 JavaScript 来构建用户界面。
Chromium 提供了以下主要功能:
- 渲染引擎:负责将 HTML、CSS 和 JavaScript 转换为用户界面。
- 多历程架构:每个页面(窗口)通常运行在独立的渲染历程中,进步了应用的稳固性和安全性。
Node.js
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,Electron 使用 Node.js 提供体系级别的 API,允许开辟者在应用中使用服务器端的功能。
Node.js 主要提供以下功能:
- 文件体系访问:允许读写文件、创建目录等操纵。
- 网络通信:支持 HTTP/HTTPS 请求、WebSocket 等网络协议。
- 历程管理:可以创建和管理子历程,实行体系下令等。
两种历程
Electron 应用通常包含主历程和渲染历程两种历程类型,每一种历程都有本身的属性和职责,另外还包含预加载脚本,他们相互协作构建出一个应用。
主历程(Main Process)
主历程是 Electron 应用的入口点,通常负责以下任务:
- 应用生命周期管理:包括启动、退出等。
- 创建和管理窗口:通过 BrowserWindow 对象创建和管理应用中的各个窗口(渲染历程)。
- 与操纵体系交互:可以使用 Node.js API 举行文件操纵、打开本地文件对话框等。
- 历程间通信:主历程和渲染历程之间通过 ipcMain 和 ipcRenderer 模块举行通信。
渲染历程(Renderer Process)
渲染历程负责 web 页面的渲染,每个 BrowserWindow 对象通常对应一个独立的渲染历程。渲染历程具有以下特点:
- 独立性:每个窗口有本身独立的渲染历程,瓦解时不会影响其他窗口。
- 安全性:由于渲染历程通常运行不具备完全访问 Node.js API 的权限,因此可以加强应用的安全性。
- UI 渲染:渲染历程使用 Chromium 提供的渲染引擎来表现 HTML、CSS 和 JavaScript 构建的用户界面。
预加载脚本(Preload Scripts)(可选)
预加载脚本在渲染历程中运行,但可以访问部分 Node.js API。它们的主要作用是:
- 安全桥梁:在渲染历程和主历程之间创建一个安全的桥梁,提供受控的 Node.js API 访问。
- 初始化任务:在 web 页面加载之前举行一些必要的初始化任务,如注入全局变量、设置事件监听等。
Chromium 和 Node.js 的协作
Electron 通过历程隔离、上下文桥接和 IPC 机制,实现了 Chromium 和 Node.js 的高效协作,确保应用的稳固性、安全性和功能性。
历程隔离
历程隔离是 Electron 实现稳固性和安全性的紧张机制。Electron 通过将应用分为主历程(Node.js运行)和多个渲染历程(Chromium运行),来确保纵然一个渲染历程瓦解,也不会影响到其他部分的运行。这种隔离使得应用能够同时利用 Node.js 强大的体系级 API 和 Chromium 先进的浏览器技术,同时也进步了应用的结实性和安全性。
上下文桥接
上下文桥接通过contextBridge API,使得Node.js的功能可以安全地袒露给渲染历程。通过这种机制,可以在不直接袒露Node.js情况的情况下,将必要的功能提供给渲染历程。
IPC(历程间通信)
历程间通信(IPC)是 Electron 中主历程和渲染历程之间举行协作的紧张机制。Electron 提供了ipcMain 和 ipcRenderer 模块,通过 IPC 机制,主历程和渲染历程可以相互发送消息,从而实现数据的传递和事件的触发。例如,当渲染历程需要访问文件体系时,可以通过发送消息给主历程,由主历程来实行实际的文件操纵,并将效果返回给渲染历程。
底层支持
一款客户端框架,仅仅是有炫酷的界面是不可的,必须要有一些强劲的底层本事支持才能让这个桌面客户端框架完备,Electron 的底层支持主要涉及以下几个方面:
libchromiumcontent
libchromiumcontent 是 Chromium 内容模块的封装。它提供了一个独立于 Chromium 浏览器的内容渲染引擎。它具有以下功能****:
- Web尺度支持:libchromiumcontent 实现了现代Web尺度,包括HTML5、CSS3、ES6等。
- 多历程架构:利用 Chromium 的多历程架构,渲染历程和主历程分离,提升了应用的稳固性和安全性。
- 渲染本事:负责将 HTML、CSS 和 JavaScript 渲染为可视内容。
libchromiumcontent 作为一个共享库,被集成到 Electron 中,为 Electron 应用提供浏览器功能。Electron 的主历程启动时,会启动 Chromium 的多个子历程(包括渲染历程),来处理网页的加载和渲染。
Node.js
****Node.js 是一个基于 V8 引擎的 JavaScript 运行情况。它使得 JavaScript 可以在服务器端运行,并且能够举行 I/O 操纵。
它具有以下功能:
- 体系级API:通过 Node.js 的模块体系,Electron 应用可以访问文件体系、网络、历程等体系级 API。
- 异步编程:Node.js 提供了异步 I/O 操纵,可以高效地处理并发任务。
- 模块化:利用 Node.js 丰富的模块生态体系,开辟者可以快速集成第三方库。
在 Electron 中,Node.js 被嵌入到主历程和渲染历程中。主历程负责管理应用生命周期和原生窗口,渲染历程负责网页内容的渲染和交互。通过 Node.js,开辟者可以在 Electron 应用中使用 require 引入 Node.js 模块,直接调用底层体系 API
V8引擎
****V8 是 Google 开辟的开源 JavaScript 引擎,最初用于 Chrome 浏览器,现在也被 Node.js 和 Electron 使用。
它具有以下功能:
- JavaScript 实行:将 JavaScript 代码编译为本地机器码,从而提升实行速度。
- 内存管理:提供垃圾回收机制,自动管理内存分配和开释。
- 性能优化:通过即时编译(JIT)和内联缓存(inline caching)等技术,优化 JavaScript 实行性能。
V8 引擎在 Electron 中同时被 Chromium 和 Node.js 共享使用。渲染历程中的 JavaScript 代码(包括前端代码)和主历程中的 JavaScript 代码(包括 Node.js 代码)都通过 V8 引擎实行。
操纵体系API
****操纵体系API 是指 Electron 应用通过 Node.js 和自定义的 native 模块与操纵体系举行交互的接口。
它具有以下功能:
- 文件体系操纵:访问和操纵文件和目录。
- 网络通信:举行网络请求和套接字编程。
- 历程管理:创建和管理子历程。
- GUI控制:通过 native 模块,控制窗口、菜单、关照等 GUI 元素。
Electron 应用可以使用 Node.js 的原生模块(如 fs、net 等)来直接与操纵体系交互。此外,Electron 还提供了一些特定于 Electron 的模块(如 electron 模块),进一步封装了与操纵体系的交互逻辑。这些模块通过 Node.js 的 C++ 插件机制(Node-API)与底层体系 API 举行通信。
Electron 通过整合 Chromium 的渲染本事、Node.js 的体系 API、共享的 V8 引擎以及操纵体系 API,提供了一个非常强劲的底层支持本事,几乎可以做你任何想做的事情。
源码层面
对于源码的话,这块看本身的研究深度,大部分时间,使用一个框架是不太需要知道源码的,只要知道 API 和一些设置就行,但是如果遇到一些棘手的题目,看源码绝对可以解决你的很多题目,下面是核心源码目录的大概解释。
具体源码可以在这里在线预览:
https://github1s.com/electron/electron/tree/main
- Electron
- ├── build/ - 构建脚本和配置文件
- ├── buildflags/ - 条件编译时可选的 Features
- ├── chromium_src/ - 包含 Chromium 的构建配置
- ├── default_app/ - Electron 默认程序,在未提供应用程序时启动
- ├── docs/ - Electron 文档
- ├── lib/ - JavaScript/TypeScript 源码
- │ ├── browser/ - 主进程相关代码
- │ ├── common/ - 主进程和渲染进程共享的代码
- │ ├── isolated_renderer/ - 隔离渲染器相关代码
- │ ├── node/ - Node.js 集成相关代码
- │ ├── renderer/ - 渲染进程相关代码
- │ ├── sandboxed_renderer/ - 沙箱化渲染器相关代码
- │ ├── utility/ - 实用工具函数
- │ └── worker/ - Web Worker 相关代码
- ├── npm/ - npm 相关配置和脚本
- ├── patches/ - 补丁文件
- ├── script/ - 开发和构建脚本
- ├── shell/ - Electron 壳层相关 C++ 代码
- │ ├── app/ - 应用程序核心代码
- │ ├── browser/ - 浏览器进程相关代码
- │ ├── common/ - 共享代码
- │ ├── renderer/ - 渲染器进程相关代码
- │ ├── services/ - 服务相关代码
- │ └── utility/ - 实用工具
- ├── spec/ - Electron 测试规范
- ├── spec-chromium/ - Chromium 相关测试
- ├── typings/ - TypeScript 类型定义文件
复制代码 整体看 Electron 源码的结构是非常精巧的,不愧是大工程。这种结构设计允许 Electron 在保持灵活性的同时,有效管理其复杂的多历程架构和跨平台特性。它将高层 JavaScript API 与底层 C++ 实现分离,同时通过 common/ 目录实现了不同历程间的代码共享,这反映了 Electron 的核心设计理念。
应用入口源码简析
Electron 的源码很多,不过我们可以简单分析一下应用入口源码,就可大概明白整个 Electron 应用的启动过程了。
入口源码在:\shell\app\electron_main_delegate.cc,大概解读一下,在这个文件里面定义了 ElectronMainDelegate 类,这个类在 Electron 的启动过程中起着关键作用。下面是这个文件的主要内容和功能:
- 根本启动流程:
- BasicStartupComplete() 方法处理根本的启动任务,如设置下令行开关、注册路径提供者等。
- 沙箱初始化:
- PreSandboxStartup() 在沙箱启动之前实行一些初始化工作,如设置用户数据目录、初始化日志体系等。
- 内容客户端创建:
- 创建各种客户端对象,如 CreateContentBrowserClient(), CreateContentRendererClient() 等,这些对象负责管理 Electron 的不同历程。
- 资源加载:
- LoadResourceBundle() 函数负责加载本地化资源。
- 历程类型处理:
- RunProcess() 方法根据不同的历程类型实行相应的启动逻辑。
- 特性列表和 Mojo 初始化:
- ShouldCreateFeatureList() 和 ShouldInitializeMojo() 控制特性列表和 Mojo 体系的初始化。
- 瓦解报告:
- 包含了瓦解报告相干的初始化代码,尤其是在非 MAS (Mac App Store) 构建中。
- 平台特定代码:
- 包含了针对 Windows、macOS 和 Linux 的特定代码处理。
这个文件的作用是和谐 Electron 应用的启动过程,设置必要的情况,初始化各种组件,并为不同类型的历程(如主历程、渲染历程等)准备运行情况。它是连接 Chromium 内容模块和 Electron 特定功能的桥梁,确保 Electron 应用能够准确启动并运行。
API设计
一个框架的 API 设计决定了它使用的上手难易度和开辟者接受的水平,幸亏 Electron 的 API 设计也是非常奇妙的,所以开辟起来也会比较随手,它大概遵照以下原则:
模块化
Electron 的模块化设计允许开辟者只使用他们需要的功能,进步了代码的可维护性和可读性。
- 实现细节:
- 每个模块通常对应一个 C++ 类,如 app 模块对应 App 类。
- JavaScript API 通过 V8 引擎与这些 C++ 类举行绑定。
- 模块间保持低耦合,高内聚,允许独立更新和维护。
- 上风:
- 便于明白和使用:开辟者可以专注于所需的特定功能。
- 性能优化:只加载必要的模块,减少内存占用。
- 可扩展性:易于添加新模块或扩展现有模块。
事件驱动
事件驱动模子使得 Electron 应用能够高效地相应各种体系和用户事件。
- 实现细节:
- 使用 Node.js 的 EventEmitter 模式。
- C++ 层面的事件通过 V8 引擎转换为 JavaScript 事件。
- 广泛应用于生命周期管理、IPC 通信等场景。
- 上风:
- 非壅闭:事件处理不会壅闭主线程。
- 松耦合:事件发送者和吸收者之间无需直接依靠。
- 灵活性:允很多个监听器相应同一事件。
异步优先
异步 API 设计确保了 Electron 应用的高性能和相应性。
- 实现细节:
- 大量使用 Promise 和 async/await 语法。
- 在 C++ 层面,使用 libuv 实现异步操纵。
- 对于大概耗时的操纵,如文件 I/O 或网络请求,总是提供异步版本。
- 上风:
- 进步应用相应性:克制长时间壅闭主线程。
- 更好的错误处理:通过 Promise 链或 try-catch 结构处理异步错误。
- 符合现代 JavaScript 实践:与 Node.js 和前端开辟模式一致。
跨平台抽象
Electron 提供统一的 API 接口,大大简化了跨平台开辟。
- 实现细节:
- 在 C++ 层面为不同平台实现具体功能。
- 使用条件编译和平台特定代码来处理平台差异。
- JavaScript API 层保持一致,底层根据平台调用不同的实现。
- 上风:
- 开辟服从:开辟者只需学习一套 API,就能开辟跨平台应用。
- 代码复用:大部分应用逻辑可以在不同平台间共享。
- 维护简化:平台特定的题目被封装在底层,简化了上层应用的维护。
通过这些设计原则,Electron 成功地将 Web 技术与原生桌面功能结合,创造了一个强大而灵活的桌面应用开辟平台。这不仅简化了开辟过程,也为创新的桌面应用提供了大概性。
结语
这里我们大概简单地从几个方面剖析了 Electron 的原理,通过这些剖析了解了 Electron 的整体架构和设计头脑,这对我们开辟 Electron 应用是非常有帮助的,特别是在一些实战场景,如果对其原理了解得更加透彻,那么设计出来的应用应该也会很棒!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |