@vitejs/plugin-react 4.5.2 → 4.7.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/dist/index.d.cts CHANGED
@@ -1,38 +1,39 @@
1
- import { TransformOptions, ParserOptions } from '@babel/core';
2
- import { PluginOption, ResolvedConfig } from 'vite';
1
+ import { ParserOptions, TransformOptions } from "@babel/core";
2
+ import { Plugin, ResolvedConfig } from "vite";
3
3
 
4
+ //#region src/index.d.ts
4
5
  interface Options {
5
- include?: string | RegExp | Array<string | RegExp>;
6
- exclude?: string | RegExp | Array<string | RegExp>;
7
- /**
8
- * Control where the JSX factory is imported from.
9
- * https://esbuild.github.io/api/#jsx-import-source
10
- * @default 'react'
11
- */
12
- jsxImportSource?: string;
13
- /**
14
- * Note: Skipping React import with classic runtime is not supported from v4
15
- * @default "automatic"
16
- */
17
- jsxRuntime?: 'classic' | 'automatic';
18
- /**
19
- * Babel configuration applied in both dev and prod.
20
- */
21
- babel?: BabelOptions | ((id: string, options: {
22
- ssr?: boolean;
23
- }) => BabelOptions);
24
- /**
25
- * React Fast Refresh runtime URL prefix.
26
- * Useful in a module federation context to enable HMR by specifying
27
- * the host application URL in the Vite config of a remote application.
28
- * @example
29
- * reactRefreshHost: 'http://localhost:3000'
30
- */
31
- reactRefreshHost?: string;
32
- /**
33
- * If set, disables the recommendation to use `@vitejs/plugin-react-oxc`
34
- */
35
- disableOxcRecommendation?: boolean;
6
+ include?: string | RegExp | Array<string | RegExp>;
7
+ exclude?: string | RegExp | Array<string | RegExp>;
8
+ /**
9
+ * Control where the JSX factory is imported from.
10
+ * https://esbuild.github.io/api/#jsx-import-source
11
+ * @default 'react'
12
+ */
13
+ jsxImportSource?: string;
14
+ /**
15
+ * Note: Skipping React import with classic runtime is not supported from v4
16
+ * @default "automatic"
17
+ */
18
+ jsxRuntime?: 'classic' | 'automatic';
19
+ /**
20
+ * Babel configuration applied in both dev and prod.
21
+ */
22
+ babel?: BabelOptions | ((id: string, options: {
23
+ ssr?: boolean;
24
+ }) => BabelOptions);
25
+ /**
26
+ * React Fast Refresh runtime URL prefix.
27
+ * Useful in a module federation context to enable HMR by specifying
28
+ * the host application URL in the Vite config of a remote application.
29
+ * @example
30
+ * reactRefreshHost: 'http://localhost:3000'
31
+ */
32
+ reactRefreshHost?: string;
33
+ /**
34
+ * If set, disables the recommendation to use `@vitejs/plugin-react-oxc`
35
+ */
36
+ disableOxcRecommendation?: boolean;
36
37
  }
37
38
  type BabelOptions = Omit<TransformOptions, 'ast' | 'filename' | 'root' | 'sourceFileName' | 'sourceMaps' | 'inputSourceMap'>;
38
39
  /**
@@ -40,28 +41,27 @@ type BabelOptions = Omit<TransformOptions, 'ast' | 'filename' | 'root' | 'source
40
41
  * an `api.reactBabel` method.
41
42
  */
42
43
  interface ReactBabelOptions extends BabelOptions {
43
- plugins: Extract<BabelOptions['plugins'], any[]>;
44
- presets: Extract<BabelOptions['presets'], any[]>;
45
- overrides: Extract<BabelOptions['overrides'], any[]>;
46
- parserOpts: ParserOptions & {
47
- plugins: Extract<ParserOptions['plugins'], any[]>;
48
- };
44
+ plugins: Extract<BabelOptions['plugins'], any[]>;
45
+ presets: Extract<BabelOptions['presets'], any[]>;
46
+ overrides: Extract<BabelOptions['overrides'], any[]>;
47
+ parserOpts: ParserOptions & {
48
+ plugins: Extract<ParserOptions['plugins'], any[]>;
49
+ };
49
50
  }
