去年,Google Angular负责人Minko Gechev在dotJS会议上的演讲中表示,Angular和React本质上是相同的框架。这在JavaScript业界中是一个激进的说法,开发者甚至被鼓励构建自己的框架。毕竟,Angular使用类和模板,而React使用函数和JSX,他承认。但在底层,它们提供了相同的功能。
Gechev表示,Google赋予他一个任务,他认为这可能是Web开发中的首次尝试:融合两个框架;在这个案例中是Angular和Wiz,Google的内部框架。他解释了这对Web开发者和框架的未来意味着什么。
在演讲中,他说:“过去从未听说过人们在融合两个不同的框架。” 这让他能够弄清楚Web框架由什么组成,并看到框架之间有很多相似之处,以及它们是如何随着时间推移来共享相同的想法和实现的。
他说,React和Angular在如何保持组件树与UI同步方面非常相似。这通常被称为反应性,或状态随时间的传播。在两种情况下,开发者都必须指定状态已更改。在React中,这是通过钩子完成的,在Angular中,这是通过zone.js完成的。但是,框架将默认从上到下遍历组件树,同时找到所有差异并应用到DOM。
他提供了另一个相似之处的例子:一个应用程序组件使用另外两个组件——用户配置文件和购物车。配置文件组件显示用户名,购物车组件遍历购物车中的物品集合。每个组件都显示其数量。
他说:“在底层逻辑中,一旦运行应用程序,框架将构建组件树。” “如果我们更新购物车的状态,比如说我们将第一项的数量更改为1,Angular和React都将执行变更检测和进行页面数据调度,但使用的算法几乎相同。它们将遍历组件树,首先到达根组件,然后它们将到达用户配置文件组件。”
如果这还不足以说服质疑者,Gechev还拿出基准测试来展示这两个框架的相似性。
他说:“Angular和React在角色交换方面都表现得相当差,而在局部更新方面,两个框架都表现得相当不错。”
他补充说,实际应用程序可能有所不同。可能有数百或数千个组件一直在运行。
他说:“如果我们不得不一个接一个地遍历这些组件树以找到差异并在视图中反映这些差异,这将需要很长时间。所以Angular决定改进其反应性故事。”
Angular在编译器上引入了静态依赖跟踪。他们在Angular 16中决定添加Signals。Signals是一种反应性原语;它们是自动跟踪其使用位置的变量。因此,当变量更改时,Signals能够使依赖于此变量的计算失效。
Ember、Solid、Vue、Svelte和其他框架也部署了Signals。(有关React和Signals的更多信息,请参见Paul Scanlon的文章,“Signals是否刚刚进入React”。)
他说:“你可以看到,所有这些框架现在都汇聚在相同的反应性原语,Signals上。”
用例融合
Wiz框架在历史上一直应用于与Angular不同的用例,它更类似于Astro和Qwik。
“它一直在为性能特别关键的应用程序提供服务——我们可以想到Google搜索或YouTube——另一方面,Angular历史上更多地用于企业客户,Google Cloud、Google Analytics等。然而,随着时间的推移,我们注意到这些框架的要求也开始汇聚。”
Signals开启了融合对话,他说,因为Wiz团队在Angular中看到后想要添加Signals。而Angular团队成员则希望Wiz的可恢复性,这是Wiz 10年前引入的一个概念,后来被Qwik采用了。
那时,Gechev被指派了融合两个框架的任务。
“浏览Wiz团队的Google聊天记录时,我看到他们一直在与YouTube合作,将平台的UI从他们的旧虚拟DOM实现重新实现为Signals,”他说。“与此同时,Angular团队正在将Signals作为框架的一部分进行集成。所以我们决定联手。”
他说,这导致移动端YouTube使用Wiz与Angular Signals,这在性能上取得了显著改进。例如,在智能电视上,他们看到了35%的提升。
现在有一个将 Signals 添加到 JavaScript 中的提案。目前处于第一阶段(TC39),参考实现使用的是 Angular Signals,因为它已被证明可以在多个框架中工作。
其他领域融合的可能性
然而,他警告说,融合并不是一项微不足道的任务,它可能需要在框架中进行大量更改。同时他补充说道,稳定性也需要考虑。但是,让他有信心可以完成的是,到目前为止——祝好运——Wiz/Angular融合在Google内部测试中没有破坏任何东西。
“每次我们在Angular中更改某些内容,我们都会打开一个拉取请求,我们将拉取请求的源代码与Google内部的单体存储库同步,该存储库大约有4500个Angular应用程序,其中一些应用程序有数百万行代码,”他说。“我们正在为所有受影响的应用程序运行测试,以确保没有变化,没有破坏。这意味着对我们来说很痛苦,调试所有这些测试,我们以前从未见过的代码。但这也确实保证了无与伦比的向后兼容性。”
““当选择框架时,不要过度思考。最终它将是相同的技术,只是不同的外观。”
“——Gechev”
他预测,事件重放和细粒度代码加载也将有可能融合。事件重放是谷歌用于弥合用户在观察其 Web 应用程序的结构和实际与之互动时所感受到的交互性差异的一种方法。目前,团队正在努力更新一个叫作 JS Action 或 Event Dispatch 的库,然后将其移入 Angular 代码库中。
Gechev说:“这和Google搜索中的事件重放代码相同,你可以在github.com/angular/angular
上找到它。我们已在 Angular 开发者预览版中添加了支持。你可以通过使用客户端水合技术,并指定启用事件重放特性来启用它。这为我们提供了另一个提升性能的可能性。”
“现在,我们可以通过提供较少的JavaScript来缩短下载和执行所需的时间,这已经通过可恢复性或一些花哨的部分水合实现,其中我们隐式指定了处理特定用户交互所需的最小代码。”
引入可延迟视图
这允许应用程序仅下载响应特定用户交互所需的最小代码量,而不是下载整个应用程序,他解释说。在Angular中不能以相同的隐式方式完成,因为这会破坏许多应用程序,而且它并不适合开发者今天使用Angular的范式。
为了解决这个差距,他们引入了可延迟视图,允许开发者在应用程序中创建交互性或水合岛屿。
他解释说:“使用可延迟视图,你可以将UI的一部分包装在一个块中,并指定你希望在满足特定条件时仅对这部分进行水合,这是使用服务器端渲染才有的语义。”
当客户端向服务器发送请求时,它提前提供了应用程序的标记,开发者将使用这些不同的块创建不同的交互岛屿,他说。
因此,如果用户交互是水合触发器,当用户与例如左侧导航栏交互时,它可以从服务器下载相应的JavaScript并水合应用程序的那部分,而无需下载任何剩余功能。
他说:“我们可以下载处理这个特定用户交互所需的最小JavaScript量,并且通过事件重放,以便我们不会丢失任何点击动作。”
对 Angular 的影响
这对Angular和Web开发者意味着什么?
Gechev告诉观众:“这将如何在Web开发者的工作中体现呢?实际上,这将只是我们随着时间引入到Angular中的逐步改进,在这个过程中,我们将寻求开源在行业中确立为最佳实践的原语。”
一些人可能认为融合的差异太大,他承认。例如,React没有依赖注入,Angular没有上下文API,但从根本上来说,它们都为了达到相同的目的。
他说:“在这两种情况下,我们都希望根据它们使用的上下文在我们的组件中注入数据。在Angular中,我们使用依赖注入来实现这一点。在React中,我们使用上下文API。它们看起来目的相同,但外观略有不同。它们也共享非常相似的数据结构。”
对开发者的建议
Chrome的首席工程师Addy Osmani发布了一个表格,从Web开发者的角度展示了每个框架中可用的功能,他在2024年Google I/O上分享了这个表格。Gechev修改了表格,以反映他自己的观点,即框架正在融合相同的功能。
“这对Web开发者意味着什么?你如何选择框架?”Gechev说。“当选择框架时,不要过度思考。最终它将是相同的技术,只是不同的外观。”
也就是说,他确实提供了一些在选择技术时有时会被忽视的建议。他建议Web开发者考虑稳定性和可靠性。
最后他建议:“我们要确保我们使用的是一个稳定的解决方案,它将与您长期相伴,拥有一个丰富、包容和能为你提供支持的生态系统非常重要,这是你真正喜欢使用的东西。”
“本文由公众号前端新世界翻译,AI辅助,有错误之处请留言反馈
原文链接:
https://thenewstack.io/google-angular-lead-sees-convergence-in-javascript-frameworks/