写点什么

Brahmos:一个更小、更快的类 React UI 框架,支持并发渲染

2020 年 11 月 07 日

Brahmos:一个更小、更快的类React UI框架,支持并发渲染

本文要点


  • 虽然近年来用于构建交互式 Web 应用程序的新 UI 框架的出现速度有所放缓,但在 2020 年,我们还是看到了一些主要关注简单性和性能的新框架;

  • Brahmos 旨在用一种不一样的、更快的方法来实现已知的 React API,还利用了 JavaScript 的一个标准特性:模板字面量。因此,Brahmos 努力实现了 React 的钩子、上下文、并发模式等等;

  • Brahmos 是为数不多实现了 React 并发模式 API 的 UI 框架之一。其他框架可能还在等待,或者完全放弃该特性。

  • 虽然新 JavaScript 框架的标准不断被该领域内占主导地位的框架抬高,但新进者表明,仍有创新的余地。


Sudhanshu Yadav 发布了Brahmos,一个新的用于开发交互式 Web 应用程序的前端框架。Brahmos 努力遵循最新的 React API,不过采用了完全避开虚拟 DOM 的实现。Brahmos 采用了模板字面量,这是在ES6/ES2015中引入的一个新的 JavaScript 语言特性。好处是通过更少的框架代码和更快的 DOM 更新计算来提高性能。


Brahmos 目前实现了大部分 React API,包括功能组件、钩子、上下文、refs、forward refs、suspense、并发模式等等。相关的示例代码可在这里中找到。


Brahmos 是一个新的前端框架,旨在提高 React 的性能。Preact 试图通过更少的代码来实现性能提升,但面向的是 DOM 渲染。与 React 不同,但与 Preact 一样,Brahmos 不适用于非基于 DOM 的输出设备(移动设备、pdf、webGL 等)。


Brahmos 一个有趣的地方是它实现了并发模式,这个功能在 React 中开发了好几年,到现在还没有正式发布。


Brahmos 的短期目标是重用现有的 React 组件(目前尚未实现)。此外,Brahmos 的性能测试基准也有待制定。


InfoQ 就该框架的基本思想、目标、价值和路线图采访了 Sudhanshu Yadav。有兴趣深入了解的读者也可以在网上观看演讲视频。


InfoQ:你能向我们的读者介绍一下你自己吗?


Sudhanshu Yadav:我是 HackerRank 的前端架构师。我很喜欢去了解我所使用的技术的内部原理,喜欢探究事物的运作原理。我还组织了一个研讨小组,讨论不同技术的内部原理。除此之外,我还喜欢探索架构、模式、工具和系统设计。

我是开源软件的忠实信徒,我开发了 Brahmos、react-number-format(每月有 1 百万的 npm 安装量)、packagebind和其他开源工具和库。


InfoQ:你最近发布了 Brahmos,一个实现了现代 React API 的前端 UI 库。这让 Brahmos 与其他 React 库(如 Preact 和 Nerv)同名。Preact 强调的是小体积(只有 4KB),Nerv 兼容包括 IE8 在内的浏览器。你认为 Brahmos 与 React 的主要区别是什么?是什么驱使你开发 Brahmos?


Yadav:提高应用性能是 Brahmos 背后的关键动力。Brahmos 深受 lit-html/hyper-html 将应用程序划分为静态和动态部分的想法的启发。遍历和处理过程可以在 O(动态节点)内完成,而不是在 O(节点)内完成,而在 React 中是后者。渲染模式还提供了很多静态优化的可能性。当我看到一个有关lit-html的演讲时,我对这个想法很感兴趣,因为应用程序的大部分是静态的,只有少数动态部分会发生变化。

我喜欢 React 和它的声明式 API,我想尝试找出一种与 React 类似的模式。所以,一开始,我考虑了两个选项。

第一个是开发 React Renderer。但这是不可能的,因为这个模式的主要问题是 React Element 和虚拟 DOM。React Element 不区分静态元素和动态元素,很难将多个静态元素组合为一个元素。

第二个是使用 lit-html 作为渲染引擎,并使用 React API 对其进行包装。但是 lit-html API 和 React API 不能直接映射。

所以两个选项都不行了。然后我决定用不同的渲染模式来开发一个实现了 React API 的库。

另外一个动机是想要了解 React 的内部原理以及如何构建一个成熟的 UI 库。