50
51
  type ReactBabelHook = (babelConfig: ReactBabelOptions, context: ReactBabelHookContext, config: ResolvedConfig) => void;
51
52
  type ReactBabelHookContext = {
52
- ssr: boolean;
53
- id: string;
53
+ ssr: boolean;
54
+ id: string;
54
55
  };
55
56
  type ViteReactPluginApi = {
56
- /**
57
- * Manipulate the Babel options of `@vitejs/plugin-react`
58
- */
59
- reactBabel?: ReactBabelHook;
57
+ /**
58
+ * Manipulate the Babel options of `@vitejs/plugin-react`
59
+ */
60
+ reactBabel?: ReactBabelHook;
60
61
  };
61
- declare function viteReact(opts?: Options): PluginOption[];
62
+ declare function viteReact(opts?: Options): Plugin[];
62
63
  declare namespace viteReact {
63
- var preambleCode: string;
64
+ var preambleCode: string;
64
65
  }
65
-
66
- export = viteReact;
67
- export type { BabelOptions, Options, ReactBabelOptions, ViteReactPluginApi };
66
+ //#endregion
67
+ export { BabelOptions, Options, ReactBabelOptions, ViteReactPluginApi, viteReact as default };
package/dist/index.d.ts CHANGED
@@ -1,38 +1,39 @@
1
- import { TransformOptions, ParserOptions } from '@babel/core';
2
- import { PluginOption, ResolvedConfig } from 'vite';
1
+ import { Plugin, ResolvedConfig } from "vite";
2
+ import { ParserOptions, TransformOptions } from "@babel/core";
3
3
 
4
+ //#region src/index.d.ts
4
5
  interface Options {
5
- include?: string | RegExp | Array<string | RegExp>;
6
- exclude?: string | RegExp | Array<string | RegExp>;
7
- /**
8
- * Control where the JSX factory is imported from.
9
- * https://esbuild.github.io/api/#jsx-import-source
10
- * @default 'react'
11
- */
12
- jsxImportSource?: string;
13
- /**
14
- * Note: Skipping React import with classic runtime is not supported from v4
15
- * @default "automatic"
16
- */
17
- jsxRuntime?: 'classic' | 'automatic';
18
- /**
19
- * Babel configuration applied in both dev and prod.
20
- */
21
- babel?: BabelOptions | ((id: string, options: {
22
- ssr?: boolean;
23
- }) => BabelOptions);
24
- /**
25
- * React Fast Refresh runtime URL prefix.
26
- * Useful in a module federation context to enable HMR by specifying
27
- * the host application URL in the Vite config of a remote application.
28
- * @example
29
- * reactRefreshHost: 'http://localhost:3000'
30
- */
31
- reactRefreshHost?: string;
32
- /**
33
- * If set, disables the recommendation to use `@vitejs/plugin-react-oxc`
34
- */
35
- disableOxcRecommendation?: boolean;
6
+ include?: string | RegExp | Array<string | RegExp>;
7
+ exclude?: string | RegExp | Array<string | RegExp>;
8
+ /**
9
+ * Control where the JSX factory is imported from.
10
+ * https://esbuild.github.io/api/#jsx-import-source
11
+ * @default 'react'
12
+ */
13
+ jsxImportSource?: string;
14
+ /**
15
+ * Note: Skipping React import with classic runtime is not supported from v4
16
+ * @default "automatic"
17
+ */
18
+ jsxRuntime?: 'classic' | 'automatic';
19
+ /**
20
+ * Babel configuration applied in both dev and prod.
21
+ */
22
+ babel?: BabelOptions | ((id: string, options: {
23
+ ssr?: boolean;
24
+ }) => BabelOptions);
25
+ /**
26
+ * React Fast Refresh runtime URL prefix.
27
+ * Useful in a module federation context to enable HMR by specifying
28
+ * the host application URL in the Vite config of a remote application.
29
+ * @example
30
+ * reactRefreshHost: 'http://localhost:3000'
31
+ */
32
+ reactRefreshHost?: string;
33
+ /**
34
+ * If set, disables the recommendation to use `@vitejs/plugin-react-oxc`
35
+ */
36
+ disableOxcRecommendation?: boolean;
36
37
  }
