@vitejs/plugin-react 6.0.4 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -79,13 +79,42 @@ Under the hood, this simply updates the React Fash Refresh runtime URL from `/@r
79
79
 
80
80
  ## React Compiler
81
81
 
82
- [React Compiler](https://react.dev/learn/react-compiler) support is available via the exported `reactCompilerPreset` helper, which requires [`@rolldown/plugin-babel`](https://npmx.dev/package/@rolldown/plugin-babel) and [`babel-plugin-react-compiler`](https://npmx.dev/package/babel-plugin-react-compiler) and [`@babel/core`](https://npmx.dev/package/@babel/core) as peer dependencies:
82
+ ### Rust React Compiler
83
+
84
+ > [!WARNING]
85
+ > Native React Compiler support is experimental.
86
+
87
+ The `compiler` option uses [`oxc-transform-react`](https://npmx.dev/package/oxc-transform-react), a Rust port of [React Compiler](https://react.dev/learn/react-compiler), which must be installed as an optional peer dependency:
88
+
89
+ ```sh
90
+ npm install -D oxc-transform-react
91
+ ```
92
+
93
+ ```js
94
+ // vite.config.js
95
+ import { defineConfig } from 'vite'
96
+ import react from '@vitejs/plugin-react'
97
+
98
+ export default defineConfig({
99
+ plugins: [react({ compiler: true })],
100
+ })
101
+ ```
102
+
103
+ The `compiler` option also accepts [React Compiler options](https://react.dev/reference/react-compiler/configuration):
104
+
105
+ ```js
106
+ react({ compiler: { compilationMode: 'annotation' } })
107
+ ```
108
+
109
+ ### Babel React Compiler
110
+
111
+ React Compiler can also be used through Babel with the exported `reactCompilerPreset` helper. This requires [`@rolldown/plugin-babel`](https://npmx.dev/package/@rolldown/plugin-babel), [`babel-plugin-react-compiler`](https://npmx.dev/package/babel-plugin-react-compiler), and [`@babel/core`](https://npmx.dev/package/@babel/core) as peer dependencies:
83
112
 
84
113
  ```sh
85
114
  npm install -D @rolldown/plugin-babel @babel/core babel-plugin-react-compiler
86
115
  ```
87
116
 
88
- If you are using TypeScript, you will also need to install [`@types/babel__core`](https://npmx.dev/package/@types/babel__core):
117
+ If you are using TypeScript with Babel 7, you will also need to install [`@types/babel__core`](https://npmx.dev/package/@types/babel__core):
89
118
 
90
119
  ```sh
91
120
  npm install -D @types/babel__core
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Plugin } from "vite";
2
- import { ReactCompilerBabelPluginOptions, RolldownBabelPreset } from "#optionalTypes";
2
+ import { ReactCompilerBabelPluginOptions, ReactCompilerOptions, RolldownBabelPreset } from "#optionalTypes";
3
3
  //#region src/reactCompilerPreset.d.ts
4
4
  declare const reactCompilerPreset: (options?: ReactCompilerBabelPluginOptions) => RolldownBabelPreset;
5
5
  //#endregion
@@ -37,6 +37,13 @@ interface Options {
37
37
  * reactRefreshHost: 'http://localhost:3000'
38
38
  */
39
39
  reactRefreshHost?: string;
40
+ /**
41
+ * Enable React Compiler with its default options or configure it.
42
+ * This requires `oxc-transform-react` to be installed.
43
+ * @default false
44
+ * @experimental
45
+ */
46
+ compiler?: boolean | ReactCompilerOptions;
40
47
  }
41
48
  declare function viteReact(opts?: Options): Plugin[];