InfoQ:让开发人员能够定义构成应用程序的视图,这是前端框架的一个重要方面。现在有两种主要策略并存:一个是遵循有限 DSL 的模板,一个是使用成熟语言(如 JavaScript 或 TypeScript)开发的渲染函数。React 使用的是渲染函数。Vue 和 Svelte 使用在非 JavaScript 文件中声明的模板。相反,Brahmos 利用了 JavaScript 中最近加入的标记模板字面量,如nanohtmllighterhtmllit-html或微软的fast-element。你能向我们的读者解释一下模板字面量的好处以及 Brahmos 是如何使用它的吗?


Yadav:除了模板字面量之外,ES6 还为我们带来了一个被低估的特性,那就是给模板打标记。模板字面量标记就像是一个函数,它接收一个字符串数组(字面量/静态部分)作为第一个参数,其余的参数是动态表达式。标记函数的一个独特行为是,如果底层文字字符串没有发生变化,则字符串数组的引用也保持不变。

Brahmos 将 JSX 置换为带标记的模板字面量,原生元素成为静态部分,而 JSX 表达式成为动态表达式部分。这让我们能够区分内容的静态和动态部分,并以不同的方式对它们加以优化。

我们可以将静态部分视为一个虚拟节点,这将显著减少应用程序的虚拟节点数量,还可以更快地遍历动态部分,以便识别出所发生的变化。

由于字符串数组引用对于给定的模板保持不变,所以我们可以缓存字符串解析结果(将字符串转换为 HTML 模板标记),即使在一个大列表中多次渲染相同的组件,也不必重复进行解析。这以一种重复的方式提高了组件的性能。

与自定义模板相比,模板字面量也很有优势。模板字面量是 JavaScript 的一个标准特性,可以发挥 JavaScript 全部的能力来编写动态表达式。自定义模板(如 Vue 或 Svelte 所使用的模板)为动态逻辑带来了有限的语法。

在脚本加载时,对于解析器来说,模板字面量也比对象字面量更友好。对象字面量是 JSX 创建元素转换的结果。另一种用于在加载时防止进行对象字面量解析的类似技术是将它们转换为 JSON 字符串。


InfoQ: React 最近新增了一系列新的 API,其中一些还处于试验阶段。其中,并发模式受到了社区的特别关注,因为它所带来的可能性以及并发渲染方面的复杂性。事实上,一些框架已经决定不接受这个特性。你能告诉我们并发渲染是做什么的吗?Brahmos 是如何进行并发渲染的?你认为这个特性所带来的而价值能够超过并发所固有的复杂性吗?


Yadav:我觉得社区里有些人对并发模式秉持了错误的态度。并发模式不仅是指在更新视图时提高性能(更新性能),它也包括在创建视图时提高性能(加载性能)。并发模式可以让开发人员控制视图加载的方式和时间以及渲染的顺序,以便提供最佳的用户体验。

并发模式有助于在应用程序在后台运行时保持 UI 的交互性。现在,由于浏览器只有一个线程,后台和前台的工作在同一个线程中进行,不过 UI 库(React/Brahmos)会在线程之间进行调度和切换。

我们可以用版本控制来解释这种行为。在典型的 git 工作流中,当我们实现一个特性时,我们会新建一个分支并在这个分支上进行开发,然后合并到 master 分支。但在此期间,如果我们有一个优先级的 bug 需要修复,就会暂时离开特性分支,处理优先级 bug,将变更推给 master 分支,然后继续在特性分支上开发。如果没有 git,我们需要先完成特性任务再去修复 bug。

与此类似,并非所有针对浏览器的修改都具有相同的渲染优先级。对于用户来说,最重要的是感知体验,而不是一个库/应用程序在处理渲染任务上花费了多少时间。并发模式试图通过使用启发式、更新源(例如用户交互或 JavaScript 回调)或声明性提示(useTransitionuseDeferredValue)来决定优先级,从而获得最佳体验。它让程序库在给定的时间内完成最重要的工作,以获得更好的用户体验。

我认为这种模式是绝对值得研究的。并不是说我们不能改进应用程序本身的并发性(可能是通过解除约束、管理竞态条件、自己管理优先级),但它给应用程序带来的复杂性是巨大的。React 的并发模式试图将复杂性隐藏在库当中,并提供一个声明性 API,提示应用程序应该如何渲染。