37
38
  type BabelOptions = Omit<TransformOptions, 'ast' | 'filename' | 'root' | 'sourceFileName' | 'sourceMaps' | 'inputSourceMap'>;
38
39
  /**
@@ -40,28 +41,27 @@ type BabelOptions = Omit<TransformOptions, 'ast' | 'filename' | 'root' | 'source
40
41
  * an `api.reactBabel` method.
41
42
  */
42
43
  interface ReactBabelOptions extends BabelOptions {
43
- plugins: Extract<BabelOptions['plugins'], any[]>;
44
- presets: Extract<BabelOptions['presets'], any[]>;
45
- overrides: Extract<BabelOptions['overrides'], any[]>;
46
- parserOpts: ParserOptions & {
47
- plugins: Extract<ParserOptions['plugins'], any[]>;
48
- };
44
+ plugins: Extract<BabelOptions['plugins'], any[]>;
45
+ presets: Extract<BabelOptions['presets'], any[]>;
46
+ overrides: Extract<BabelOptions['overrides'], any[]>;
47
+ parserOpts: ParserOptions & {
48
+ plugins: Extract<ParserOptions['plugins'], any[]>;
49
+ };
49
50
  }
50
51
  type ReactBabelHook = (babelConfig: ReactBabelOptions, context: ReactBabelHookContext, config: ResolvedConfig) => void;
51
52
  type ReactBabelHookContext = {
52
- ssr: boolean;
53
- id: string;
53
+ ssr: boolean;
54
+ id: string;
54
55
  };
55
56
  type ViteReactPluginApi = {
56
- /**
57
- * Manipulate the Babel options of `@vitejs/plugin-react`
58
- */
59
- reactBabel?: ReactBabelHook;
57
+ /**
58
+ * Manipulate the Babel options of `@vitejs/plugin-react`
59
+ */
60
+ reactBabel?: ReactBabelHook;
60
61
  };
61
- declare function viteReact(opts?: Options): PluginOption[];
62
+ declare function viteReact(opts?: Options): Plugin[];
62
63
  declare namespace viteReact {
63
- var preambleCode: string;
64
+ var preambleCode: string;
64
65
  }
