React 编译器

在这里插入图片描述

🤖 作者简介:水煮白菜王,一位前端劝退师 👻
👀 文章专栏: 前端专栏 ,记录一下平时在博客写作中,总结出的一些开发技巧和知识归纳总结✍。
感谢支持💕💕💕
本文内容参考自 React文档 - React Compiler 内容进行记录和整理✍

目录

  • React 编译器
    • 编译器是做什么的?
      • 注意
      • 深入探究
      • React Compiler 添加了什么样的记忆?
        • 优化重新渲染
        • 昂贵的计算也会被记忆化
    • 开始使用
      • 安装 eslint-plugin-react-hooks
      • 将编译器推出到您的代码库
      • 现有项目
      • 新项目
      • 在 React 17 或 18 中使用 React 编译器
      • 在库上使用编译器
    • 用法
      • Babel
      • Vite
      • Next.js :
      • Remix
      • Webpack
    • 故障 排除
      • 编译器假定什么?
      • 如何知道我的组件已优化?
      • 编译后某些内容无法正常工作
  • 如果你觉得这篇文章对你有帮助,请点赞 👍、收藏 👏 并关注我!👀

React 编译器

本文将为你介绍 React Compiler 以及如何成功试用它

本文您进入React 编译器将学习
编译器入门
安装编译器和 ESLint 插件
进行故障排除

注意
React Compiler 是目前在 RC 中的一个新编译器,React已经开源了它以从社区获得反馈。现在建议大家试用编译器并提供反馈。
最新的 RC 版本可以通过标签找到,每日实验版本可以使用 .@rc@experimental

React Compiler 是React开源的一个新的编译器,用于从社区获取反馈。它是一个仅限构建时的工具,可自动优化您的 React 应用程序。它与纯 JavaScript 一起工作,并且理解 React 的规则,因此你不需要重写任何代码来使用它。

eslint-plugin-react-hooks 还包括一个 ESLint 规则,该规则直接在编辑器中显示来自编译器的分析。React强烈建议大家立即使用 Linter。Linter 不需要您安装编译器,因此即使您还没有准备好试用编译器,也可以使用它。

该编译器目前作为 发布,可以在 React 17+ 应用程序和库上试用。要安装 RC:rc
npm

npm install -D babel-plugin-react-compiler@rc eslint-plugin-react-hooks@^6.0.0-rc.1

yarn

yarn add -D babel-plugin-react-compiler@rc eslint-plugin-react-hooks@^6.0.0-rc.1

编译器是做什么的?

为了优化应用程序,React Compiler 会自动记住你的代码。您现在可能熟悉通过 API 进行记忆化,例如 、 和 。通过这些 API,你可以告诉 React 如果它们的输入没有改变,你的应用程序的某些部分就不需要重新计算,从而减少了更新的工作。虽然功能强大,但很容易忘记应用记忆化或错误地应用它们。这可能会导致更新效率低下,因为 React 必须检查没有任何有意义的更改的 UI 部分。useMemouseCallbackReact.memo

编译器利用其 JavaScript 和 React 规则的知识来自动记住组件和 hook 中的值或值组。如果它检测到规则的破坏,它将自动跳过这些组件或 hook,并继续安全地编译其他代码。

注意

React Compiler 可以静态检测何时违反 React 规则,并安全地选择退出仅优化受影响的组件或钩子。编译器没有必要优化 100% 的代码库

如果您的代码库已经很好地记住了,您可能不希望看到编译器的性能有重大改进。但是,在实践中,记住导致性能问题的正确依赖项是很棘手的。

深入探究

React Compiler 添加了什么样的记忆?

React Compiler 的初始版本主要专注于提高更新性能(重新渲染现有组件),因此它专注于以下两个用例:
1.跳过组件的级联重新渲染

  • 重新渲染会导致其组件树中的许多组件重新渲染,即使只有更改<Parent /><Parent />

2.跳过 React 外部的昂贵计算

  • 例如,在需要该数据的组件或 hook 内部调用expensivelyProcessAReallyLargeArrayOfObjects()
优化重新渲染

React 允许你将你的 UI 表示为当前状态的函数(更具体地说:它们的 props、state 和 context)。在当前的实现中,当组件的状态发生变化时,React 将重新渲染该组件及其所有子组件 — 除非你使用 、 或 应用了某种形式的手动记忆。例如,在下面的示例中,每当 的状态发生变化时,都会重新渲染:useMemo() useCallback() React.memo() <MessageButton><FriendList>

