惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

SecWiki News
SecWiki News
I
InfoQ
The Cloudflare Blog
人人都是产品经理
人人都是产品经理
博客园 - Franky
T
Tailwind CSS Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园_首页
罗磊的独立博客
V
V2EX
李成银的技术随笔
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
True Tiger Recordings
Vercel News
Vercel News
Cyberwarzone
Cyberwarzone
Cisco Talos Blog
Cisco Talos Blog
F
Fox-IT International blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
M
Microsoft Research Blog - Microsoft Research
Know Your Adversary
Know Your Adversary
爱范儿
爱范儿
The Register - Security
The Register - Security
G
Google Developers Blog
The Hacker News
The Hacker News
Malwarebytes
Malwarebytes
S
Securelist
博客园 - 三生石上(FineUI控件)
Jina AI
Jina AI
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
博客园 - 叶小钗
F
Fortinet All Blogs
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
博客园 - 聂微东
T
Threatpost
博客园 - 【当耐特】
D
Docker
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
G
GRAHAM CLULEY
V
Visual Studio Blog
C
Cisco Blogs
IT之家
IT之家
S
Security Archives - TechRepublic
Latest news
Latest news
阮一峰的网络日志
阮一峰的网络日志

Xiaobin's Notes

Mac本地快速部署DeepSeek 如何让大语言模型输出JSON格式 webstorm 的 cpu 占用高 修改Joplin主题样式 ECMAScript 历代版本 新一代包管理器 PNPM React useEffect() Hook Vue 2.x 使用高德地图JS API 2.0加载起点终点路径轨迹 家庭用电插座 MacOS 14.4 引发Java 应用崩溃 重定向广告 Pyenv工具 ElasticSearch集群原理 ElasticSearch集群节点 Elasticsearch Mapping 参数 Elasticsearch元数据 Elasticsearch的数据类型 Go语言的向后兼容和toolchain规则 Go 1.21 新增特性
Electron的原理
2024-08-28 · via Xiaobin's Notes

Electron是一个集成项目,允许开发者使用前端技术开发桌面端应用。它做了如下几个重要的工作:

  • 定制 Chromium,并把定制版本的 Chromium 集成在 Electron 内部;
  • 定制 Node.js,并把定制版本的 Node.js 集成在 Electron 内部;
  • 通过消息轮询机制打通 Node.js 和 Chromium 的消息循环;
  • 通过 Electron 的内置模块向开发者提供桌面应用开发必备的 API;

其中 Chromium 基础能力可以让应用渲染 HTML(CSS) 页面,可以执行页面的JavaScript脚本,让应用可以在 Cookie、LocalStorage或 IndexedDB 中存取数据。除此之外,Electron还允许开发者突破同源策略的限制:伪装请求,截获响应,修改session等。

Node.js 基础能力可以让开发者读写本地磁盘的文件、通过 socket 访问网络、创建和控制子进程等。除此之外,还修改了Node的加解密机制让Chromium的BoringSSL和Node的OpenSSL兼容的更好,让Node.js可以加载asar压缩包内的文件等。

Electron 内置模块可以让开发者创建操作系统的托盘图标、访问操作系统的剪切板、屏幕信息、发送系统通知等,除此之外还提供了崩溃报告收集能力、性能问题追踪能力等。

另外,Electron继承了Chromium的多进程架构,也是分一个主进程多个渲染进程的。

Electron 应用启动时,首先会加载主进程的逻辑,主进程会创建一个或多个窗口,我们暂时可以粗浅的认为一个窗口就代表一个渲染进程,主进程负责管理所有的渲染进程。具体的多进程概念请看Chromium的原理。


Chromium的原理

Chromium是一个多进程架构的浏览器。

以前(大约2008年)浏览器大都是单进程、多线程的架构模式实现的,浏览器中任何一个行为不当的网页或插件都可能让整个浏览器崩溃。

Chromium为了解决这个问题,把每个页面约束在单独的进程中,以保护整个浏览器不受单个页面中的故障所影响。这极大地缓解了浏览器容易崩溃的问题。如下图所示:

Chromium把管理页面、管理选项卡和插件的进程称为浏览器进程(Browser Process)。把特定于页面的进程称为渲染进程(Render Process)。