65
-
66
- export = viteReact;
67
- export type { BabelOptions, Options, ReactBabelOptions, ViteReactPluginApi };
66
+ //#endregion
67
+ export { BabelOptions, Options, ReactBabelOptions, ViteReactPluginApi, viteReact as default };
package/dist/index.js ADDED
@@ -0,0 +1,320 @@
1
+ import { dirname, join } from "node:path";
2
+ import { fileURLToPath } from "node:url";
3
+ import { readFileSync } from "node:fs";
4
+ import * as vite from "vite";
5
+ import { createFilter } from "vite";
6
+ import { exactRegex, makeIdFiltersToMatchWithQuery } from "@rolldown/pluginutils";
7
+
8
+ //#region ../common/refresh-utils.ts
9
+ const runtimePublicPath = "/@react-refresh";
10
+ const reactCompRE = /extends\s+(?:React\.)?(?:Pure)?Component/;
11
+ const refreshContentRE = /\$RefreshReg\$\(/;
12
+ const preambleCode = `import { injectIntoGlobalHook } from "__BASE__${runtimePublicPath.slice(1)}";
13
+ injectIntoGlobalHook(window);
14
+ window.$RefreshReg$ = () => {};
15
+ window.$RefreshSig$ = () => (type) => type;`;
16
+ const getPreambleCode = (base) => preambleCode.replace("__BASE__", base);
17
+ const avoidSourceMapOption = Symbol();
18
+ function addRefreshWrapper(code, map, pluginName, id, reactRefreshHost = "") {
19
+ const hasRefresh = refreshContentRE.test(code);
20
+ const onlyReactComp = !hasRefresh && reactCompRE.test(code);
21
+ const normalizedMap = map === avoidSourceMapOption ? null : map;
22
+ if (!hasRefresh && !onlyReactComp) return {
23
+ code,
24
+ map: normalizedMap
25
+ };
26
+ const avoidSourceMap = map === avoidSourceMapOption;
27
+ const newMap = typeof normalizedMap === "string" ? JSON.parse(normalizedMap) : normalizedMap;
28
+ let newCode = code;
29
+ if (hasRefresh) {
30
+ const refreshHead = removeLineBreaksIfNeeded(`let prevRefreshReg;
31
+ let prevRefreshSig;
32
+
33
+ if (import.meta.hot && !inWebWorker) {
34
+ if (!window.$RefreshReg$) {
35
+ throw new Error(
36
+ "${pluginName} can't detect preamble. Something is wrong."
37
+ );
38
+ }
39
+
40
+ prevRefreshReg = window.$RefreshReg$;
41
+ prevRefreshSig = window.$RefreshSig$;
42
+ window.$RefreshReg$ = RefreshRuntime.getRefreshReg(${JSON.stringify(id)});
43
+ window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;
44
+ }
45
+
46
+ `, avoidSourceMap);
47
+ newCode = `${refreshHead}${newCode}
48
+
49
+ if (import.meta.hot && !inWebWorker) {
50
+ window.$RefreshReg$ = prevRefreshReg;
51
+ window.$RefreshSig$ = prevRefreshSig;
52
+ }
53
+ `;
54
+ if (newMap) newMap.mappings = ";".repeat(16) + newMap.mappings;
55
+ }
56
+ const sharedHead = removeLineBreaksIfNeeded(`import * as RefreshRuntime from "${reactRefreshHost}${runtimePublicPath}";
57
+ const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
58
+
59
+ `, avoidSourceMap);
60
+ newCode = `${sharedHead}${newCode}
61
+
62
+ if (import.meta.hot && !inWebWorker) {
63
+ RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
64
+ RefreshRuntime.registerExportsForReactRefresh(${JSON.stringify(id)}, currentExports);
65
+ import.meta.hot.accept((nextExports) => {
66
+ if (!nextExports) return;
67
+ const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(${JSON.stringify(id)}, currentExports, nextExports);
68
+ if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage);
69
+ });
70
+ });
71
+ }
72
+ `;
73
+ if (newMap) newMap.mappings = ";;;" + newMap.mappings;
74
+ return {
75
+ code: newCode,
76
+ map: newMap
77
+ };
78
+ }
79
+ function removeLineBreaksIfNeeded(code, enabled) {
80
+ return enabled ? code.replace(/\n/g, "") : code;
81
+ }
82
+
83
+ //#endregion
84
+ //#region ../common/warning.ts
85
+ const silenceUseClientWarning = (userConfig) => ({ rollupOptions: { onwarn(warning, defaultHandler) {
86
+ var _userConfig$build;
87
+ if (warning.code === "MODULE_LEVEL_DIRECTIVE" && (warning.message.includes("use client") || warning.message.includes("use server"))) return;
88
+ if (warning.code === "SOURCEMAP_ERROR" && warning.message.includes("resolve original location") && warning.pos === 0) return;
89
+ if ((_userConfig$build = userConfig.build) === null || _userConfig$build === void 0 || (_userConfig$build = _userConfig$build.rollupOptions) === null || _userConfig$build === void 0 ? void 0 : _userConfig$build.onwarn) userConfig.build.rollupOptions.onwarn(warning, defaultHandler);
90
+ else defaultHandler(warning);
91
+ } } });
92
+
93
+ //#endregion
94
+ //#region src/index.ts
95
+ const _dirname = dirname(fileURLToPath(import.meta.url));
96
+ const refreshRuntimePath = join(_dirname, "refresh-runtime.js");
97
+ let babel;
98
+ async function loadBabel() {
99
+ if (!babel) babel = await import("@babel/core");
100
+ return babel;
101
+ }
102
+ const defaultIncludeRE = /\.[tj]sx?$/;
103
+ const tsRE = /\.tsx?$/;
104
+ function viteReact(opts = {}) {
105
+ var _opts$babel;
106
+ const include = opts.include ?? defaultIncludeRE;
107
+ const exclude = opts.exclude;
108
+ const filter = createFilter(include, exclude);
109
+ const jsxImportSource = opts.jsxImportSource ?? "react";
110
+ const jsxImportRuntime = `${jsxImportSource}/jsx-runtime`;
111
+ const jsxImportDevRuntime = `${jsxImportSource}/jsx-dev-runtime`;
112
+ let runningInVite = false;
113
+ let isProduction = true;
114
+ let projectRoot = process.cwd();
115
+ let skipFastRefresh = true;
116
+ let runPluginOverrides;
117
+ let staticBabelOptions;
118
+ const importReactRE = /\bimport\s+(?:\*\s+as\s+)?React\b/;
119
+ const viteBabel = {
120
+ name: "vite:react-babel",
121
+ enforce: "pre",
122
+ config() {
123
+ if (opts.jsxRuntime === "classic") if ("rolldownVersion" in vite) return { oxc: { jsx: {
124
+ runtime: "classic",
125
+ development: false
126
+ } } };
127
+ else return { esbuild: { jsx: "transform" } };
128
+ else return {
129
+ esbuild: {
130
+ jsx: "automatic",
131
+ jsxImportSource: opts.jsxImportSource
132
+ },
133
+ optimizeDeps: "rolldownVersion" in vite ? { rollupOptions: { jsx: { mode: "automatic" } } } : { esbuildOptions: { jsx: "automatic" } }
134
+ };
135
+ },
136
+ configResolved(config) {
137
+ runningInVite = true;
138
+ projectRoot = config.root;
139
+ isProduction = config.isProduction;
140
+ skipFastRefresh = isProduction || config.command === "build" || config.server.hmr === false;
141
+ if ("jsxPure" in opts) config.logger.warnOnce("[@vitejs/plugin-react] jsxPure was removed. You can configure esbuild.jsxSideEffects directly.");
142
+ const hooks = config.plugins.map((plugin) => {
143
+ var _plugin$api;
144
+ return (_plugin$api = plugin.api) === null || _plugin$api === void 0 ? void 0 : _plugin$api.reactBabel;
145
+ }).filter(defined);
146
+ if ("rolldownVersion" in vite && !opts.babel && !hooks.length && !opts.disableOxcRecommendation) config.logger.warn("[vite:react-babel] We recommend switching to `@vitejs/plugin-react-oxc` for improved performance. More information at https://vite.dev/rolldown");
147
+ if (hooks.length > 0) runPluginOverrides = (babelOptions, context) => {
148
+ hooks.forEach((hook) => hook(babelOptions, context, config));
149
+ };
150
+ else if (typeof opts.babel !== "function") {
151
+ staticBabelOptions = createBabelOptions(opts.babel);
152
+ if (canSkipBabel(staticBabelOptions.plugins, staticBabelOptions) && skipFastRefresh && (opts.jsxRuntime === "classic" ? isProduction : true)) delete viteBabel.transform;
153
+ }
154
+ },
155
+ options(options) {
156
+ if (!runningInVite) {
157
+ options.jsx = {
158
+ mode: opts.jsxRuntime,
159
+ importSource: opts.jsxImportSource
160
+ };
161
+ return options;
162
+ }
163
+ },
164
+ transform: {
165
+ filter: { id: {
166
+ include: makeIdFiltersToMatchWithQuery(include),
167
+ exclude: [...exclude ? makeIdFiltersToMatchWithQuery(ensureArray(exclude)) : [], /\/node_modules\//]
168
+ } },
169
+ async handler(code, id, options) {
170
+ if (id.includes("/node_modules/")) return;
171
+ const [filepath] = id.split("?");
172
+ if (!filter(filepath)) return;
173
+ const ssr = (options === null || options === void 0 ? void 0 : options.ssr) === true;
174
+ const babelOptions = (() => {
175
+ if (staticBabelOptions) return staticBabelOptions;
176
+ const newBabelOptions = createBabelOptions(typeof opts.babel === "function" ? opts.babel(id, { ssr }) : opts.babel);
177
+ runPluginOverrides === null || runPluginOverrides === void 0 || runPluginOverrides(newBabelOptions, {
178
+ id,
179
+ ssr
180
+ });
181
+ return newBabelOptions;
182
+ })();
183
+ const plugins = [...babelOptions.plugins];
184
+ const isJSX = filepath.endsWith("x");
185
+ const useFastRefresh = !skipFastRefresh && !ssr && (isJSX || (opts.jsxRuntime === "classic" ? importReactRE.test(code) : code.includes(jsxImportDevRuntime) || code.includes(jsxImportRuntime)));
186
+ if (useFastRefresh) plugins.push([await loadPlugin("react-refresh/babel"), { skipEnvCheck: true }]);
187
+ if (opts.jsxRuntime === "classic" && isJSX) {
188
+ if (!isProduction) plugins.push(await loadPlugin("@babel/plugin-transform-react-jsx-self"), await loadPlugin("@babel/plugin-transform-react-jsx-source"));
189
+ }
190
+ if (canSkipBabel(plugins, babelOptions)) return;
191
+ const parserPlugins = [...babelOptions.parserOpts.plugins];
192
+ if (!filepath.endsWith(".ts")) parserPlugins.push("jsx");
193
+ if (tsRE.test(filepath)) parserPlugins.push("typescript");
194
+ const babel$1 = await loadBabel();
195
+ const result = await babel$1.transformAsync(code, {
196
+ ...babelOptions,
197
+ root: projectRoot,
198
+ filename: id,
199
+ sourceFileName: filepath,
200
+ retainLines: getReactCompilerPlugin(plugins) != null ? false : !isProduction && isJSX && opts.jsxRuntime !== "classic",
201
+ parserOpts: {
202
+ ...babelOptions.parserOpts,
203
+ sourceType: "module",
204
+ allowAwaitOutsideFunction: true,
205
+ plugins: parserPlugins
206
+ },
207
+ generatorOpts: {
208
+ ...babelOptions.generatorOpts,
209
+ importAttributesKeyword: "with",
210
+ decoratorsBeforeExport: true
211
+ },
212
+ plugins,
213
+ sourceMaps: true
214
+ });
215
+ if (result) {
216
+ if (!useFastRefresh) return {
217
+ code: result.code,
218
+ map: result.map
219
+ };
220
+ return addRefreshWrapper(result.code, result.map, "@vitejs/plugin-react", id, opts.reactRefreshHost);
221
+ }
222
+ }
223
+ }
224
+ };
225
+ const dependencies = [
226
+ "react",
227
+ "react-dom",
228
+ jsxImportDevRuntime,
229
+ jsxImportRuntime
230
+ ];
231
+ const staticBabelPlugins = typeof opts.babel === "object" ? ((_opts$babel = opts.babel) === null || _opts$babel === void 0 ? void 0 : _opts$babel.plugins) ?? [] : [];
232
+ const reactCompilerPlugin = getReactCompilerPlugin(staticBabelPlugins);
233
+ if (reactCompilerPlugin != null) {
234
+ const reactCompilerRuntimeModule = getReactCompilerRuntimeModule(reactCompilerPlugin);
235
+ dependencies.push(reactCompilerRuntimeModule);
236
+ }
237
+ const viteReactRefresh = {
238
+ name: "vite:react-refresh",
239
+ enforce: "pre",
240
+ config: (userConfig) => ({
241
+ build: silenceUseClientWarning(userConfig),
242
+ optimizeDeps: { include: dependencies },
243
+ resolve: { dedupe: ["react", "react-dom"] }
244
+ }),
245
+ resolveId: {
246
+ filter: { id: exactRegex(runtimePublicPath) },
247
+ handler(id) {
248
+ if (id === runtimePublicPath) return id;
249
+ }
250
+ },
251
+ load: {
252
+ filter: { id: exactRegex(runtimePublicPath) },
253
+ handler(id) {
254
+ if (id === runtimePublicPath) return readFileSync(refreshRuntimePath, "utf-8").replace(/__README_URL__/g, "https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react");
255
+ }
256
+ },
257
+ transformIndexHtml(_, config) {
258
+ if (!skipFastRefresh) return [{
259
+ tag: "script",
260
+ attrs: { type: "module" },
261
+ children: getPreambleCode(config.server.config.base)
262
+ }];
263
+ }
264
+ };
265
+ return [viteBabel, viteReactRefresh];
266
+ }
267
+ viteReact.preambleCode = preambleCode;
268
+ function canSkipBabel(plugins, babelOptions) {
269
+ return !(plugins.length || babelOptions.presets.length || babelOptions.configFile || babelOptions.babelrc);
270
+ }
271
+ const loadedPlugin = /* @__PURE__ */ new Map();
272
+ function loadPlugin(path) {
273
+ const cached = loadedPlugin.get(path);
274
+ if (cached) return cached;
275
+ const promise = import(path).then((module) => {
276
+ const value = module.default || module;
277
+ loadedPlugin.set(path, value);
278
+ return value;
279
+ });
280
+ loadedPlugin.set(path, promise);
281
+ return promise;
282
+ }
283
+ function createBabelOptions(rawOptions) {
284
+ var _babelOptions$parserO;
285
+ const babelOptions = {
286
+ babelrc: false,
287
+ configFile: false,
288
+ ...rawOptions
289
+ };
290
+ babelOptions.plugins || (babelOptions.plugins = []);
291
+ babelOptions.presets || (babelOptions.presets = []);
292
+ babelOptions.overrides || (babelOptions.overrides = []);
293
+ babelOptions.parserOpts || (babelOptions.parserOpts = {});
294
+ (_babelOptions$parserO = babelOptions.parserOpts).plugins || (_babelOptions$parserO.plugins = []);
295
+ return babelOptions;
296
+ }
297
+ function defined(value) {
298
+ return value !== void 0;
299
+ }
300
+ function getReactCompilerPlugin(plugins) {
301
+ return plugins.find((p) => p === "babel-plugin-react-compiler" || Array.isArray(p) && p[0] === "babel-plugin-react-compiler");
302
+ }
303
+ function getReactCompilerRuntimeModule(plugin) {
304
+ let moduleName = "react/compiler-runtime";
305
+ if (Array.isArray(plugin)) {
306
+ var _plugin$, _plugin$2, _plugin$3;
307
+ if (((_plugin$ = plugin[1]) === null || _plugin$ === void 0 ? void 0 : _plugin$.target) === "17" || ((_plugin$2 = plugin[1]) === null || _plugin$2 === void 0 ? void 0 : _plugin$2.target) === "18") moduleName = "react-compiler-runtime";
308
+ else if (typeof ((_plugin$3 = plugin[1]) === null || _plugin$3 === void 0 ? void 0 : _plugin$3.runtimeModule) === "string") {
309
+ var _plugin$4;
310
+ moduleName = (_plugin$4 = plugin[1]) === null || _plugin$4 === void 0 ? void 0 : _plugin$4.runtimeModule;
311
+ }
312
+ }
313
+ return moduleName;
314
+ }
315
+ function ensureArray(value) {
316
+ return Array.isArray(value) ? value : [value];
317
+ }
318
+
319
+ //#endregion
320
+ export { viteReact as default };
@@ -545,6 +545,21 @@ function isLikelyComponentType(type) {
545
545
  }
546
546
  }
547
547
 
548
+ function isCompoundComponent(type) {
549
+ if (!isPlainObject(type)) return false
550
+ for (const key in type) {
551
+ if (!isLikelyComponentType(type[key])) return false
552
+ }
553
+ return true
554
+ }
555
+
556
+ function isPlainObject(obj) {
557
+ return (
558
+ Object.prototype.toString.call(obj) === '[object Object]' &&
559
+ (obj.constructor === Object || obj.constructor === undefined)
560
+ )
561
+ }
562
+
548
563
  /**
549
564
  * Plugin utils
550
565
  */
@@ -565,6 +580,13 @@ export function registerExportsForReactRefresh(filename, moduleExports) {
565
580
  // The register function has an identity check to not register twice the same component,
566
581
  // so this is safe to not used the same key here.
567
582
  register(exportValue, filename + ' export ' + key)
583
+ } else if (isCompoundComponent(exportValue)) {
584
+ for (const subKey in exportValue) {
585
+ register(
586
+ exportValue[subKey],
587
+ filename + ' export ' + key + '-' + subKey,
588
+ )
589
+ }
568
590
  }
569
591
  }
