跳到主要内容

React Native 0.82 - 新纪元

·13 分钟阅读
Vitali Zaidman
Vitali Zaidman
Meta 软件工程师
Nicola Corti
Nicola Corti
Meta 软件工程师
Gabriel Donadel Dall'Agnol
Gabriel Donadel Dall'Agnol
Expo 软件工程师
Alan Hughes
Alan Hughes
Expo 软件工程师

今天,我们很高兴地发布 React Native 0.82:第一个完全在新架构上运行的 React Native 版本。

这对 React Native 来说是一个里程碑式的版本,我们相信这是一个新时代的开始。在未来的版本中,我们将删除旧架构中剩余的代码,以减少安装大小并简化代码库。

此外,0.82 还附带了一个实验性的可选择启用更新版本的 Hermes,称为 Hermes V1。我们还通过将 React 版本更新到 19.1.1 来启用多个 React 功能,并支持 DOM 节点 API。

亮点

仅支持新架构

在 React Native 0.76 中,我们宣布新架构成为 React Native 的默认架构。

从那时起,新架构经过了测试和完善,我们相信它可以成为 React Native 此版本和未来版本的唯一架构。

这意味着,如果您尝试在 Android 上设置 newArchEnabled=false,或者在 iOS 上尝试使用 RCT_NEW_ARCH_ENABLED=0 安装 CocoaPods,这些都将被忽略,您的应用程序仍将使用新架构运行。

如何迁移

如果您尚未将项目迁移到新架构,我们建议您首先将项目迁移到 React Native 0.81 或 Expo SDK 54。这些是允许您使用旧架构的最后版本。它们包含专门用于帮助迁移到新架构的警告和性能改进。
然后在 0.81 中启用新架构并验证您的应用程序是否正常工作。
一旦您在 0.81 中使用了新架构,您就可以安全地更新到 React Native 0.82,该版本会阻止启用旧架构。

如果某个不兼容的第三方依赖项阻止您迁移到新架构,我们建议您直接联系库维护人员。

如果 React Native 核心中的错误阻止您迁移,我们建议您通过我们的问题跟踪器联系我们。

互操作层和第三方库兼容性

我们将在可预见的未来保留代码库中的互操作层。互操作层所需的所有类和函数都不会很快被删除。我们将在未来分享有关互操作层删除的进一步更新。

我们还验证了提供与两种架构向后兼容的第三方库将继续与 0.82 协同工作,其中新架构是唯一的架构。

旧架构类的移除

为了确保向后兼容并减少破坏性更改,此版本中我们不会从 React Native 核心中移除旧架构的任何 API。移除旧架构将使我们能够显著减小整体包大小,因此计划从下一个 React Native 版本开始移除。

您可以在RFC0929: 移除 React Native 的旧架构中找到更多信息。

实验性 Hermes V1

React Native 0.82 添加了对选择 Hermes V1 的支持。

Hermes V1 是 Hermes 的下一代演进。我们已经在内部应用程序中对其进行了实验,现在是社区也尝试它的时候了。它带来了编译器和 VM 的改进,从而提升了 Hermes 的性能。

从初步测试和基准测试来看,Hermes V1 在各种场景下都优于当前的 Hermes。我们已经看到了捆绑包加载和 TTI 的改进。这些改进强烈依赖于应用程序的详细信息。

Expensify 应用程序(一个真实世界且复杂的应用程序)中,我们看到了以下改进

指标Android(低端设备)iOS
捆绑包加载时间快 3.2%快 9%
总 TTI快 7.6%快 2.5%
内容 TTI快 7.2%快 7.5%

对于总 TTI,我们测量了从捆绑包加载到应用程序中第一个屏幕渲染并可交互所需的时间。

对于内容 TTI,我们测量了组件从自身首次渲染到可交互所需的时间。

Hermes V1 尚未包含 JS 到原生编译(以前称为“静态 Hermes”)或在 React Native EU 2023 期间展示的 JIT 编译。我们仍在测试这些功能,并将在取得进展后分享更多信息。

如何启用 Hermes V1

信息

Hermes V1 处于实验阶段,您需要从源代码构建 React Native 才能试用。一旦 Hermes V1 在未来的 React Native 版本中作为默认发布,此限制将被取消。

