feat(react): add support for React Compiler in @nx/react/babel (#26826)

This PR adds a check in `@nx/react/babel` preset to enable React
Compiler when `babel-plugin-react-compiler` is installed.

This affects:

- React apps using Webpack + Babel
- React libs using Rollup + Babel
- React Native apps using Webpack + Babel

If SWC is used, there is no way to use React Compiler currently.

Also adds a [new
recipe](https://nx-dev-git-feat-react-compiler-nrwl.vercel.app/recipes/react/react-compiler)
showing how to enable the compiler using `@nx/react/babel`.

## Current Behavior
<!-- This is the behavior we have today -->

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
This commit is contained in:
Jack Hsu 2024-07-04 16:18:34 -04:00 committed by GitHub
parent 7caf9017f0
commit 653cad2492
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 137 additions and 5 deletions

View File

@ -1259,6 +1259,14 @@
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
},
{
"name": "React Compiler with Nx",
"path": "/recipes/react/react-compiler",
"id": "react-compiler",
"isExternal": false,
"children": [],
"disableCollapsible": false
} }
], ],
"disableCollapsible": false "disableCollapsible": false
@ -2361,6 +2369,14 @@
"isExternal": false, "isExternal": false,
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
},
{
"name": "React Compiler with Nx",
"path": "/recipes/react/react-compiler",
"id": "react-compiler",
"isExternal": false,
"children": [],
"disableCollapsible": false
} }
], ],
"disableCollapsible": false "disableCollapsible": false
@ -2421,6 +2437,14 @@
"children": [], "children": [],
"disableCollapsible": false "disableCollapsible": false
}, },
{
"name": "React Compiler with Nx",
"path": "/recipes/react/react-compiler",
"id": "react-compiler",
"isExternal": false,
"children": [],
"disableCollapsible": false
},
{ {
"name": "Angular", "name": "Angular",
"path": "/recipes/angular", "path": "/recipes/angular",

View File

@ -1720,6 +1720,17 @@
"isExternal": false, "isExternal": false,
"path": "/recipes/react/deploy-nextjs-to-vercel", "path": "/recipes/react/deploy-nextjs-to-vercel",
"tags": [] "tags": []
},
{
"id": "react-compiler",
"name": "React Compiler with Nx",
"description": "",
"mediaImage": "",
"file": "shared/guides/react-compiler",
"itemList": [],
"isExternal": false,
"path": "/recipes/react/react-compiler",
"tags": []
} }
], ],
"isExternal": false, "isExternal": false,
@ -3229,6 +3240,17 @@
"isExternal": false, "isExternal": false,
"path": "/recipes/react/deploy-nextjs-to-vercel", "path": "/recipes/react/deploy-nextjs-to-vercel",
"tags": [] "tags": []
},
{
"id": "react-compiler",
"name": "React Compiler with Nx",
"description": "",
"mediaImage": "",
"file": "shared/guides/react-compiler",
"itemList": [],
"isExternal": false,
"path": "/recipes/react/react-compiler",
"tags": []
} }
], ],
"isExternal": false, "isExternal": false,
@ -3312,6 +3334,17 @@
"path": "/recipes/react/deploy-nextjs-to-vercel", "path": "/recipes/react/deploy-nextjs-to-vercel",
"tags": [] "tags": []
}, },
"/recipes/react/react-compiler": {
"id": "react-compiler",
"name": "React Compiler with Nx",
"description": "",
"mediaImage": "",
"file": "shared/guides/react-compiler",
"itemList": [],
"isExternal": false,
"path": "/recipes/react/react-compiler",
"tags": []
},
"/recipes/angular": { "/recipes/angular": {
"id": "angular", "id": "angular",
"name": "Angular", "name": "Angular",

View File

@ -496,6 +496,11 @@
"name": "Deploying Next.js applications to Vercel", "name": "Deploying Next.js applications to Vercel",
"id": "deploy-nextjs-to-vercel", "id": "deploy-nextjs-to-vercel",
"file": "shared/recipes/deployment/deploy-nextjs-to-vercel" "file": "shared/recipes/deployment/deploy-nextjs-to-vercel"
},
{
"name": "React Compiler with Nx",
"id": "react-compiler",
"file": "shared/guides/react-compiler"
} }
] ]
}, },