570
592
  }
@@ -618,6 +640,7 @@ export function validateRefreshBoundaryAndEnqueueUpdate(
618
640
  (key, value) => {
619
641
  hasExports = true
620
642
  if (isLikelyComponentType(value)) return true
643
+ if (isCompoundComponent(value)) return true
621
644
  return prevExports[key] === nextExports[key]
622
645
  },
623
646
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-react",
3
- "version": "4.5.2",
3
+ "version": "4.7.0",
4
4
  "license": "MIT",
5
5
  "author": "Evan You",
6
6
  "description": "The default Vite plugin for React projects",
@@ -21,19 +21,19 @@
21
21
  ],
22
22
  "type": "module",
23
23
  "main": "./dist/index.cjs",
24
- "module": "./dist/index.mjs",
25
- "types": "./dist/index.d.mts",
24
+ "module": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
26
  "exports": {
27
27
  ".": {
28
- "import": "./dist/index.mjs",
28
+ "import": "./dist/index.js",
29
29
  "require": "./dist/index.cjs"
30
30
  }
31
31
  },
32
32
  "scripts": {
33
- "dev": "unbuild --stub",
34
- "build": "unbuild && pnpm run patch-cjs && tsx scripts/copyRefreshRuntime.ts",
35
- "patch-cjs": "tsx ../../scripts/patchCJS.ts",
36
- "prepublishOnly": "npm run build"
33
+ "dev": "tsdown --watch",
34
+ "build": "tsdown",
35
+ "prepublishOnly": "npm run build",
36
+ "test-unit": "vitest run"
37
37
  },
38
38
  "engines": {
39
39
  "node": "^14.18.0 || >=16.0.0"
@@ -48,18 +48,23 @@
48
48
  },
49
49
  "homepage": "https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme",
50
50
  "dependencies": {
51
- "@babel/core": "^7.27.4",
51
+ "@babel/core": "^7.28.0",
52
52
  "@babel/plugin-transform-react-jsx-self": "^7.27.1",
53
53
  "@babel/plugin-transform-react-jsx-source": "^7.27.1",
54
- "@rolldown/pluginutils": "1.0.0-beta.11",
54
+ "@rolldown/pluginutils": "1.0.0-beta.27",
55
55
  "@types/babel__core": "^7.20.5",
56
56
  "react-refresh": "^0.17.0"
57
57
  },
58
58
  "peerDependencies": {
59
- "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0"
59
+ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@vitejs/react-common": "workspace:*",
63
- "unbuild": "^3.5.0"
63
+ "babel-plugin-react-compiler": "19.1.0-rc.2",
64
+ "react": "^19.1.0",
65
+ "react-dom": "^19.1.0",
66
+ "rolldown": "1.0.0-beta.27",
67
+ "tsdown": "^0.12.9",
68
+ "vitest": "^3.2.4"
64
69
  }
65
70
  }