要在您自己的项目中试用 Hermes V1,请按照以下步骤操作

  1. 通过修改 package.json 文件中的相应部分,强制您的包管理器解析 Hermes V1 编译器包的实验版本(请注意,当前的版本命名约定仅适用于 Hermes V1 的实验阶段)
"resolutions": {
"hermes-compiler": "250829098.0.1"
}
  1. 通过在 android/gradle.properties 中添加 hermesV1Enabled=true 来为 Android 启用 Hermes V1
android/gradle.properties
hermesV1Enabled=true

此外,通过编辑 android/settings.gradle 配置 React Native从源代码构建

android/settings.gradle
  includeBuild('../node_modules/react-native') {
dependencySubstitution {
substitute(module("com.facebook.react:react-android")).using(project(":packages:react-native:ReactAndroid"))
substitute(module("com.facebook.react:react-native")).using(project(":packages:react-native:ReactAndroid"))
substitute(project(":packages:react-native:ReactAndroid:hermes-engine")).using(module("com.facebook.hermes:hermes-android:250829098.0.1"))
}
}
  1. 通过使用 RCT_HERMES_V1_ENABLED=1 环境变量安装 pods 来为 iOS 启用 Hermes V1。
RCT_HERMES_V1_ENABLED=1 bundle exec pod install

请记住,Hermes V1 与预编译的 React Native 构建不兼容,因此请确保在安装 pods 时不要使用 RCT_USE_PREBUILT_RNCORE 标志。

  1. 要确认您的应用程序是否正在运行 Hermes V1,请在您的应用程序或 DevTools 控制台中执行以下代码。此代码将返回 Hermes 版本,该版本应与步骤 1 中指定的版本(250829098.0.1)匹配
// expecting "250829098.0.1" in Hermes V1
HermesInternal.getRuntimeProperties()['OSS Release Version'];

React 19.1.1

此 React Native 版本附带最新的 React 稳定版:React 19.1.1

此 React 版本包含对 React Native 所有者堆栈的全面支持。早在 React Native 0.80 中,当我们发布对 19.1.0 的支持时,我们提到如果您使用 @babel/plugin-transform-function-name Babel 插件,则所有者堆栈未完全支持。此版本取消了此限制,并为所有 React Native 用户启用了所有者堆栈。

之前之后
Example error thrown without Owner Stacks
Example error thrown with Owner Stacks

React 19.1.1 还改进了在 React Native 的 Suspense 边界中 useDeferredValueDOM 节点 API

从 React Native 0.82 开始,原生组件将通过 refs 提供类似 DOM 的节点。

以前,原生组件提供 React Native 特定的对象,只有少量方法,如 measuresetNativeProps。此版本之后,它们将提供实现 DOM API 子集的节点,用于遍历 UI 树、测量布局等,就像在 Web 上一样。例如

function MyComponent(props) {
const ref = useRef();

useEffect(() => {
const element = ref.current;

// New methods
element.parentNode;
element.parentElement;
element.childNodes;
element.children;
const bounds = element.getBoundingClientRect();
const doc = element.ownerDocument;
const maybeElement = doc.getElementById('some-view');

// Legacy methods are still available
element.measure((x, y, width, height, pageX, pageY) => {
/* ... */
});
}, []);

return <View ref={ref} />;
}

此外,这将暴露对叶文本节点(由 Text 组件创建)和代表 React Native 根节点的文档节点的访问。

这是一个向后兼容的更改,因为新节点将继续实现旧方法(如 measure)。

有关更多信息,请查看我们的文档

其他更改

Web 性能 API (Canary)

React Native 现在实现了 Web 上可用性能 API 的子集

  • 高分辨率时间:定义 performance.now()performance.timeOrigin
  • 性能时间线:定义 PerformanceObserver 和访问性能对象中性能条目(getEntries()getEntriesByType()getEntriesByName())的方法。
  • 用户计时:定义 performance.markperformance.measure
  • 事件计时 API:定义报告给 PerformanceObserverevent 条目类型。
  • 长任务 API:定义报告给 PerformanceObserverlongtask 条目类型。

它们允许在运行时跟踪应用程序性能的不同方面(用于遥测),并且它们将在 React Native DevTools 中的性能面板中可见(在未来的 React Native 版本中可用)。