View File

@ -0,0 +1,43 @@
# React Compiler with Nx
React 19 comes with an experimental compiler that optimizes application code to automatically memoize code. Read the [official React Compiler documentation](https://react.dev/learn/react-compiler) for more information.
## Enabling React Compiler in Nx Projects
For Nx projects using Babel and the `@nx/react/babel` preset, install the `babel-plugin-react-compiler` package and enable it with the `reactCompiler` option.
```json {% highlightLines=[7] %}
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"reactCompiler": true
}
]
],
"plugins": []
}
```
You can also pass an object to set compiler options.
```json {% highlightLines=["7-9"] %}
{
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"reactCompiler": {
"compilationMode": "annotation"
}
}
]
],
"plugins": []
}
```
Check the [React Compiler usage docs](https://react.dev/learn/react-compiler#installation) for all support setups, such as Vite, Remix, etc.

View File

@ -76,6 +76,7 @@
- [Adding Images, Fonts, and Files](/recipes/react/adding-assets-react) - [Adding Images, Fonts, and Files](/recipes/react/adding-assets-react)
- [Setup Module Federation with SSR for React](/recipes/react/module-federation-with-ssr) - [Setup Module Federation with SSR for React](/recipes/react/module-federation-with-ssr)
- [Deploying Next.js applications to Vercel](/recipes/react/deploy-nextjs-to-vercel) - [Deploying Next.js applications to Vercel](/recipes/react/deploy-nextjs-to-vercel)
- [React Compiler with Nx](/recipes/react/react-compiler)
- [Angular](/recipes/angular) - [Angular](/recipes/angular)
- [Migration](/recipes/angular/migration) - [Migration](/recipes/angular/migration)
- [Migrating from Angular CLI](/recipes/angular/migration/angular) - [Migrating from Angular CLI](/recipes/angular/migration/angular)

View File

@ -3,15 +3,21 @@
*/ */
interface NxReactBabelOptions { interface NxReactBabelOptions {
development?: boolean;
runtime?: string;
importSource?: string;
useBuiltIns?: boolean | string;
decorators?: { decorators?: {
decoratorsBeforeExport?: boolean; decoratorsBeforeExport?: boolean;
legacy?: boolean; legacy?: boolean;
}; };
development?: boolean;
importSource?: string;
loose?: boolean; loose?: boolean;
reactCompiler?:
| boolean
| {
compilationMode?: string;
sources?: (filename: string) => boolean;
};
runtime?: string;
useBuiltIns?: boolean | string;
/** @deprecated Use `loose` option instead of `classProperties.loose` /** @deprecated Use `loose` option instead of `classProperties.loose`
*/ */
classProperties?: { classProperties?: {
@ -27,7 +33,10 @@ module.exports = function (api: any, options: NxReactBabelOptions) {
*/ */
const isNextJs = api.caller((caller) => caller?.pagesDir); const isNextJs = api.caller((caller) => caller?.pagesDir);
const presets: any[] = [[require.resolve('@nx/js/babel'), options]]; const presets: Array<[string, unknown]> = [
[require.resolve('@nx/js/babel'), options],
];
const plugins: Array<[string, unknown]> = [];
/** /**
* Next.js already includes the preset-react, and including it * Next.js already includes the preset-react, and including it
@ -50,8 +59,25 @@ module.exports = function (api: any, options: NxReactBabelOptions) {
]); ]);
} }
if (options.reactCompiler) {
try {
const reactCompilerPlugin = require.resolve(
'babel-plugin-react-compiler'
);
plugins.push([
reactCompilerPlugin,
typeof options.reactCompiler !== 'boolean' ? options.reactCompiler : {},
]);
} catch {
throw new Error(
`Could not find "babel-plugin-react-compiler". Did you install it?`
);
}
}
return { return {
presets, presets,
plugins,
}; };
}; };