全面解析React Compiler Beta 版:突破创新,提升开发效率!

目录
文章目录隐藏
  1. 什么是 React Compiler?
  2. 安装 React Compiler
  3. 在不同项目中的应用
  4. 问题排查
  5. React Compiler 在 Meta 的应用
  6. 未来计划
  7. 开放 React Compiler 工作组

在今年 5 月份的 React Conf 2024 上,React 团队宣布推出 React Compiler 的实验版本。

全面解析 React Compiler Beta 版:突破创新,提升开发效率!

经过几个月的迭代和优化,React 团队修复了 React 社区报告的大量 Bug,收到了几个高质量的 Bug 修复和对编译器的 PR ,使编译器更能适应各种 JavaScript 模式,并继续在 Meta 内部更广泛地落地编译器。

React Compiler Beta 版

React 官方近日发布了 React Compiler 的 Beta 版,并且宣布将于不久后发布 RC 版本,这也标志着  React Compiler 即将进入稳定阶段了。现在可以通过可选的 React-compiler-runtime 包正式支持 React 17+ 上的应用程序的 React Compiler

什么是 React Compiler?

React Compiler 是一个全新的编译器,旨在编译时自动优化我们的 React 应用。它可以与原生 JavaScript 一起工作,并且理解 React 的规则,因此使用它时不需要重写任何代码。

自动优化

React Compiler 可以帮我们自动完成代码的记忆化(memoization),这意味着它会自动记住哪些组件或钩子(hooks)需要重新渲染,从而提高性能。当检测到违反 React 规则的情况时,它会自动跳过这些有问题的部分,但继续安全地编译其它代码。

例如,以下代码展示了 React Compiler 如何处理组件的重新渲染,在以下示例中,每当 friends 的状态发生变化时,都会重新渲染 <MessageButton>

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 Compiler 确定即使 friends 发生变化,<FriendListCard /> 的返回值也可以复用,并且可以避免重新创建此 JSX 并避免在计数变化时重新渲染 <MessageButton>

复杂计算优化

React Compiler 还能自动记忆化一些复杂计算。例如:

// 此函数并不会被 React Compiler 记忆化,因为它不是组件或钩子
function expensivelyProcessAReallyLargeArrayOfObjects() { /* ... */ }

// 这个函数会被 React Compiler 记忆化
function TableContainer({ items }) {
  const data = expensivelyProcessAReallyLargeArrayOfObjects(items);
  // ...
}

不过,如果 expensivelyProcessAReallyLargeArrayOfObjects 是一个真正耗时的函数,你可能需要考虑在 React 外部实现它的记忆化。

安装 React Compiler

要试用 React Compiler,可以在 React 17+ 的应用和库中安装 Beta 版:

npm install -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta

或者使用 Yarn:

yarn add -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta

使用 Babel

安装 Babel 插件:

npm install babel-plugin-react-compiler@beta

然后在 Babel 配置中添加插件,确保编译器先运行:

const ReactCompilerConfig = { /* ... */ };

module.exports = function () {
  return {
    plugins: [
      ['babel-plugin-react-compiler', ReactCompilerConfig], // 必须先运行!
    ],
  };
};

其他工具链

在不同的工具链中,我们也可以随着文档进行配置,如 Vite、Next.js、Remix、Webpack、Expo 等。

如果你使用 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.config.js 添加 experimental.reactCompiler 选项 :

import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  experimental: {
    reactCompiler: true,
  },
}
 
export default nextConfig

Remix:

// 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 TypeScript
        plugins: [
          ["babel-plugin-react-compiler", ReactCompilerConfig],
        ],
      },
    }),
  ],
});

Webpack/Rspack:

// webpack.config.js / rspack.config.js

// You can leverage your IDE's Intellisense (autocompletion, type check, etc.) with the helper function `defineReactCompilerLoaderOption`:
const { defineReactCompilerLoaderOption, reactCompilerLoader } = require('react-compiler-webpack');

module.exports = {
  module: {
    rules: [
      rules: [
        {
          test: /\.[mc]?[jt]sx$/i,
          exclude: /node_modules/,
          use: [
            // babel-loader, swc-loader, esbuild-loader, or anything you like to transpile JSX should go here.
            // If you are using rspack, the rspack's buiilt-in react transformation is sufficient.
            // { loader: 'swc-loader' },
            // Now add forgetti-loader
            {
              loader: reactCompilerLoader,
              options: defineReactCompilerLoaderOption({
                // React Compiler options goes here
              })
            }
          ]
        }
      ]
    ]
  }
};

在不同项目中的应用

现有项目

对于现有项目,可以先在小目录中运行编译器,逐步扩展覆盖范围:

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

新项目

对于新项目,可以在整个代码库上启用编译器,这是默认行为。

在库中的使用

最初发布的 React Compiler 专注于在应用程序中使用编译器,已经收到了大量的反馈,并且对编译器进行了显著改进。现在,React 团队准备广泛接受社区反馈,并邀请库的作者尝试编译器,以提高性能和开发者体验。