实现并发模式很难,而且有很多情况需要考虑。在为 Brahmos 实现并发模式时,当我以为可以搞定时,另一个问题就会冒出来,我不得不重新进行全盘考量。但考虑到它所带来的可能性,在这个模式上投入是有意义的。

目前,Brahmos 支持所有即将到来的并发模式。它支持 fiber 架构、时间切片、转换、数据获取的 suspense 和 suspense 列表。

API 保持不变,Brahmos 解决并发模式问题所采用的架构和方法与 React 略有不同。例如:

Brahmos 没有将行为和启发式划分为多种优先级,而是将更新划分为三个类别:

首先,必须同步渲染和提交的更新——不能暂停(比如由事件引起的更新)。

其次,更新可以暂停,但更新的值不能修改(比如由 setState 引起的更新,不是源自用户交互)。

第三,推迟的更新,可以暂停,可以变旧,可以被延迟(像异步更新、转换内的更新)。如果前台状态发生变化,异步和延迟更新就会变旧。

Brahmos 直接在前台的 fiber 树上进行高优先级的更改,因为它们必须同步刷新。

Brahmos 为每一次转换维护一个单独的更新列表,因此它们可以独立运行,一个转换不会阻碍另一个转换。


InfoQ:考虑到与 React API 的相似之处,将现有的 React 代码迁移到 Brahmos 有多容易?你会建议在新项目中使用 Brahmos 吗?


Yadav: Brahmos 的最终目标是让 React 的迁移像起个别名一样简单。但目前最大的障碍是与子组件相关的 React API。Brahmos 将所有静态节点合并为一个,子组件看起来和 React 不一样——尽管我们确实有一个解决办法。但是第三方 React 组件确实需要这种支持。

由于 Brahmos 所做的主要优化是将静态和动态部分划分开来,并将 JSX 转换为带标记的模板字面量,因此我们也在研究如何对第三方模块进行后处理,以便将 createElement 语法转换为带标记的模板字面量。顺便说一下,Brahmos 也支持 createElement 语法,只是 Brahmos 将它归为动态的部分。

我们有一些计划,使用 Brahmos 来优化现有的 React 应用程序,但还有很长的路要走。


InfoQ:你可以举一些例子说明 Brahmos 相对于其他框架的优势吗?


Yadav:Brahmos 的主要目标是提高服务器和浏览器 UI 渲染的性能。目前,Brahmos 仍处在开发阶段,所以我们还没有任何基准测试结果。下面是 Brahmos 提升性能的各种方法:

  1. 包大小(缩小+压缩)

Brahmos:~12kb(涵盖了大部分 React API,包括即将推出的并发模式)。

Preact+Preact Compact:~9kb(但 Preact 不支持并发模式)

React+React-DOM:38.5kb(如果支持并发模式,它可能会变得更大一些)。

还有其他一些想法可用来缩小 Brahmos 体积,另外我们也在研究如何在支持 React 的第三方库的同时实现摇树优化。

  1. 应用程序包的性能

  2. Brahmos 的 JSX 转换输出体积也比 React 的应用程序代码小。此外,它还可以减少整体加载解析时间,因为标记的模板字面量是一个字符串,不必像对象文字那样在脚本加载时进行解析。

  3. 渲染/更新时间

  4. 在 Brahmos 中,我们将静态部分组合为一个节点,遍历变成 O(动态节点),在 React 中为 O(节点)。因此,在 Brahmos 中找到应用于 DOM 的更新所需的遍历时间要少一些。

  5. 服务器端渲染

  6. 由于 Brahmos 将 JSX 转换为标记的模板字面量(已经是一个字符串),因此将应用程序渲染为字符串比渲染来自 VDOM (React Element)的字符串具有更高的性能。

  7. 服务器端异步渲染(尚未构建)

除了性能改进之外,我们还计划在服务器端引入异步渲染。Brahmos 从一开始就考虑了异步渲染,因此这个架构也可以支持服务器端异步渲染。这种渲染方式可以让服务器和客户端的逻辑保持统一,并且可以消除很多用于标识路由和 API 调用的约定。


InfoQ:反过来说,使用 React 比使用 Brahmos 更容易做哪些事情呢?


Yadav:Brahmos 只是针对浏览器和服务器渲染,不支持其他目标。由于使用了 VDOM, React 更容易支持多个目标,而且由于 Brahmos 中没有 VDOM,所以它不能支持不同的渲染器。

