@vitejs/plugin-react 5.0.2 → 5.0.4

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
@@ -127,10 +127,6 @@ Otherwise, you'll probably get this error:
127
127
  Uncaught Error: @vitejs/plugin-react can't detect preamble. Something is wrong.
128
128
  ```
129
129
 
130
- ### disableOxcRecommendation
131
-
132
- If set, disables the recommendation to use `@vitejs/plugin-react-oxc` (which is shown when `rolldown-vite` is detected and `babel` is not configured).
133
-
134
130
  ## Consistent components exports
135
131
 
136
132
  For React refresh to work correctly, your file should only export React components. You can find a good explanation in the [Gatsby docs](https://www.gatsbyjs.com/docs/reference/local-development/fast-refresh/#how-it-works).
package/dist/index.js CHANGED
@@ -14,22 +14,15 @@ injectIntoGlobalHook(window);
14
14
  window.$RefreshReg$ = () => {};
15
15
  window.$RefreshSig$ = () => (type) => type;`;
16
16
  const getPreambleCode = (base) => preambleCode.replace("__BASE__", base);
17
- const avoidSourceMapOption = Symbol();
18
- function addRefreshWrapper(code, map, pluginName, id, reactRefreshHost = "") {
17
+ function addRefreshWrapper(code, pluginName, id, reactRefreshHost = "") {
19
18
  const hasRefresh = refreshContentRE.test(code);
20
19
  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;
20
+ if (!hasRefresh && !onlyReactComp) return void 0;
28
21
  let newCode = code;
29
- if (hasRefresh) {
30
- const refreshHead = removeLineBreaksIfNeeded(`let prevRefreshReg;
31
- let prevRefreshSig;
22
+ newCode += `
32
23
 
24
+ import * as RefreshRuntime from "${reactRefreshHost}${runtimePublicPath}";
25
+ const inWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;
33
26
  if (import.meta.hot && !inWebWorker) {
34
27
  if (!window.$RefreshReg$) {
35
28
  throw new Error(
@@ -37,29 +30,6 @@ if (import.meta.hot && !inWebWorker) {
37
30
  );
38
31
  }
39
32
 
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
33
  RefreshRuntime.__hmr_import(import.meta.url).then((currentExports) => {
64
34
  RefreshRuntime.registerExportsForReactRefresh(${JSON.stringify(id)}, currentExports);
65
35
  import.meta.hot.accept((nextExports) => {
@@ -70,14 +40,10 @@ if (import.meta.hot && !inWebWorker) {
70
40
  });
71
41
  }
72
42
  `;
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;
43
+ if (hasRefresh) newCode += `function $RefreshReg$(type, id) { return RefreshRuntime.register(type, ${JSON.stringify(id)} + ' ' + id) }
44
+ function $RefreshSig$() { return RefreshRuntime.createSignatureFunctionForTransform(); }
45
+ `;
46
+ return newCode;
81
47
  }
82
48
 
83
49
  //#endregion
@@ -114,6 +80,8 @@ function viteReact(opts = {}) {
114
80
  let isProduction = true;
115
81
  let projectRoot = process.cwd();
116
82
  let skipFastRefresh = true;
83
+ let base;
84
+ let isFullBundle = false;
117
85
  let runPluginOverrides;
118
86
  let staticBabelOptions;
119
87
  const importReactRE = /\bimport\s+(?:\*\s+as\s+)?React\b/;
@@ -127,8 +95,8 @@ function viteReact(opts = {}) {
127
95
  refresh: command === "serve",
128
96
  development: false
129
97
  },
130
- jsxRefreshInclude: include,
131
- jsxRefreshExclude: exclude
98
+ jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
99
+ jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude)
132
100
  } };
133
101
  else return {
134
102
  oxc: {
@@ -137,8 +105,8 @@ function viteReact(opts = {}) {
137
105
  importSource: opts.jsxImportSource,
138
106
  refresh: command === "serve"
139
107
  },
140
- jsxRefreshInclude: include,
141
- jsxRefreshExclude: exclude
108
+ jsxRefreshInclude: makeIdFiltersToMatchWithQuery(include),
109
+ jsxRefreshExclude: makeIdFiltersToMatchWithQuery(exclude)
142
110
  },
143
111
  optimizeDeps: { rollupOptions: { transform: { jsx: { runtime: "automatic" } } } }
144
112
  };
@@ -153,6 +121,8 @@ function viteReact(opts = {}) {
153
121
  },
154
122
  configResolved(config) {
155
123
  runningInVite = true;
124
+ base = config.base;
125
+ if (config.experimental.fullBundleMode) isFullBundle = true;
156
126
  projectRoot = config.root;
157
127
  isProduction = config.isProduction;
158
128
  skipFastRefresh = isProduction || config.command === "build" || config.server.hmr === false;
@@ -212,8 +182,7 @@ function viteReact(opts = {}) {
212
182
  const parserPlugins = [...babelOptions.parserOpts.plugins];
213
183
  if (!filepath.endsWith(".ts")) parserPlugins.push("jsx");
214
184
  if (tsRE.test(filepath)) parserPlugins.push("typescript");
215
- const babel$1 = await loadBabel();
216
- const result = await babel$1.transformAsync(code, {
185
+ const result = await (await loadBabel()).transformAsync(code, {
217
186
  ...babelOptions,
218
187
  root: projectRoot,
219
188
  filename: id,
@@ -238,7 +207,10 @@ function viteReact(opts = {}) {
238
207
  code: result.code,
239
208
  map: result.map
240
209
  };
241
- return addRefreshWrapper(result.code, result.map, "@vitejs/plugin-react", id, opts.reactRefreshHost);
210
+ return {
211
+ code: addRefreshWrapper(result.code, "@vitejs/plugin-react", id, opts.reactRefreshHost) ?? result.code,
212
+ map: result.map
213
+ };
242
214
  }
243
215
  }
244
216
  }
@@ -246,6 +218,26 @@ function viteReact(opts = {}) {
246
218
  const viteRefreshWrapper = {
247
219
  name: "vite:react:refresh-wrapper",
248
220
  apply: "serve",
221
+ async applyToEnvironment(env) {
222
+ if (env.config.consumer !== "client" || skipFastRefresh) return false;
223
+ let nativePlugin;
224
+ try {
225
+ nativePlugin = (await import("vite/internal")).reactRefreshWrapperPlugin;
226
+ } catch {}
227
+ if (!nativePlugin || [
228
+ "7.1.10",
229
+ "7.1.11",
230
+ "7.1.12"
231
+ ].includes(vite.version)) return true;
232
+ delete viteRefreshWrapper.transform;
233
+ return nativePlugin({
234
+ cwd: process.cwd(),
235
+ include: makeIdFiltersToMatchWithQuery(include),
236
+ exclude: makeIdFiltersToMatchWithQuery(exclude),
237
+ jsxImportSource,
238
+ reactRefreshHost: opts.reactRefreshHost ?? ""
239
+ });
240
+ },
249
241
  transform: {
250
242
  filter: { id: {
251
243
  include: makeIdFiltersToMatchWithQuery(include),
@@ -255,13 +247,12 @@ function viteReact(opts = {}) {
255
247
  const ssr = options?.ssr === true;
256
248
  const [filepath] = id.split("?");
257
249
  const isJSX = filepath.endsWith("x");
258
- const useFastRefresh = !skipFastRefresh && !ssr && (isJSX || code.includes(jsxImportDevRuntime) || code.includes(jsxImportRuntime));
259
- if (!useFastRefresh) return;
260
- const { code: newCode } = addRefreshWrapper(code, avoidSourceMapOption, "@vitejs/plugin-react", id, opts.reactRefreshHost);
261
- return {
250
+ if (!(!skipFastRefresh && !ssr && (isJSX || code.includes(jsxImportDevRuntime) || code.includes(jsxImportRuntime)))) return;
251
+ const newCode = addRefreshWrapper(code, "@vitejs/plugin-react", id, opts.reactRefreshHost);
252
+ return newCode ? {
262
253
  code: newCode,
263
254
  map: null
264
- };
255
+ } : void 0;
265
256
  }
266
257
  }
267
258
  };
@@ -272,6 +263,20 @@ function viteReact(opts = {}) {
272
263
  if (userConfig.server?.hmr === false) return { oxc: { jsx: { refresh: false } } };
273
264
  }
274
265
  };
266
+ const viteReactRefreshFullBundleMode = {
267
+ name: "vite:react-refresh-fbm",
268
+ enforce: "pre",
269
+ transformIndexHtml: {
270
+ handler() {
271
+ if (!skipFastRefresh && isFullBundle) return [{
272
+ tag: "script",
273
+ attrs: { type: "module" },
274
+ children: getPreambleCode(base)
275
+ }];
276
+ },
277
+ order: "pre"
278
+ }
279
+ };
275
280
  const dependencies = [
276
281
  "react",
277
282
  "react-dom",
@@ -303,17 +308,21 @@ function viteReact(opts = {}) {
303
308
  if (id === runtimePublicPath) return readFileSync(refreshRuntimePath, "utf-8").replace(/__README_URL__/g, "https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react");
304
309
  }
305
310
  },
306
- transformIndexHtml(_, config) {
307
- if (!skipFastRefresh) return [{
311
+ transformIndexHtml() {
312
+ if (!skipFastRefresh && !isFullBundle) return [{
308
313
  tag: "script",
309
314
  attrs: { type: "module" },
310
- children: getPreambleCode(config.server.config.base)
315
+ children: getPreambleCode(base)
311
316
  }];
312
317
  }
313
318
  };
314
319
  return [
315
320
  viteBabel,
316
- ...isRolldownVite ? [viteRefreshWrapper, viteConfigPost] : [],
321
+ ...isRolldownVite ? [
322
+ viteRefreshWrapper,
323
+ viteConfigPost,
324
+ viteReactRefreshFullBundleMode
325
+ ] : [],
317
326
  viteReactRefresh
318
327
  ];
319
328
  }
@@ -243,7 +243,7 @@ function performReactRefresh() {
243
243
  }
244
244
  }
245
245
 
246
- function register(type, id) {
246
+ export function register(type, id) {
247
247
  if (type === null) {
248
248
  return
249
249
  }
@@ -564,10 +564,6 @@ function isPlainObject(obj) {
564
564
  * Plugin utils
565
565
  */
566
566
 
567
- export function getRefreshReg(filename) {
568
- return (type, id) => register(type, filename + ' ' + id)
569
- }
570
-
571
567
  // Taken from https://github.com/pmmmwh/react-refresh-webpack-plugin/blob/main/lib/runtime/RefreshUtils.js#L141
572
568
  // This allows to resister components not detected by SWC like styled component
573
569
  export function registerExportsForReactRefresh(filename, moduleExports) {
@@ -653,10 +649,7 @@ export function validateRefreshBoundaryAndEnqueueUpdate(
653
649
 
654
650
  function predicateOnExport(ignoredExports, moduleExports, predicate) {
655
651
  for (const key in moduleExports) {
656
- if (key === '__esModule') continue
657
652
  if (ignoredExports.includes(key)) continue
658
- const desc = Object.getOwnPropertyDescriptor(moduleExports, key)
659
- if (desc && desc.get) return key
660
653
  if (!predicate(key, moduleExports[key])) return key
661
654
  }
662
655
  return true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-react",
3
- "version": "5.0.2",
3
+ "version": "5.0.4",
4
4
  "license": "MIT",
5
5
  "author": "Evan You",
6
6
  "description": "The default Vite plugin for React projects",
@@ -40,10 +40,10 @@
40
40
  },
41
41
  "homepage": "https://github.com/vitejs/vite-plugin-react/tree/main/packages/plugin-react#readme",
42
42
  "dependencies": {
43
- "@babel/core": "^7.28.3",
43
+ "@babel/core": "^7.28.4",
44
44
  "@babel/plugin-transform-react-jsx-self": "^7.27.1",
45
45
  "@babel/plugin-transform-react-jsx-source": "^7.27.1",
46
- "@rolldown/pluginutils": "1.0.0-beta.34",
46
+ "@rolldown/pluginutils": "1.0.0-beta.38",
47
47
  "@types/babel__core": "^7.20.5",
48
48
  "react-refresh": "^0.17.0"
49
49
  },
@@ -52,11 +52,11 @@
52
52
  },
53
53
  "devDependencies": {
54
54
  "@vitejs/react-common": "workspace:*",
55
- "babel-plugin-react-compiler": "19.1.0-rc.2",
55
+ "babel-plugin-react-compiler": "19.1.0-rc.3",
56
56
  "react": "^19.1.1",
57
57
  "react-dom": "^19.1.1",
58
- "rolldown": "1.0.0-beta.34",
59
- "tsdown": "^0.14.2",
58
+ "rolldown": "1.0.0-beta.38",
59
+ "tsdown": "^0.15.4",
60
60
  "vitest": "^3.2.4"
61
61
  }
62
62
  }