React 18 已经存在了两年多,现在终于到了迎接 React 19 的时候了。引入的主要创新,我们都喜欢的创新是 React 编译器!它承诺通过消除手动记忆优化的需要来永远简化前端开发。
在本指南中,您将了解 React Compiler 是什么、它是如何工作的、它引入了哪些好处以及如何准备您的应用程序。
React 19 带来了什么
React 19 于 2024 年 5 月 15 日至 16 日在 React Conf 2024 上发布,是期待已久的该框架的下一个版本。React 18 于 2022 年发布,从那时起,Web 技术有了很大的发展。现在是更新的时候了。
版本 19 不仅向前迈出了一步,而且有望永远改变开发人员在 React 中构建应用程序的方式。React 19 计划引入的一些最令人兴奋的功能是:
- 服务器组件:组件的服务器端渲染,以实现更快的页面加载和更好的 SEO。通过在将页面交付给用户之前在服务器上处理组件,React 19 可以加快网站加载时间、提高搜索引擎可见性和更流畅的数据管理。Next.js已经使用此功能。
- Actions:简化网页内数据和交互的管理。通过操作可以更轻松地通过表单更新页面信息,从而消除复杂性并简化用户体验。
- 优化资产加载:后台加载网站资产,实现更流畅的页面更改。React 19 可以在用户仍在浏览当前页面时开始在后台加载图像和其他文件,从而减少页面转换期间的等待时间。
- 文档元数据:借助新
<DocumentHead>
组件,简化了 SEO 管理。向页面添加标题和元标记将更加直观,无需重复编码即可改善搜索引擎优化。 - Web 组件:改进了与 Web 组件标准的兼容性,以实现更灵活和兼容的前端开发。
- 增强型挂钩:通过现有挂钩和新挂钩更好地控制组件的生命周期和状态。最终目标是简化编码过程,使 React 开发更加高效和愉快。
- React 编译器:将 React 代码自动转换为标准化、优化的 JavaScript 代码。它允许编译后的 React 代码在状态更改时自动仅呈现 UI 的正确部分,从而减少了对
useMemo
、useCallback
和memo
的需要。这意味着使用简化的代码库更快地实现 React 应用程序。
当然,所有这些功能都很棒,但最突出的是 React Compiler。这次升级有望永远改变 React 开发。现在让我们试着了解它背后的原因以及它将带来什么好处!
React 编译器:你需要知道的一切
深入研究 React 19 编译器工具,探索它是什么以及它是如何工作的。
React 的核心心智模型
要理解 React Compiler 背后的原因,你首先需要深入研究一些关键的 React 概念。 React 的核心是一个声明式和基于组件的心智模型。在前端开发中,声明式编程涉及描述 UI 所需的最终状态,而不指定通过 DOM 操作实现该状态的每个步骤。同时,基于组件的方法将UI元素分解为可重用、简洁、独立的构建块,促进模块化和易于维护。 为了有效地识别需要更新的特定 DOM 元素,React 采用了称为虚拟 DOM 的用户界面的内存表示。在应用程序状态发生变化的情况下,React 会将虚拟 DOM 与真实 DOM 进行比较,确定所需的最小更改集,并准确更新真实 DOM。 简而言之,心智模型是每当应用程序的状态发生变化时,React 就会重新渲染。但是,有时 React 可能过于被动,导致不必要的重新渲染,从而大大降低应用程序的速度。
重新渲染地狱:对编译器的需求
React 响应应用程序状态变化的敏捷性是一把双刃剑。一方面,由于其声明式方法,它简化了前端开发。另一方面,它可能导致 UI 中的组件过度重新呈现以响应状态更改 在处理 JavaScript 数据结构(如对象和数组)时,重新渲染问题尤为常见。问题在于,没有有效的计算方法来比较两个对象和数组,以查看它们在 JavaScript 中是否等效(具有相同的键和值) 请考虑以下方案。你有一个 React 组件,它在每次渲染时都会生成一个新的对象或数组,如下例所示:
尽管局部数组的内容在每次渲染时都是相同的,但 React 无法有效地知道这一点。因此,它可能会根据该数组中的值在组件的嵌套 DOM 元素中触发重新渲染,而不知道 UI 应保持相同。这种重新渲染机制可能会迅速失控,从而严重影响应用程序性能和用户体验。
为了优化重新渲染行为并避免这些问题,React 开发人员必须手动将记忆引入他们的组件中。在 React 中,记忆涉及根据输入参数缓存昂贵的计算或组件输出的结果。通过存储和重用这些结果,记忆有助于防止不必要的重新读取组件,从而提高 React 应用程序的整体效率和性能。
React 18 provides several memoization tools:
React 18 提供了几个记忆工具:
React.memo()
: 一个高阶函数,用于避免在组件的道具保持不变时重新渲染组件。useMemo()
: 一个 React 钩子,用于在重新渲染之间缓存计算结果,从而减少冗余计算。- [
useCallback()
]:来自 React 的钩子,用于在重新渲染之间缓存函数的定义,避免不必要的函数创建。
多亏了钩 useMemo()
子,您可以优化 <AlphabetList>
组件以避免不必要的重新渲染,如下所示:
React 提供的记忆工具当然很强大。同时,它们的引入只不过是明显背离了 React 核心心智模型背后的声明哲学。这是因为负担落在了开发人员身上,他们不仅要描述 UI 的最终状态,还要显式管理渲染优化。手动记忆还会带来代码复杂性和维护难题。
解决方案是什么?一种高级编译器,能够将 React 代码转换为优化的 JavaScript 代码,以便仅在状态值发生重大变化时自动重新渲染组件。
什么是 React 编译器?
React Compiler,也称为 React Forget,是 React 的优化编译器。它现在为 Instagram 的 Web 门户网站提供生产支持,并将在其第一个开源版本之前部署在其他 Meta 应用程序上。
编译器的最初目标是通过自动生成等价的 、 memo
useMemo
和 useCallback
调用来强制执行 React 的核心编程模型,以最大限度地降低重新渲染的成本。该项目从一开始就有了很大的发展,从“自动记忆编译器”变成了“自动反应编译器”。
React Forget 的真正目标是确保 React 应用程序在默认情况下具有适量的反应性。换言之,仅当状态值发生有意义更改时,应用才应重新呈现。目前,当对象身份发生变化时,React 会重新渲染组件。使用 React Forget,它只会在对象的语义值发生变化时重新渲染,但不会产生深度比较的运行时成本。
从实现的角度来看,React Compiler 应用了自动记忆。然而,它背后的团队认为反应性框架是一种更完整的方法来理解它的作用。如果你想了解更多关于 React 编译器的内部工作原理和逻辑,请阅读 React Labs 部分。
在下面的视频中查看 React Forget 的实际应用:www.youtube.com/watch?v=qOQ…
虽然 JavaScript 是一种众所周知的难以优化的语言,因为它的动态性质和松散的规则,但 React Compiler 可以通过对 JavaScript 规则和“React 规则”进行建模来安全地编译代码。这些规则限制了开发人员可以执行的操作,有助于为编译器执行优化开辟一个安全空间。
React的规则
React 附带了一组旨在支持高质量 Web 应用程序的规则。开发人员应该遵循这些规则,这些规则也代表了 React Compiler 所基于的内容。 React 的一些最重要的规则是:
- 组件必须是幂等的:React 组件应该始终在给定同一组输入(包括 props、state 和 context)的情况下产生相同的输出。
- 副作用必须在渲染之外运行:在组件的渲染过程中,不应执行副作用,例如数据提取、订阅或手动更改 DOM。相反,它们应该在生命周期钩子中执行,例如
useEffect
. - props和state是不可变的:React 组件中的道具和状态应该被视为不可变的,这意味着它们不应该被直接修改。直接更改道具或状态可能会导致错误和不可预测的行为。
- 值在传递给 JSX 后是不可变的:呈现后不要改变 JSX 中使用的值。在创建 JSX 之前,应执行任何必要的更改,以确保呈现的输出保持一致。
- 永远不要直接调用组件函数:React 组件应该只在 JSX 中使用,而不是作为常规函数直接调用。
- 永远不要将钩子作为常规值传递:React 钩子,例如
useState
useEffect
和 ,应该只在功能组件内部调用。将它们用作常规值可能会导致意外行为并违反钩子规则。 - 只在顶层调用钩子:在任何条件语句或循环之前,应该始终在功能组件的顶层调用 React 钩子。这可确保在每次渲染时以相同的顺序调用钩子,并保持其预期行为。
- 仅从 React 函数调用钩子:钩子只能从 React 函数组件或自定义钩子中调用。从常规 JavaScript 函数调用钩子可能会导致错误并违反钩子规则。
启用严格模式并配置 React 的 ESLint插件,以确保您的 React 应用程序遵循这些规则。
好处和希望
React Compiler 引入的主要好处是:
-
不再有令人头疼的死记硬背:: 开发人员不再需要在代码中手动实现和管理死记策略。这降低了复杂性和出错的可能性,简化了开发过程。
-
更好的开发人员体验:: 更好的开发人员体验:开发人员可以更专注于构建功能,而不是性能优化,从而提高生产力和满意度。他们最终将能够完全接受 React 声明式方法。
-
更快的 React 应用程序:: 仅在必要时渲染组件,最大限度地减少不必要的计算和开销。这导致了更快、响应更灵敏的用户界面,提高了整体性能和用户体验。
这些都是有希望的变化,但我们还没有看到这个新工具将对代码开发产生什么影响。为了确保编译器完成其工作,您的代码必须遵循 React 的规则。这就是为什么官方团队建议采用 ESLint 和类似工具来准备 React Compiler 的应用程序。
React Compiler:前端革命?
很难说 React Compiler 是否足以在前端开发领域引发一场真正的革命。可以肯定的是,它拥有显着改变未来 React 应用程序开发的所有凭据。通过引入自动记忆,该编译器可以自动加速 React 应用程序并改善开发人员体验。这些只是这个充满希望的雄心勃勃的项目为标签带来的一些好处。
React Conf 2024 即将到来,我们期待看到这个雄心勃勃的项目将在前端世界取得哪些突破!