function FriendList({ friends }) {const onlineCount = useFriendOnlineCount();
if (friends.length === 0) {return <NoFriends />;}return (<div><span>{onlineCount} online</span>{friends.map((friend) => (<FriendListCard key={friend.id} friend={friend} />))}<MessageButton /></div>);
}

React Compiler 会自动应用等同于手动记忆化的作,确保只有应用程序的相关部分会随着状态变化而重新渲染,这有时被称为“细粒度响应性”。在上面的例子中,React 编译器确定 of 的返回值即使作为更改也可以重用,并且可以避免重新创建这个 JSX,并避免在 count 发生变化时重新渲染。<FriendListCard />friends<MessageButton>

昂贵的计算也会被记忆化

编译器还可以自动 memoize 渲染期间使用的昂贵计算:

// **Not** memoized by React Compiler, since this is not a component or hook
function expensivelyProcessAReallyLargeArrayOfObjects() { /* ... */ }// Memoized by React Compiler since this is a component
function TableContainer({ items }) {// This function call would be memoized:const data = expensivelyProcessAReallyLargeArrayOfObjects(items);// ...
}

但是,如果确实是一个昂贵的函数,你可能需要考虑在 React 之外实现自己的记忆化,因为:expensivelyProcessAReallyLargeArrayOfObjects

  • React 编译器只记住 React 组件和钩子,而不是每个函数
  • React Compiler 的记忆不会在多个组件或 hook 之间共享

因此,如果用于许多不同的组件,即使传递了完全相同的项目,也会重复运行昂贵的计算。建议先进行分析,看看它是否真的那么昂贵,然后再使代码变得更复杂。expensivelyProcessAReallyLargeArrayOfObjects

开始使用

安装 eslint-plugin-react-hooks

React Compiler 还为 ESLint 插件提供支持。你可以通过安装 eslint-plugin-react-hooks@^6.0.0-rc.1 来试用。

npm install -D eslint-plugin-react-hooks@^6.0.0-rc.1

ESLint 插件将在编辑器中显示任何违反 React 规则的行为。当它这样做时,这意味着编译器跳过了优化该组件或 hook。这是完全可以的,编译器可以恢复并继续优化代码库中的其他组件。

你不必立即修复所有 ESLint 冲突。您可以按照自己的节奏解决它们,以增加要优化的组件和 hook 的数量,但不需要在使用编译器之前修复所有问题。

将编译器推出到您的代码库

现有项目

编译器旨在编译遵循 React 规则的功能组件和 hook。它还可以通过救助 (跳过) 这些组件或 hook 来处理违反这些规则的代码。然而,由于 JavaScript 的灵活性,编译器无法捕获所有可能的违规,并且可能会以漏报进行编译:也就是说,编译器可能会意外编译一个违反 React 规则的组件/钩子,这可能导致未定义的行为。

因此,要在现有项目中成功采用编译器,建议先在产品代码中的小目录上运行它。您可以通过将编译器配置为仅在一组特定的目录上运行来执行此作:

const ReactCompilerConfig = {sources: (filename) => {return filename.indexOf('src/path/to/dir') !== -1;},
};

您对推出编译器更有信心时,您也可以将覆盖范围扩展到其他目录,并慢慢将其扩展到整个应用程序。

新项目

如果要启动新项目,则可以在整个代码库上启用编译器,这是默认行为。

在 React 17 或 18 中使用 React 编译器

React 编译器与 React 19 RC 配合得最好。如果您无法升级,您可以安装额外的软件包,这将允许编译后的代码在 19 之前的版本上运行。但是,请注意,支持的最低版本为 17。react-compiler-runtime

npm install react-compiler-runtime@rc

你还应该将 correct 添加到你的编译器配置中,其中 是你目标的 React 的主要版本:target target

// babel.config.js
const ReactCompilerConfig = {target: '18' // '17' | '18' | '19'
};module.exports = function () {return {plugins: [['babel-plugin-react-compiler', ReactCompilerConfig],],};
}

在库上使用编译器

React Compiler 也可以用于编译库。因为 React Compiler 需要在任何代码转换之前在原始源代码上运行,所以应用程序的构建管道不可能编译它们使用的库。因此,建议库维护者使用编译器独立编译和测试他们的库,并将编译后的代码发送到 npm。

