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
发布后就产生了,人们开始思考如何在网页和移动设备上都使用 RN
。Nicolas 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
一直在努力构建 Expo
在 Web
上的 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,以“更快地发布功能,覆盖更多平台,并减少工程师数量”。Meta
对UI
的“通用”解决方案的直接投资意味着它将加速其发展。此外,如果 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
事件循环以使其更接近 we
b 事件循环之类的事情也正在进行中。
关注点
原生设备上的性能
React Strict DOM
中将翻译层从网页端移至原生实现可能会对移动应用程序的性能产生负面影响,这是一个潜在的关注点。React Native
在性能方面一直备受质疑,因此测试这一点并确保使用 RSD
不会出现任何退化是非常重要的。
为了了解性能影响,我进行了一些初步测试,使用Flashlight
渲染了一个 Flatlist
中的1000
个项目(手动覆盖任何虚拟化),每个项目都有一个视图和一些文本。
从我的基本测试中,我发现React Native
和 React 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 Web
和React Strict DOM
之间的基本差异来促进迁移。由于这些库已经在RN API
之上有了抽象层,所以在它们将来采用 RSD
的情况下,建立在这些库之上的应用程序应该能够在几乎不修改代码库的情况下从 React Native Web
切换到 RSD
。
何时稳定?
这自然引出了最后一个问题。RSD
在一个多月前宣布。它仍处于实验阶段,RSD
何时可以准备投入生产仍然不清楚。在为原生应用程序准备就绪之前,仍然有很大一部分 API 表面需要涵盖。
最初的 RFC
是在 2022 年夏季开放的,这表明开发已经进行了大约两年。考虑到项目的范围和复杂性,如果再过一两年才完全稳定,那也不足为奇。
总结
对于 React Native
社区和更广泛的React
生态系统来说,这是一个令人兴奋的时刻。看到 Meta
使用 RSD
进入通用应用程序领域意味着由大型科技公司采纳了一个代码库可以驱动原生应用程序 + 网页的愿景。这个努力将意味着作为一个社区,我们将看到更高质量、性能更好的通用应用程序,并且未来将会有更多的工具来促进它们的构建。