另外,对于主要由动态部分组成的应用程序(比如数据可视化),可能不会从 Brahmos 中获得太多好处。重度使用数据可视化和主要由动态部分组成的应用程序并不适合使用 Brahmos。


InfoQ:Brahmos 路线图的下一步要做什么?


Yadav:首先,我们的目标是支持 React 第三方库,然后是服务器端渲染(SSR)。这样 Brahmos 就可以立即为社区带来好处。我们还计划在 SSR 中引入异步渲染支持,这将对当前 SSR 应用的架构产生重大影响。

我们还将寻求对 React 开发工具的支持。


嘉宾简介


Sudhanshu Yadav 是 JavaScript 和 React 的粉丝,对框架的内部结构和工作原理有着浓厚的兴趣。Yadav 在 HackerRank 担任前端架构师,开发了 BrahmosJS、response -number-format、packagebind 和其他一些 OSS 工具。他还组织了一个会议小组,讨论不同技术栈的内部原理。


原文链接


Brahmos, a New, Small, React-like UI Framework with Concurrent Rendering – Q&A with Sudhanshu Yadav


2020 年 11 月 07 日 08:001885

评论

发布
暂无评论
发现更多内容

进击谷歌:多线程下程序顺序怎么稳定不乱?

架构师修行之路

数据结构与算法

有一种自我欺骗,叫只为孩子

zhoo299

随笔杂谈 家庭

云原生架构的基石

soolaugust

Docker 架构 Kubernetes 容器 云原生

SpreadJS 纯前端表格控件应用案例:集成 Odoo提升企业ERP表格功能

Geek_Willie

开源 SpreadJS Odoo

Pulsar 联合 TiDB 推出大数据场景数据应用分析解决方案

Apache Pulsar

大数据 InfoQ Apache Pulsar #TiDB

法定数字人民币将成中国金融新名片

CECBC区块链专委会

数字货币 人民币

ST在keil下开发时候文件options配置的一些小技巧

良知犹存

嵌入式

Python3 for ... else ...陷阱

王坤祥

Python Python PEP

大厂面试必读,JAVA进阶神书《深入理解Java虚拟机》第三版更新内容全曝光!

华章IT

JVM 虚拟机 周志明 Java虚拟机 jvm调优

四种主要的 IO 模型

方明

Netty

为什么一旦自己创业了,很难再回到公司去坐班?

北柯

创业 互联网 创业心态 上班 上班族

一文吃透PHP进程信号处理

书旅

php Linux 信号

“庆俞年”大战,真正受损的不是李国庆

北柯

创业 合伙人 创业者 互联网人 当当网

优雅快速的统计千万级别uv

架构师修行之路

哈希表 数据结构与算法

微服务-技术专题-设计原则AFK

李浩宇/Alex

核查框架新的选择

柿子

jsr-303 核查框架 butterfly

浅谈如何做好软件研发团队的盘点

大黄蜂

团队管理 技术管理

吃透Laravel的Ioc容器

书旅

laravel 容器 ioc

LeetCode题解:66. 加一,新数组求和再翻转,JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

奈学:reaseShared共享式释放锁

奈学教育

共享锁

华为:新政务风口下加宽“护城河”

脑极体

56张图入门操作系统——内功心法,适合所有程序员

执鸢者

前端 操作系统

跟我一起基于Karma搭建一个测试环境(下)

Jack Q

测试框架 前端进阶训练营 Karma

为什么 Bash 脚本总是不稳定?

柴锋

bash Linux DevOps 运维 Shell

浅谈技术管理之团队管理

大黄蜂

团队管理 技术管理

Flink所需组件-1

小知识点

scala 大数据 flink 流计算

Week11

一叶知秋

9大训练营免费开营!阿里云大数据团队的独门绝学全在这了

Apache Flink

大数据 训练营

《精益创业》摘要

孙苏勇

书摘 精益创业

大数据技术发展(二):Hadoop 技术生态圈的发展

抖码算法

Java 大数据 hadoop 大数据技术 hadoop3

2w字 + 40张图带你参透并发编程!

cxuan

Java 后端 并发

NLP领域的2020年大事记及2021展望

NLP领域的2020年大事记及2021展望

Brahmos:一个更小、更快的类React UI框架,支持并发渲染-InfoQ