React Strict DOM:React Native 通用应用程序的未来


Meta 宣布发布了 react-strict-dom。从根本上讲,这将改变我们使用 React Native(以及在网页上使用 React)的方式。它提供了一套统一的 UI 原语,带有样式,可以在网页和移动设备上通用使用!现在,“编写一次,到处部署”对于那些在通用 RN 领域的人来说并不是新闻——react-native-web 已经存在多年,可以处理将 RN 的源码转换为网页· DOM· 元素。这是一种 ·RN ·优先,网页次之的方法,但是付出了一定的代价。

本文探讨了为什么react-strict-dom很重要,它与 react-native-web 有何不同,以及为什么你应该感到兴奋!

背景

RN UI 在网页和移动设备上的尝试

在网页上使用 React Native 的重要里程碑的时间线

“编写一次,随处运行”的愿景早在 2015 年 React Native 发布后就产生了,人们开始思考如何在网页和移动设备上都使用 RNNicolas Gallagher 在 2016 年发布了 React Native Web,作为 React Native React DOM 之间的互操作层,从根本上将 RN 的组件和 API 转换为网页组件。Twitter Lite 使用`` React Native Web 创建了仅用于网页的组件,并且至今仍在为 Twitter 网页版提供大部分组件。

与此同时,微软的开发人员开发了 ReactXP,这是他们如何弥合 React 网页版和 React Native 之间 UI 层差距的方式。这个项目获得了很大的关注,并被用于 Skype。最终,ReactXP 在 2020 年被弃用。

与此同时,Expo 的开发人员也一直在致力于实现通用视觉。早在 2019 年,Expo 宣布支持进入 web 测试版。从那时起,Evan Bacon 一直在努力构建 ExpoWeb 上的 RN 视觉。在 2020 年,Evan 发布了如何使用 Metro 打包 web 应用程序的演示。到 2022 年,Expo Router 被宣布推出,这是 ``Expo 关于如何使用遵循网页和移动标准的导航路由器来驱动web和移动设备的单一代码库的看法。Expo Router 在底层使用 Metro,统一了应用程序的网页和移动版本的打包过程。

减少 React DOM 和 React Native 之间 API 碎片化的 RFC:react-strict-dom

在 2022 年 8 月,React Native Web 的创建者 Nicolas Gallagher 创建了一个 RFC,提议应该努力减少 React 在网页上与 React Native 之间的 API 差异。最初被称为“strict DOM”,这是 React DOM 的子集。

RFC 的主要目标是:

  • 提高网页上的性能
  • 使 React 开发人员更容易转向 React Native
  • 实现更高质量的“通用”应用程序。

Nicolas Meta 的其他人员(以及来自开源社区的密集讨论和建议)在一年多的时间里一直在努力推动这一工作,直到 2024 年 2 月推出。
##为什么 react-strict-dom 如此重要?
虽然社区一直在努力实现通用应用程序的愿景,但直到 RSD 发布之前,Meta 从未“认可”这一点。Meta 总是推崇“学一次,随处编写”的口号,暗示 React Native 可用于多个平台,但需要为每个平台进行不同的实现。这与社区一直向着“编写一次,随处运行”的愿景相反。RSD Meta首次正式认可的跨平台UI解决方案,涵盖了网页和移动设备。

深入了解细节,这些是我认为这是一件非常重要的事情的主要原因!

Meta 本身正在使用它

当你在 Github 上查看 react-strict-dom 存储库时,它提到Meta的团队已经在生产中使用 RSD,以“更快地发布功能,覆盖更多平台,并减少工程师数量”。

MetaUI的“通用”解决方案的直接投资意味着它将加速其发展。此外,如果 Meta 将其用于生产中的应用程序,这意味着它将在一些最频繁使用的网站/应用程序中经过实战测试,这自然意味着它将被极度优化和可扩展化。

网页性能提升

我对 React Native Web 的一个问题是它是一个相当庞大的依赖项。如果没有启用树摇,捆绑大小接近 300KB。加上 React-DOM 的约 125KB,你的依赖项仅处理捆绑就有约 425KB(尽管这些是未压缩的大小)。这是因为 React Native Web 尝试覆盖 React Native API 的整个实现,因此将不得不支持大量可能不想在网页上使用的功能。