渲染进程使用Blink布局引擎来解释和渲染HTML。渲染进程与浏览器进程通过IPC管道进行通信(详细资料)。

通常每个新窗口或选项卡都会在新进程中打开。浏览器进程(Browser Process)负责创建这些新的进程(Render Process)。一旦渲染进程崩溃或挂起,则浏览器进程控制着界面,提示用户需要重新加载页面,当用户点击重新加载按钮后,浏览器进程则创建一个新的渲染进程来为用户服务。

有的时候创建新窗口或选项卡不会创建新渲染进程。比如开发者使用window.open方法打开新窗口时,就希望这个窗口复用当前的渲染进程,因为两个窗口之间往往需要同步的数据交互。另外还有一些情况需要复用渲染进程,比如打开一个新的渲染进程时,发现系统中已经有一个同样的渲染进程可以复用的情况(详细资料)。

由于渲染进程运行在一个单独的进程中,所有页面脚本都在此进程中运行,当页面脚本尝试访问网络或本地资源时,当前渲染进程会发消息给浏览器进程,由浏览器进程完成相应的工作。此时浏览器进程会判断这些操作是否合法,比如跨越同源策略的请求、突破限制访问Cookie、https页面内嵌http的页面等,这些行为都是不合法的行为,浏览器进程可以拒绝提供服务,这就是浏览器的沙箱模式。

多进程模式还带来了性能上的提升,对于那些不可见的渲染进程,操作系统会在用户可用内存较低时,把它们占用的内存部分或全部交换到磁盘上,以保证用户可见的进程更具响应性。相比之下,单进程浏览器架构将所有页面的数据随机分布在内存中,不可能如此干净地分离使用和未使用的数据,性能表现不佳。

多进程架构模式每个进程都会包含公共基础结构的副本(例如V8引擎的执行环境)、更复杂的通信模型等,这都意味着浏览器会消耗更多的内存、CPU甚至电能。


Node.js的原理

Node.js也是一个集成项目,它允许JavaScript脱离浏览器执行,并提供了一系列的API,供JavaScript访问用户操作系统的资源。

它集成的项目:

  • V8:高性能JavaScript的执行引擎,同时拥有解释执行和编译执行的能力,可以将JavaScript代码编译为底层机器码,Node.js通过V8引擎提供的c++ API使V8引擎解析并执行JavaScript代码,并且通过V8引擎公开的接口和类型把自己内置的C++模块和方法转换为可被JavaScript访问的形式;(Chromium网页中解释执行JS脚本用的也是V8引擎);
  • libuv:高性能、跨平台事件驱动的I/O库,它提供了文件系统、网络、子进程、管道、信号处理、轮询和流的管控机制。它还包括一个线程池,用于某些不易于在操作系统级别完成的异步工作;
  • c-ares:异步DNS解析库。用于支持Node.js的DNS模块;
  • llhttp:一款由TypeScript和C语言编写的轻量级HTTP解析器,内存消耗非常小;
  • OpenSSL:提供了经过严格测试的各种加密解密算法的实现,用于支持Node.js的crypto模块;
  • zlib:提供同步的、异步或流式的压缩和解压缩能力,用于支持Node.js的zlib模块;

JavaScript在Node.js运行环境中的执行流程

  1. 初始化自己的执行环境:在这个阶段Node.js会注册一系列的C++模块以备将来使用。
  2. 创建libuv的消息循环:这个消息循环会伴随着整个应用的生命周期,运行线程退出它才会退出。libuv模块内部持有一个非常复杂的结构体,当用户的代码开始读取文件或发起网络请求时,Node.js就会给这个结构体增加一个回调函数,libuv的消息循环会不断的遍历这个结构体上的回调函数,当读取文件或发起网络请求有数据可用时,就会执行用户的回调函数。
  3. 创建V8引擎的运行环境:这是一个拥有自己的堆栈的隔离环境。
  4. 绑定底层模块:Node.js会使V8引擎执行一个JavaScript脚本(node_bootstrap.js),这是Node.js内置的一个脚本,这个脚本负责绑定Node.js注册的一系列C++模块。
  5. 读取并执行用户脚本的内容:Node.js会把这个文件的内容交给V8引擎运行,并把运行结果返回给用户。