跳至主内容

React Native 0.79 - 更快的工具链及更多改进

· 1 分钟阅读
Alan Hughes
Alan Hughes
Software Engineer @ Expo
Shubham Gupta
Shubham Gupta
Software Engineer @ Dream11
Fabrizio Cucci
Fabrizio Cucci
Software Engineer @ Meta
Nicola Corti
Nicola Corti
Software Engineer @ Meta
非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

今天我们很高兴发布 React Native 0.79!

此版本带来了多方面的性能改进以及若干错误修复。首先,由于延迟哈希(deferred hashing)的引入,Metro 的启动速度现在更快,并且稳定支持包导出(package exports)。此外,由于对 JS 包压缩的改动,Android 的启动时间也将得到改善,还有更多改进。

重点更新

重点详解

Metro:更快的启动速度和包导出支持

此版本搭载了 Metro 0.82。该版本通过延迟哈希(deferred hashing)技术,通常将首次运行 yarn start 的速度提高了 3 倍以上(在大型项目和 monorepo 中提升更明显),使您的开发体验和 CI 构建日常运行更快。

Metro 启动速度对比

在 Metro 0.82 中,我们还将 package.json"exports""imports" 字段解析功能升级为稳定版。"exports" 解析最初在 React Native 0.72 中引入,而 "imports" 支持则是通过社区贡献添加的——现在这两项功能将在所有 React Native 0.79 项目中默认启用。

这提升了与现代 npm 依赖的兼容性,并为项目组织开辟了符合标准的新方式。

破坏性变更

虽然我们已在社区测试 package.json"exports" 功能一段时间,但此次切换可能对某些包和项目设置造成破坏性变更。

特别需要注意的是,我们已收到用户报告 Firebase 和 AWS Amplify 等流行包的兼容性问题,目前正在从源头修复这些问题。

若您遇到问题:

JSC 迁移至社区包

作为精简 React Native API 表面积工作的一部分,我们正将 JavaScriptCore (JSC) 引擎迁移至社区维护的包:@react-native-community/javascriptcore

此项变更不会影响使用 Hermes 的用户。

从 React Native 0.79 开始,您可以通过遵循 README 中的安装说明 使用社区支持的 JSC 版本。React Native 核心提供的 JSC 在 0.79 版本中仍将保留,但我们计划在近期将其移除。

将 JSC 迁移至社区维护包后,我们将能更频繁地更新 JSC 版本并提供最新功能。社区维护的 JSC 将采用与 React Native 不同的发布周期。

iOS:支持 Swift 的原生模块注册

本次更新重构了原生模块注册到 React Native 运行时的机制。新方法遵循与组件相同的注册方式,详见官方文档

从此版本开始,您可以通过修改 package.json 文件注册模块。我们在 ios 属性中新增了 modulesProvider 字段:

"codegenConfig": {
"ios": {
+ "modulesProvider": {
+ "JS Name for the module": "ObjC Module provider for the pure C++ TM or a class conforming to RCTTurboModule"
+ }
}
}

Codegen 将根据您的 package.json 文件自动生成所有相关代码。

若使用纯 C++ 原生模块,需遵循以下推荐配置:

Configure pure C++Native Modules in your app

For pure C++ Native Modules, you need to add a new ObjectiveC++ class to glue together the C++ Native Module with the rest of the App:

CppNativeModuleProvider.h
#import <Foundation/Foundation.h>
#import <ReactCommon/RCTTurboModule.h>

NS_ASSUME_NONNULL_BEGIN

@interface <YourNativeModule>Provider : NSObject <RCTModuleProvider>

@end
CppNativeModuleProvider.mm
NS_ASSUME_NONNULL_END

#import "<YourNativeModule>Provider.h"
#import <ReactCommon/CallInvoker.h>
#import <ReactCommon/TurboModule.h>
#import "<YourNativeModule>.h"

@implementation NativeSampleModuleProvider

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeSampleModule>(params.jsInvoker);
}

这种新方法统一了应用开发者和库维护者的原生模块注册流程。库开发者可在自己的 package.json 中声明相同属性,Codegen 将自动完成剩余工作。

此方案解决了我们在 0.77 版本引入的限制——当时无法在使用 Swift AppDelegate 时注册纯 C++ 原生模块。如您所见,这些变更均不涉及修改 AppDelegate,生成的代码可同时兼容 Swift 和 Objective-C 实现的 AppDelegate

Android:更快的应用启动

我们同时推出了一项重大改进,显著提升 Android 应用的启动速度。

此版本起,APK 中将不再压缩 JavaScript 包。此前 Android 系统需在应用启动前解压 JavaScript 包,导致应用启动明显延迟。

从本版本开始,我们将默认提供未压缩的 JavaScript 包,因此您的 Android 应用启动速度将整体提升。

Margelo 团队在 Discord 应用上测试该功能后获得了显著性能提升:三星 A14 设备上的测试显示,Discord 的可交互时间(TTI)缩短了 400 毫秒,仅通过一行代码变更就实现了 12% 的速度提升。