由于 React Compiler 需要在任何代码转换之前运行,因此无法通过应用程序的构建流程编译所使用的库。我们的建议是库的维护者独立编译测试他们的库,并将编译后的代码提交到 npm 上。因为代码是预先编译的,库的用户无需启用编译器,就可以享受到自动记忆化带来的性能提升。

向后兼容性

尽管理论上 React Compiler 生成的代码依赖于 React 19 版本,但官方已经扩展支持 React 17React 18。在 React 19 之前的版本上使用编译器,需要安装 react-compiler-runtime 包:

npm install react-compiler-runtime@beta

并在 Babel 配置中添加相应的 target

const ReactCompilerConfig = {
  target: '18' // 支持 '17' | '18' | '19'
};

module.exports = function () {
  return {
    plugins: [
      ['babel-plugin-react-compiler', ReactCompilerConfig],
    ],
  };
};

问题排查

当开发遇到问题时,我们可以通过 React Compiler Playground 创建一个最小的复现例子,并在 facebook/react 提交 Issues

React Compiler Playground

同时,React CompilerESLint 插件可帮助开发人员主动识别和纠正 React 规则违规。我们强烈建议大家立即使用 linterlinter 不需要我们安装编译器,因此即使我们尚未准备好试用编译器,也可以独立使用它。

npm install -D eslint-plugin-react-compiler@beta

然后将其添加到你的 ESLint 配置中:

import reactCompiler from 'eslint-plugin-react-compiler'

export default [
  {
    plugins: {
      'react-compiler': reactCompiler,
    },
    rules: {
      'react-compiler/react-compiler': 'error',
    },
  },
];

React Compiler 在 Meta 的应用

在 React Conf 大会上,React 团队分享了在 Quest StoreInstagram 上成功部署 React Compiler 的经验。自那以后,React 团队又在 Meta 的多个主要 Web 应用上部署了 React Compiler,包括 FacebookThreads。这意味着,如果我们最近使用了这些应用程序,使用体验可能已经由 React Compiler 提供支持。够在一个包含超过 100,000 个 React 组件的单一代码仓库中,几乎不需要代码修改,就将这些应用程序迁移到了 React Compiler 上。

几乎在所有这些应用程序中都看到了显著的性能提升。尤其是在已经被 Meta 工程师和 React 专家多年来精心调优和优化的应用程序中,即便是几个百分点的提升也已是巨大的胜利。

另外, React Compiler 也能够提升开发者的生产力。为了衡量这一点,React 团队与 Meta 数据科学团队合作,进行了手动记忆化对生产力影响的深入统计分析。在 Meta 推出编译器之前,我们发现只有大约 8% 的 React 合并请求使用了手动记忆化,而这些合并请求的撰写时间平均长 31-46%。这证实了我们普遍的直觉:手动记忆化带来了认知负担,我们期望 React Compiler 将带来更高效的代码撰写和审核体验。值得注意的是,React Compiler 默认确保所有代码都进行记忆化,而不仅仅是(案例中)8% 的显式记忆化代码。

未来计划

以下是目前的 Roadmap,可能未来也会有所变动。

React 团队的计划是在 Beta 版本发布后不久,发布编译器的候选版本(Release Candidate),当大多数遵循 React 规则的应用和库都能很好地与编译器配合使用后再发布。在社区提供最后反馈的一段时间之后,发布编译器的稳定版本。稳定版本的发布将标志着 React 开始新基础的起点,所有应用程序和库都将被强烈推荐使用编译器及其 ESLint 插件。

  • ✅ 实验版本:于 2024 年 React Conf 大会上发布,主要面向早期采纳者提供反馈。
  • ✅ 公共 Beta:现已发布,面向更广泛社区提供反馈。
  • 🚧 候选版本:React Compiler 能无问题地支持大多数遵循规则的应用和库。
  • 🚧 全面可用(General Availability):在社区反馈期过后发布。

这些版本还包括编译器的 ESLint 插件,该插件通过静态分析提供诊断信息。React 团队计划将现有的 eslint-plugin-react-hooks 插件与编译器的 ESLint 插件合并,这样只需要安装一个插件。

在稳定版本之后,React 团队计划添加更多的编译器优化和改进。这包括自动记忆化的持续改进和全新的优化,而且几乎不需要变动产品代码。每次编译器的新版本升级都将十分简便,并且会持续提升性能,增强对多样化 JavaScript 和 React 模式的处理。

在整个过程中,React 团队还计划为 React 制作一个 IDE 扩展。这仍然处于非常早期的研究阶段。

开放 React Compiler 工作组

在此前 React Conf 大会上宣布了邀请制的 React Compiler 工作组,旨在为编译器的实验版本提供反馈、解答问题并进行合作。

开放 React Compiler 工作组

今天,随着 React Compiler 的 Beta 版本发布,React 团队决定将工作组的成员资格向所有人开放。React Compiler 工作组的目标是为现有应用和库逐步顺利地引入 React Compiler 做准备。

文章来源:code 秘密花园

「点点赞赏,手留余香」

1

给作者打赏,鼓励TA抓紧创作!

微信微信 支付宝支付宝

还没有人赞赏,快来当第一个赞赏的人吧!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系maynote@foxmail.com处理
码云笔记 » 全面解析React Compiler Beta 版:突破创新,提升开发效率!

发表回复