42
49
  declare namespace viteReact {
@@ -44,4 +51,4 @@ declare namespace viteReact {
44
51
  }
45
52
  declare function viteReactForCjs(this: unknown, options: Options): Plugin[];
46
53
  //#endregion
47
- export { Options, viteReact as default, viteReactForCjs as "module.exports", reactCompilerPreset };
54
+ export { Options, type ReactCompilerOptions, viteReact as default, viteReactForCjs as "module.exports", reactCompilerPreset };
package/dist/index.js CHANGED
@@ -41,7 +41,7 @@ const silenceUseClientWarning = (userConfig) => ({ rollupOptions: { onwarn(warni
41
41
  } } });
42
42
  //#endregion
43
43
  //#region src/reactCompilerPreset.ts
44
- const defaultCodeFilter = /forwardRef|memo|(?:const|let|var|function)\s+(?:[A-Z]|use[A-Z0-9])|(?:[A-Z]|use[A-Z0-9])[^\s:=(){}[\],;]*\s*(?:\(|[:=]\s*(?:function|\())/;
44
+ const defaultCodeFilter = /forwardRef|memo|\b(?:[A-Z]|use[A-Z0-9])/;
45
45
  const reactCompilerPreset = (options = {}) => ({
46
46
  preset: () => ({ plugins: [[fileURLToPath(import.meta.resolve("babel-plugin-react-compiler")), options]] }),
47
47
  rolldown: {
@@ -52,7 +52,8 @@ const reactCompilerPreset = (options = {}) => ({
52
52
  });
53
53
  //#endregion
54
54
  //#region src/index.ts
55
- const refreshRuntimePath = join(dirname(fileURLToPath(import.meta.url)), "refresh-runtime.js");
55
+ const _dirname = dirname(fileURLToPath(import.meta.url));
56
+ const refreshRuntimePath = join(_dirname, "refresh-runtime.js");
56
57
  const defaultIncludeRE = /\.[tj]sx?$/;
57
58
  const defaultExcludeRE = /\/node_modules\//;
58
59
  function viteReact(opts = {}) {
@@ -72,10 +73,11 @@ function viteReact(opts = {}) {
72
73
  name: "vite:react-babel",
73
74
  enforce: "pre",
74
75
  config(_userConfig, { command }) {
76
+ const refresh = command === "serve" && !opts.compiler;
75
77
  if (opts.jsxRuntime === "classic") return { oxc: {
76
78
  jsx: {
77
79
  runtime: "classic",
78
- refresh: command === "serve"
80
+ refresh
79
81
  },
80
82
  jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
81
83
  jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude)
@@ -85,7 +87,7 @@ function viteReact(opts = {}) {
85
87
  jsx: {
86
88
  runtime: "automatic",
87
89
  importSource: opts.jsxImportSource,
88
- refresh: command === "serve"
90
+ refresh
89
91
  },
90
92
  jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
91
93
  jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude)
@@ -152,7 +154,7 @@ function viteReact(opts = {}) {
152
154
  jsxImportDevRuntime,
153
155
  jsxImportRuntime
154
156
  ];
155
- return [
157
+ const plugins = [
156
158
  viteBabel,
157
159
  viteRefreshWrapper,
158
160
  viteConfigPost,
@@ -189,6 +191,62 @@ function viteReact(opts = {}) {
189
191
  isEnabled: () => !skipFastRefresh && !isBundledDev
190
192
  })
191
193
  ];
194
+ if (opts.compiler) plugins.unshift(createReactCompilerPlugin(opts.compiler === true ? {} : opts.compiler, include, exclude, opts, () => !skipFastRefresh));
195
+ return plugins;
196
+ }
197
+ function createReactCompilerPlugin(options, include, exclude, reactOptions, isFastRefreshEnabled) {
198
+ let sourcemap = true;
199
+ let jsxDevelopment = false;
200
+ let compiler;
201
+ const runtime = options.target === "17" || options.target === "18" ? "react-compiler-runtime" : "react/compiler-runtime";
202
+ const loadCompiler = async (onError) => {
203
+ if (compiler) return compiler;
204
+ try {
205
+ return compiler = await import("oxc-transform-react");
206
+ } catch (error) {
207
+ return onError(`React Compiler requires the optional \`oxc-transform-react\` package. Install it in your project before enabling \`react({ compiler: true })\`.${error instanceof Error ? `\n${error.message}` : ""}`);
208
+ }
209
+ };
210
+ return {
211
+ name: "vite:react-compiler",
212
+ enforce: "pre",
213
+ async config() {
214
+ await loadCompiler((message) => this.error(message));
215
+ return { optimizeDeps: { include: [runtime] } };
216
+ },
217
+ configResolved(config) {
218
+ sourcemap = config.command !== "build" || !!config.build.sourcemap;
219
+ jsxDevelopment = !config.isProduction;
220
+ },
221
+ transform: {
222
+ filter: { id: {
223
+ include: makeIdFiltersToMatchWithQuery(include),
224
+ exclude: makeIdFiltersToMatchWithQuery(exclude)
225
+ } },
226
+ async handler(code, id) {
227
+ const isClient = this.environment?.config.consumer !== "server";
228
+ const shouldCompile = isClient && (options.compilationMode === "annotation" ? /['"]use memo['"]/.test(code) : defaultCodeFilter.test(code));
229
+ const { transform } = compiler ?? await loadCompiler((message) => this.error(message));
230
+ const result = await transform(id.split("?")[0], code, {
231
+ jsx: {
232
+ runtime: reactOptions.jsxRuntime,
233
+ development: jsxDevelopment,
234
+ importSource: reactOptions.jsxImportSource,
235
+ refresh: isClient && isFastRefreshEnabled()
236
+ },
237
+ reactCompiler: shouldCompile ? options : false,
238
+ sourcemap
239
+ });
240
+ const diagnostics = result.errors.map((error) => `${error.message}${error.codeframe ? `\n${error.codeframe}` : ""}`);
241
+ if (result.fatal) this.error(diagnostics.join("\n\n") || "React Compiler transform failed.");
242
+ for (const diagnostic of diagnostics) this.warn(diagnostic);
243
+ return {
244
+ code: result.code,
245
+ map: result.map
246
+ };
247
+ }
248
+ }
249
+ };
192
250
  }
193
251
  viteReact.preambleCode = preambleCode;
194
252
  function viteReactForCjs(options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-react",
3
- "version": "6.0.4",
3
+ "version": "6.1.0",
4
4
  "description": "The default Vite plugin for React projects",
5
5
  "keywords": [
6
6
  "fast refresh",
@@ -50,15 +50,17 @@
50
50
  "@rolldown/plugin-babel": "^0.2.3",
51
51
  "@vitejs/react-common": "workspace:*",
52
52
  "babel-plugin-react-compiler": "^1.0.0",
53
+ "oxc-transform-react": "^0.145.0",
53
54
  "react": "^19.2.8",
54
55
  "react-dom": "^19.2.8",
55
- "rolldown": "^1.1.5",
56
- "tsdown": "^0.22.7",
57
- "vite": "^8.1.4"
56
+ "rolldown": "^1.2.3",
57
+ "tsdown": "^0.22.14",
58
+ "vite": "^8.2.1"
58
59
  },
59
60
  "peerDependencies": {
60
61
  "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0",
61
62
  "babel-plugin-react-compiler": "^1.0.0",
63
+ "oxc-transform-react": "^0.145.0",
62
64
  "vite": "^8.0.0"
63
65
  },
64
66
  "peerDependenciesMeta": {
@@ -67,6 +69,9 @@
67
69
  },
68
70
  "babel-plugin-react-compiler": {
69
71
  "optional": true
72
+ },
73
+ "oxc-transform-react": {
74
+ "optional": true
70
75
  }
71
76
  },
72
77
  "engines": {
@@ -4,9 +4,13 @@
4
4
  import type * as pluginBabel from '@rolldown/plugin-babel'
5
5
  // @ts-ignore --- `babel-plugin-react-compiler` is an optional peer dependency, so this may cause an error
6
6
  import type * as babelPluginReactCompiler from 'babel-plugin-react-compiler'
7
+ // @ts-ignore --- `oxc-transform-react` is an optional peer dependency, so this may cause an error
8
+ import type * as oxcTransformReact from 'oxc-transform-react'
7
9
 
8
10
  // @ts-ignore --- `@rolldown/plugin-babel` is an optional peer dependency, so this may cause an error
9
11
  export type RolldownBabelPreset = pluginBabel.RolldownBabelPreset
10
12
  // @ts-ignore --- `babel-plugin-react-compiler` is an optional peer dependency, so this may cause an error
11
13
  export type ReactCompilerBabelPluginOptions =
12
14
  babelPluginReactCompiler.PluginOptions
15
+ // @ts-ignore --- `oxc-transform-react` is an optional peer dependency, so this may cause an error
16
+ export type ReactCompilerOptions = oxcTransformReact.ReactCompilerOptions