另一方面,未压缩的包会导致应用在用户设备上占用更多存储空间。若您对此有顾虑,可在 app/build.gradle 文件中通过 enableBundleCompression 属性切换此行为。

app/build.gradle
react {
// ...
// If you want to compress the JS bundle (slower startup, less
// space consumption)
enableBundleCompression = true
// If don't you want to compress the JS bundle (faster startup,
// higher space consumption)
enableBundleCompression = false

// Default is `false`
}

请注意:此版本 APK 体积将会增大,但用户从网络下载 APK 时不会承担额外成本,因为下载时 APK 会经过压缩传输。

重大变更

移除远程 JS 调试功能

作为持续改进调试体验的一部分,我们移除了基于 Chrome 的远程 JS 调试功能。这项传统调试方法已在 React Native 0.73 版本中被弃用并改为运行时选择启用。请使用React Native DevTools 进行现代化且可靠的调试。

这也意味着 React Native 不再兼容 react-native-debugger 社区项目。对于需要使用第三方调试扩展(如 Redux DevTools)的开发者,我们推荐使用 Expo DevTools Plugins,或集成这些工具的独立版本。

阅读更多内容,请参考这篇专门文章

内部模块更新为 export 语法

作为 JavaScript 代码库现代化工作的一部分,我们已将 react-native 中的多个实现模块统一更新为使用 export 语法替代 module.exports

我们总共更新了约 46 个 API,具体变更可查看更新日志

此变更对现有导入有细微影响:

Case 1: Default export
  // CHANGED - require() syntax
- const ImageBackground = require('react-native/Libraries/Image/ImageBackground');
+ const ImageBackground = require('react-native/Libraries/Image/ImageBackground').default;

// Unchanged - import syntax
import ImageBackground from 'react-native/Libraries/Image/ImageBackground';

// RECOMMENDED - root import
import {ImageBackground} from 'react-native';

Case 2: Secondary exports

There are very few cases of this pattern, again unaffected when using the root 'react-native' import.

  // Unchanged - require() syntax
const BlobRegistry = require('react-native/Libraries/Blob/BlobRegistry');

// Unchanged - require() syntax with destructuring
const {register, unregister} = require('react-native/Libraries/Blob/BlobRegistry');

// CHANGED - import syntax as single object
- import BlobRegistry from 'react-native/Libraries/Blob/BlobRegistry';
+ import * as BlobRegistry from 'react-native/Libraries/Blob/BlobRegistry';


// Unchanged - import syntax with destructuring
import {register, unregister} from 'react-native/Libraries/Blob/BlobRegistry';

// RECOMMENDED - root import
import {BlobRegistry} from 'react-native';

我们预计此变更的影响范围非常有限,特别是对于使用 TypeScript 和 import 语法的项目。请检查并修复可能出现的类型错误以更新代码。

技巧

强烈推荐使用根路径 react-native 导入

作为通用建议,我们强烈推荐从根路径 'react-native' 导入,以避免未来出现意外的破坏性变更。在下一个版本中,我们将弃用深层导入,这是精确定义 React Native 公共 JavaScript API 工作的一部分(参见 RFC)。

其他破坏性变更

此列表包含一系列其他破坏性变更,我们预计这些变更可能对您的产品代码产生轻微影响,值得注意:

  • box shadows 和 filters 中无效的无单位长度

    • 为使 React Native 更符合 CSS/Web 规范,我们不再支持在 box-shadowfilter 中使用无单位长度。这意味着类似 1 1 blackbox-shadow 将不再被渲染,您应改用带单位的格式如 1px 1px black
  • 从 normalize-color 移除错误的 hwb() 语法支持

    • 为使 React Native 更符合 CSS/Web 规范,我们限制了一些 hwb() 的无效语法。历史版本曾支持逗号分隔值(如 hwb(0, 0%, 100%)),现在不再支持(应迁移至 hwb(0 0% 100%))。更多细节请参考此提交
  • Libraries/Core/ExceptionsManager 导出更新

    • 作为现代化 React Native JS API 工作的一部分,我们更新了 ExceptionsManager,现在默认导出 ExceptionsManager 对象,并将 SyntheticError 作为次要导出

致谢

React Native 0.79 包含了来自 100 位贡献者的 944 多次提交。感谢大家的辛勤工作!

我们要向在此版本中做出重要贡献的社区成员表示感谢:

同时感谢为本版本说明文档撰文的作者:

升级至 0.79 版本

对于现有项目,除了升级文档外,请使用 React Native Upgrade Helper 查看 React Native 各版本间的代码变更。

要创建新项目:

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

若您使用 Expo,React Native 0.79 将在即将发布的 Expo SDK 53 中作为默认版本获得支持。

信息

0.79 现已成为 React Native 的最新稳定版本,0.76.x 系列将停止支持。详细信息请参阅 React Native 支持策略。我们计划在近期发布 0.76 的最终终止支持更新。