由于您的代码是预编译的,因此您的库的用户不需要启用编译器即可从应用于您的库的自动记忆化中受益。如果你的库面向尚未在 React 19 上运行的应用程序,请指定最小目标并将 react-compiler-runtime 添加为直接依赖项。运行时包将根据应用程序的版本使用正确的 API 实现,并在必要时对缺少的 API 进行 polyfill 填充。

库代码通常需要更复杂的模式和转义舱口的使用。因此,建议您确保进行足够的测试,以便识别在库上使用编译器可能出现的任何问题。如果你发现任何问题,你可以随时使用 'use no memo' 指令选择退出特定的组件或 hook。

与 app 类似,你不需要完全编译 100% 的组件或 hook 就能看到你的库里的好处。一个好的起点可能是确定库中对性能最敏感的部分,并确保它们不会违反 React 规则,你可以用它来识别。eslint-plugin-react-compiler

用法

Babel

npm install babel-plugin-react-compiler@rc

编译器包括一个 Babel 插件,您可以在构建管道中使用它来运行编译器。

安装后,将其添加到你的 Babel 配置中。请注意,编译器首先在管道中运行至关重要:

// babel.config.js
const ReactCompilerConfig = { /* ... */ };module.exports = function () {return {plugins: [['babel-plugin-react-compiler', ReactCompilerConfig], // must run first!// ...],};
};

babel-plugin-react-compiler应该在其他 Babel 插件之前先运行,因为编译器需要输入源信息进行声音分析。

Vite

如果你使用 Vite,你可以将插件添加到 vite-plugin-react 中:

// vite.config.js
const ReactCompilerConfig = { /* ... */ };export default defineConfig(() => {return {plugins: [react({babel: {plugins: [["babel-plugin-react-compiler", ReactCompilerConfig],],},}),],// ...};
});

Next.js :

参阅 Next.js 文档

Remix

安装 ,并向其添加编译器的 Babel 插件:vite-plugin-babel

npm install vite-plugin-babel
// vite.config.js
import babel from "vite-plugin-babel";const ReactCompilerConfig = { /* ... */ };export default defineConfig({plugins: [remix({ /* ... */}),babel({filter: /\.[jt]sx?$/,babelConfig: {presets: ["@babel/preset-typescript"], // if you use TypeScriptplugins: [["babel-plugin-react-compiler", ReactCompilerConfig],],},}),],
});

Webpack

社区 webpack loader已提供。

故障 排除

要报告问题,请首先在 React Compiler Playground 上创建一个最小重现,并将其包含在你的错误报告中。您可以在 facebook/react 存储库中打开问题。

你也可以通过申请成为成员在 React 编译器工作组中提供反馈。有关 加入的更多详细信息,请参阅 README。

编译器假定什么?

React 编译器假定你的代码:

  1. 是有效的语义 JavaScript。
  2. 测试在访问可空/可选值和属性之前是否定义它们(例如,如果使用 TypeScript,则通过启用 strictNullChecks ),即或使用 optional-chaining 。if (object.nullableProperty) { object.nullableProperty.foo }object.nullableProperty?.foo
  3. React 的规则。

React Compiler 可以静态验证 React 的许多规则,并在检测到错误时安全地跳过编译。要查看错误,建议同时安装 。eslint-plugin-react-compiler。

如何知道我的组件已优化?

React DevTools (v5.0+) 和 React Native DevTools内置了对 React 编译器的支持,并将在编译器优化的组件旁边显示 “Memo ✨ ” 徽章。

编译后某些内容无法正常工作

如果你安装了 eslint-plugin-react-compiler,编译器会在你的编辑器中显示任何违反 React 规则的行为。当它这样做时,这意味着编译器跳过了优化该组件或 hook。这是完全可以的,编译器可以恢复并继续优化代码库中的其他组件。你不必立即修复所有 ESLint 冲突。您可以按照自己的节奏解决这些问题,以增加要优化的组件和 hook 的数量。

然而,由于 JavaScript 的灵活和动态特性,不可能全面检测所有情况。在这些情况下,可能会出现错误和未定义的行为,例如无限循环。

如果你的 app 在编译后无法正常工作,并且你没有看到任何 ESLint 错误,则编译器可能错误地编译了你的代码。为了确认这一点,请尝试通过 “use no memo” 指令主动选择退出您认为可能相关的任何组件或 hook,从而使问题消失。

function SuspiciousComponent() {"use no memo"; // opts out this component from being compiled by React Compiler// ...
}

注意
“use no memo”
"use no memo"是一个临时的转义舱口,允许你选择退出 React 编译器编译的组件和钩子。这个指令并不意味着像 use client 那样长寿。

除非绝对必要,否则不建议使用该指令。一旦你选择退出一个组件或 hook,它就会永远选择退出,直到该指令被删除。这意味着,即使您修复了代码,编译器仍将跳过编译它,除非您删除该指令。
#如果你觉得这篇文章对你有帮助,请点赞 👍、收藏 👏 并关注我!👀

当您使错误消失时,请确认删除 opt out 指令会使问题再次出现。然后使用 React Compiler Playground 与React共享错误报告(您可以尝试将其简化为一个小的复制,或者如果它是开源代码,您也可以直接粘贴整个源代码),以便官方识别并帮助解决问题。

如果你觉得这篇文章对你有帮助,请点赞 👍、收藏 👏 并关注我!👀

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/82396.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac下通过anaconda安装Python

本次分享mac下通过anaconda安装Python、Jupyter Notebook、R。 anaconda安装 点击&#x1f449;https://www.anaconda.com/download&#xff0c; 点击Mac系统安装包&#xff0c; 选择Mac芯片&#xff1a;苹果芯片 or intel芯片&#xff0c; 选择苹果芯片图形界面安装&#x…

Pandas 技术解析:从数据结构到应用场景的深度探索

序 我最早用Python做大数据项目时&#xff0c;接触最早的就是Pandas了。觉得对于IT技术人员而言&#xff0c;它是可以属于多场景的存在&#xff0c;因为它的本身就是数据驱动的技术生态中&#xff0c;对于软件工程师而言&#xff0c;它是快速构建数据处理管道的基石&#xff1…

【循环神经网络RNN第一期】循环神经网络RNN原理概述

目录 &#x1f9e0; 什么是循环神经网络&#xff08;RNN&#xff09;&#xff1f;&#x1f501; RNN 的结构图&#x1f504; RNN 的“记忆”与问题RNN梯度推导 &#x1f9ec; LSTM&#xff1a;解决长期依赖问题&#x1f9f1; LSTM 的核心结构LSTM总结 参考 人类在思考的时候&am…

代码随想录算法训练营 Day60 图论Ⅹ Bellmen_ford 系列算法

图论 题目 94. 城市间货物运输 I Bellmen_ford 队列优化算法 SPFA 大家可以发现 Bellman_ford 算法每次松弛 都是对所有边进行松弛。 但真正有效的松弛&#xff0c;是基于已经计算过的节点在做的松弛。 本图中&#xff0c;对所有边进行松弛&#xff0c;真正有效的松弛&#…

Juce实现Table自定义

Juce实现Table自定义 一.总体展示概及概述 在项目中Juce中TableList往往无法满足用户需求&#xff0c;头部和背景及背景颜色设置以及在Cell中添加自定义按钮&#xff0c;所以需要自己实现自定义TabelList&#xff0c;该示例是展示实现自定义TableList&#xff0c;实现自定义标…

C++ set数据插入、set数据查找、set数据删除、set数据统计、set排序规则、代码练习1、2

set数据插入&#xff0c;代码见下 #include<iostream> #include<set> #include<vector>using namespace std;void printSet(const set<int>& s) {for (set<int>::const_iterator it s.begin(); it ! s.end(); it) {cout << *it <…

深度学习赋能图像识别:技术、应用与展望

论文&#xff1a; 一、引言​ 1.1 研究背景与意义​ 在当今数字化时代&#xff0c;图像作为信息的重要载体&#xff0c;广泛存在于各个领域。图像识别技术旨在让计算机理解和识别图像内容&#xff0c;将图像中的对象、场景、行为等信息转化为计算机能够处理的符号或数据 &am…

深入解析C++引用:从别名机制到函数特性实践

1.C引用 1.1引用的概念和定义 引用不是新定义⼀个变量&#xff0c;而是给已存在变量取了⼀个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同⼀块内存空间。比如四大名著中林冲&#xff0c;他有一个外号叫豹子头&#xff0c;类比到C里就…

【从0-1的HTML】第1篇:HTML简介

1 HTML简介 HTML是用来描述网页的一种语言,是超文本标记语言的缩写(Hyper Text Markup Language),不属于编程语言的范畴&#xff0c;属于一种标记语言。 标记语言使用一套标记标签(Markup tag)&#xff0c;又称为标签,HTML就是使用标记标签来描述网页。 1.2 HTML标签 1、HTM…

vue+cesium示例:地形开挖(附源码下载)

基于cesium和vue绘制多边形实现地形开挖效果&#xff0c;适合学习Cesium与前端框架结合开发3D可视化项目。 demo源码运行环境以及配置 运行环境&#xff1a;依赖Node安装环境&#xff0c;demo本地Node版本:推荐v18。 运行工具&#xff1a;vscode或者其他工具。 配置方式&#x…

qwen大模型在进行词嵌入向量时,针对的词表中的唯一数字还是其他的?

qwen大模型在进行词嵌入向量时,针对的词表中的唯一数字还是其他的? Qwen大模型进行词嵌入向量时,针对的是词表中每个 Token 对应的唯一数字(Token ID) ,核心逻辑结合词表构建、嵌入过程展开 一、Qwen 词表与 Token ID Qwen 用 BPE 分词器(基于 tiktoken,以 cl100k 为…

动态规划-1143.最长公共子序列-力扣(LeetCode)

一、题目解析 对于给定了两个字符串中&#xff0c;需要找到最长的公共子序列&#xff0c;也就是两个字符串所共同拥有的子序列。 二、算法原理 1、状态表示 dp[i][j]&#xff1a;表示s1的[0,i]和s2的[0,j]区间内所有子序列&#xff0c;最长子序列的长度 2、状态转移方程 根…

互联网c++开发岗位偏少,测开怎么样?

通过这标题&#xff0c;不难看出问这个问题的&#xff0c;就是没工作过的。如果工作过&#xff0c;那就是不断往深的钻研&#xff0c;路越走越窄&#xff0c;找工作一般就是找原来方向的。没工作过的&#xff0c;那一般就是学生。 学生找什么方向的工作比较好&#xff1f; 学生…

推荐算法八股

跑路了&#xff0c;暑期0offer&#xff0c;华为主管面挂了&#xff0c;真幽默&#xff0c;性格测评就挂了居然给我一路放到主管面&#xff0c;科大迅飞太嚣张&#xff0c;直接跟人说后面要面华为&#xff0c;元戎启行&#xff0c;学了C后python完全忘了怎么写&#xff0c;挺尴尬…

Spring Boot微服务架构(九):设计哲学是什么?

一、Spring Boot设计哲学是什么&#xff1f; Spring Boot 的设计哲学可以概括为 ​​“约定优于配置”​​ 和 ​​“开箱即用”​​&#xff0c;其核心目标是​​极大地简化基于 Spring 框架的生产级应用的初始搭建和开发过程​​&#xff0c;让开发者能够快速启动并运行项目…

前端导入Excel表格

前端如何在 Vue 3 中导入 Excel 文件&#xff08;.xls 和 .xlsx&#xff09;&#xff1f; 在日常开发中&#xff0c;我们经常需要处理 Excel 文件&#xff0c;比如导入数据表格、分析数据等。文章将在 Vue 3 中实现导入 .xls 和 .xlsx 格式的文件&#xff0c;并解析其中的数据…

C++和C#界面开发方式的全面对比

文章目录 C界面开发方式1. **MFC&#xff08;Microsoft Foundation Classes&#xff09;**2. **Qt**3. **WTL&#xff08;Windows Template Library&#xff09;**4. **wxWidgets**5. **DirectUI** C#界面开发方式1. **WPF&#xff08;Windows Presentation Foundation&#xf…

刷leetcode hot100返航必胜版--链表6/3

链表初始知识 链表种类&#xff1a;单链表&#xff0c;双链表&#xff0c;循环链表 链表初始化 struct ListNode{ int val; ListNode* next; ListNode(int x): val&#xff08;x&#xff09;,next(nullptr) {} }; //初始化 ListNode* head new ListNode(5); 删除节点、添加…

软考 系统架构设计师系列知识点之杂项集萃(78)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;77&#xff09; 第139题 以下关于软件测试工具的叙述&#xff0c;错误的是&#xff08;&#xff09;。 A. 静态测试工具可用于对软件需求、结构设计、详细设计和代码进行评审、走查和审查 B. 静…

【Unity】云渲染

1 前言 最近在搞Unity云渲染的东西&#xff0c;所以研究了下官方提供的云渲染方案Unity Renderstreaming。注&#xff1a;本文使用的Unity渲染管线是URP。 2 文档 本文也只是介绍基本的使用方法&#xff0c;更详细内容参阅官方文档。官方文档&#xff1a;Unity Renderstreamin…