它们目前仅在金丝雀发布级别可用,并将在未来的 React Native 版本中作为稳定版发布。

Android 的优化调试构建类型

从 React Native 0.82 开始,您将能够使用 debugOptimized 构建类型来加快您的开发体验。

历史上,Android 创建了两种默认的构建变体

  • debug,在开发时默认使用,允许您连接到各种调试器工具,例如 React Native DevTools、Metro、Android JVM 和 C++ 调试器
  • release,用于将您的应用程序发布到生产环境。这是完全优化的,包含混淆和优化,这将使调试更加困难。

由于大多数 React Native 开发者在开发时不需要使用 C++ 调试器,我们引入了 debugOptimized 构建类型。

使用 debugOptimized,您的动画和重新渲染将更快,因为您正在运行一个启用了多项 C++ 优化的 React Native 构建。同时,您仍然能够使用 React Native Dev Tools 来调试您的 JavaScript 代码。

使用 debugOptimized 时,您将无法使用 C++ 本机调试器,但如果您使用调试构建类型,您仍然可以使用它。

要运行应用程序的 debugOptimized 变体,您可以调用

npx react-native run-android --mode debugOptimized
信息

debugOptimized 构建类型也已向后移植到 React Native 0.81 和 Expo SDK 54。

您可以在这些示例中看到 debugOptimized 的实际应用,我们在屏幕上渲染了多个动画。

运行 debug 的构建以约 20FPS 运行,而 debugOptimized 则以约 60FPS 运行

调试debugOptimized
Example build running with debugExample build running with debugOptimized

重大变更

未捕获的 promise 拒绝现在将引发 console.error

在上一版本中改进了未捕获 JavaScript 错误的报告之后,我们现在也将通过该机制报告未捕获的 promise

Example of a promise rejection reported to console

由于一个错误,这些之前完全被吞噬和忽略了,因此在升级到 React Native 0.81 后,请预期一些预先存在的错误会浮出水面。因此,之前预先存在的错误也可能在报告给后端 JavaScript 错误中浮出水面,并导致新报告激增。

其他重大变更

通用

  • ReactNativeFeatureFlags 移动到 src/private
    • 通常,您不应该依赖 ReactNativeFeatureFlags,因为那是一个私有 API。
  • Appearance.setColorScheme() 的类型已更新,不再接受可空值
    • 在需要重置颜色方案的特殊情况下,请使用“unspecified”而不是 null/undefined。

iOS

  • RCTDisplayLink 已从旧版 API RCTModuleData 迁移,因为我们计划在未来移除它。

Android

  • com.facebook.react.bridge.JSONArguments 类被删除,因为它意外地是 public
  • 弃用 MessageQueueThreadPerfStats
    • 我们已弃用此 API 并将其替换为存根。您不应再依赖此 API 的统计数据,因为提供的统计数据不可靠
  • 将 Gradle 从 8.x 升级到 9.0.0
    • Gradle 9.0.0 下一个主要稳定版本中所有更改的列表可在此处查看,但我们预计对用户没有任何影响

C++

  • 删除 CallbackWrapper.h / LongLivedObject.h 的向后兼容性头文件
    • 这些头文件的正确包含方式是 #include <react/bridging/LongLivedObject.h>#include <react/bridging/CallbackWrapper.h>
    • 您不应使用 #import <ReactCommon/….h> 下的旧包含

阅读0.82 的更新日志中所有重大更改的完整列表。

致谢

React Native 0.82 包含来自 93 位贡献者的 868 次以上的提交。感谢大家辛勤的工作!

我们要特别感谢在此版本中做出重大贡献的社区成员

升级到 0.82

除了升级到新版本文档之外,请使用React Native 升级助手来查看现有项目在 React Native 版本之间的代码更改。

要创建新项目

npx @react-native-community/cli@latest init MyProject --version latest

如果您使用 Expo,React Native 0.82 将作为 expo@canary 版本的一部分提供。

下一个 SDK,SDK 55,将随下一个 React Native 稳定版本:0.83 一起发布。

信息

0.82 现在是 React Native 的最新稳定版本,0.79.x 变为不受支持。有关更多信息,请参阅React Native 的支持策略