例如,Animated API ``在 react-native-web 中超过70KB的大小,并且依赖于JS层来执行动画,这比仅使用 CSS 进行动画要慢。同样,您可能不想在网页上使用 VirtualizedList、PanResponders 和其他 React Native `生态系统的组件。

对于 react-native-web,转译和支持 API 的负担在网页应用程序上,这可能会导致性能下降,因为诸如 SEO 排名之类的原因。

React Strict DOM 采取了一种几乎相反的方法。它将兼容性和 API 的翻译负担放在了移动端,那里可以更充分地处理将 API 映射到原生层功能的负担。如果有任何性能损失,这已经存在于 React Native 工作方式的核心,其中JS层必须将视图、文本和其他元素委托给原生层实现。

将 React 开发人员池与 React Native 更接近

阻碍 web 开发人员从 React 切换到 React Native 的主要因素之一是API的重大差异。Web 开发人员习惯于 DOM,这也是使 React 首先具有吸引力的原因之一。您可以使用 <div><input><button> 和几乎任何其他在 DOM 中存在的元素,几乎不需要修改(最初对人们来说最大的困惑通常是从 class 切换到 className)。

React Native 显然更加受限制 - 开发人员需要熟悉一组定义良好的 API,这些 API DOM 类似,但在根本上却有很大的不同。这意味着开发人员开始使用 React Native 存在着显著更大的学习曲线。

RSD 接受DOM元素,并通过引入对React开发人员来说更加熟悉的API来消除开发人员从 React 迁移到 React Native 时的认知负担。

不仅是 API,作为 RFC 的一部分,诸如重新设计 React Native 事件循环以使其更接近 web 事件循环之类的事情也正在进行中。

关注点

原生设备上的性能

React Strict DOM 中将翻译层从网页端移至原生实现可能会对移动应用程序的性能产生负面影响,这是一个潜在的关注点。React Native 在性能方面一直备受质疑,因此测试这一点并确保使用 RSD 不会出现任何退化是非常重要的。

为了了解性能影响,我进行了一些初步测试,使用Flashlight渲染了一个 Flatlist 中的1000个项目(手动覆盖任何虚拟化),每个项目都有一个视图和一些文本。

从我的基本测试中,我发现React NativeReact Strict DOM 几乎产生了相同的结果,这是一个令人鼓舞的迹象。但是,这只是一个非常基本的测试,需要更大范围的测试,测试更多的 API 表面来更准确地了解性能影响。

对于现有的通用应用程序的实际采用计划

另一个考虑因素是现有应用程序使用 react-native-web 或普通 RN 如何迁移到 react-strict-dom,而无需对其代码库进行大规模改造。理想情况下,应该有一条平稳的迁移路径,最大限度地减少手动修改的需求。

我想到的一些想法是利用代码转换来自动处理大部分迁移。这可能涉及自定义的 Babel 配置或其他构建时工具,将现有的 React Native Web 代码转换为与 React Strict DOM 兼容的代码。

另一种方法可能是积极地将 UI 原语抽象为自定义组件,这些组件目前使用 React Native Web,但将来可以轻松地与 React Strict DOM 相当的组件进行替换。通过及早构建这个抽象层,迁移到 React Strict DOM 可能会更容易。

更现实的情况是,像 Tamagui Gluestack 这样的流行通用 UI 库也可以通过抽象掉 React Native WebReact Strict DOM之间的基本差异来促进迁移。由于这些库已经在RN API之上有了抽象层,所以在它们将来采用 RSD 的情况下,建立在这些库之上的应用程序应该能够在几乎不修改代码库的情况下从 React Native Web 切换到 RSD

何时稳定?

这自然引出了最后一个问题。RSD 在一个多月前宣布。它仍处于实验阶段,RSD 何时可以准备投入生产仍然不清楚。在为原生应用程序准备就绪之前,仍然有很大一部分 API 表面需要涵盖。

最初的 RFC 是在 2022 年夏季开放的,这表明开发已经进行了大约两年。考虑到项目的范围和复杂性,如果再过一两年才完全稳定,那也不足为奇。

总结

对于 React Native 社区和更广泛的React生态系统来说,这是一个令人兴奋的时刻。看到 Meta 使用 RSD 进入通用应用程序领域意味着由大型科技公司采纳了一个代码库可以驱动原生应用程序 + 网页的愿景。这个努力将意味着作为一个社区,我们将看到更高质量、性能更好的通用应用程序,并且未来将会有更多的工具来促进它们的构建。