@vitejs/plugin-react 6.1.1 → 6.1.2

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.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Plugin } from "vite";
2
2
  import { ReactCompilerBabelPluginOptions, ReactCompilerOptions, RolldownBabelPreset } from "#optionalTypes";
3
3
  //#region src/reactCompilerPreset.d.ts
4
- declare const reactCompilerPreset: (options?: ReactCompilerBabelPluginOptions) => RolldownBabelPreset;
4
+ export declare const reactCompilerPreset: (options?: ReactCompilerBabelPluginOptions) => RolldownBabelPreset;
5
5
  //#endregion
6
6
  //#region src/index.d.ts
7
7
  interface ReactCompilerPluginOptions extends ReactCompilerOptions {
@@ -9,10 +9,11 @@ interface ReactCompilerPluginOptions extends ReactCompilerOptions {
9
9
  * Log recoverable React Compiler diagnostics through Vite.
10
10
  * Fatal diagnostics are always logged and fail the transform.
11
11
  * @default false
12
+ * @deprecated Use `reportDiagnostics` instead
12
13
  */
13
14
  logDiagnostics?: boolean;
14
15
  }
15
- interface Options {
16
+ export interface Options {
16
17
  /**
17
18
  * Can be used to process extra files like `.mdx`
18
19
  * @example include: /\.(mdx|js|jsx|ts|tsx)$/
@@ -59,4 +60,4 @@ declare namespace viteReact {
59
60
  }
60
61
  declare function viteReactForCjs(this: unknown, options: Options): Plugin[];
61
62
  //#endregion
62
- export { Options, type ReactCompilerPluginOptions as ReactCompilerOptions, viteReact as default, viteReactForCjs as "module.exports", reactCompilerPreset };
63
+ export { type ReactCompilerPluginOptions as ReactCompilerOptions, viteReact as default, viteReactForCjs as "module.exports" };
package/dist/index.js CHANGED
@@ -198,6 +198,9 @@ function createReactCompilerPlugin({ logDiagnostics, ...reactCompilerOptions },
198
198
  let jsxDevelopment = false;
199
199
  let compiler;
200
200
  const runtime = reactCompilerOptions.target === "17" || reactCompilerOptions.target === "18" ? "react-compiler-runtime" : "react/compiler-runtime";
201
+ const jsxImportSource = reactOptions.jsxImportSource ?? "react";
202
+ const jsxImportRuntime = `${jsxImportSource}/jsx-runtime`;
203
+ const jsxImportDevRuntime = `${jsxImportSource}/jsx-dev-runtime`;
201
204
  const loadCompiler = async (onError) => {
202
205
  if (compiler) return compiler;
203
206
  try {
@@ -222,7 +225,10 @@ function createReactCompilerPlugin({ logDiagnostics, ...reactCompilerOptions },
222
225
  exclude: makeIdFiltersToMatchWithQuery(exclude)
223
226
  } },
224
227
  async handler(code, id) {
228
+ const [filepath] = id.split("?");
229
+ const isJSX = filepath.endsWith("x");
225
230
  const isClient = this.environment?.config.consumer !== "server";
231
+ const refreshEnabled = isClient && isFastRefreshEnabled() && (isJSX || code.includes(jsxImportRuntime) || code.includes(jsxImportDevRuntime));
226
232
  const shouldCompile = isClient && (reactCompilerOptions.compilationMode === "annotation" ? /['"]use memo['"]/.test(code) : defaultCodeFilter.test(code));
227
233
  const { transform } = compiler ?? await loadCompiler((message) => this.error(message));
228
234
  const result = await transform(id.split("?")[0], code, {
@@ -230,14 +236,17 @@ function createReactCompilerPlugin({ logDiagnostics, ...reactCompilerOptions },
230
236
  runtime: reactOptions.jsxRuntime,
231
237
  development: jsxDevelopment,
232
238
  importSource: reactOptions.jsxImportSource,
233
- refresh: isClient && isFastRefreshEnabled()
239
+ refresh: refreshEnabled
234
240
  },
235
- reactCompiler: shouldCompile ? reactCompilerOptions : false,
241
+ reactCompiler: !shouldCompile ? false : logDiagnostics ? {
242
+ ...reactCompilerOptions,
243
+ reportDiagnostics: true
244
+ } : reactCompilerOptions,
236
245
  sourcemap: this.environment ? this.environment.config.command !== "build" || !!this.environment.config.build.sourcemap : true
237
246
  });
238
247
  const diagnostics = result.errors.map((error) => `${error.message}${error.codeframe ? `\n${error.codeframe}` : ""}`);
239
248
  if (result.fatal) this.error(diagnostics.join("\n\n") || "React Compiler transform failed.");
240
- if (logDiagnostics) for (const diagnostic of diagnostics) this.warn(diagnostic);
249
+ for (const diagnostic of diagnostics) this.warn(diagnostic);
241
250
  return {
242
251
  code: result.code,
243
252
  map: result.map
@@ -112,6 +112,29 @@ function canPreserveStateBetween(prevType, nextType) {
112
112
  if (isReactClass(prevType) || isReactClass(nextType)) {
113
113
  return false
114
114
  }
115
+ // A fiber's tag is derived from the kind of its type (a plain function
116
+ // vs memo vs forwardRef), and the reconciler can only swap implementations
117
+ // in place within the same tag. If the kind changed, the tree must remount.
118
+ if (typeof prevType !== typeof nextType) {
119
+ return false
120
+ }
121
+ if (typeof prevType === 'object' && prevType !== null && nextType !== null) {
122
+ if (
123
+ getProperty(prevType, '$$typeof') !== getProperty(nextType, '$$typeof')
124
+ ) {
125
+ return false
126
+ }
127
+ // Switching from SimpleMemoComponent to MemoComponent requires a remount;
128
+ // for symmetry, remount for the reverse too.
129
+ if (getProperty(prevType, '$$typeof') === REACT_MEMO_TYPE) {
130
+ if (
131
+ (getProperty(prevType, 'compare') === null) !==
132
+ (getProperty(nextType, 'compare') === null)
133
+ ) {
134
+ return false
135
+ }
136
+ }
137
+ }
115
138
  if (haveEqualSignatures(prevType, nextType)) {
116
139
  return true
117
140
  }
@@ -609,50 +632,49 @@ export function validateRefreshBoundaryAndEnqueueUpdate(
609
632
  prevExports,
610
633
  nextExports,
611
634
  ) {
635
+ let hasExports = false
612
636
  const ignoredExports = window.__getReactRefreshIgnoredExports?.({ id }) ?? []
613
- if (
614
- predicateOnExport(
615
- ignoredExports,
616
- prevExports,
617
- (key) => key in nextExports,
618
- ) !== true
619
- ) {
620
- return 'Could not Fast Refresh (export removed)'
621
- }
622
- if (
623
- predicateOnExport(
624
- ignoredExports,
625
- nextExports,
626
- (key) => key in prevExports,
627
- ) !== true
628
- ) {
629
- return 'Could not Fast Refresh (new export)'
630
- }
631
637
 
632
- let hasExports = false
633
- const allExportsAreComponentsOrUnchanged = predicateOnExport(
634
- ignoredExports,
635
- nextExports,
636
- (key, value) => {
637
- hasExports = true
638
- if (isLikelyComponentType(value)) return true
639
- if (isCompoundComponent(value)) return true
640
- return prevExports[key] === nextExports[key]
641
- },
642
- )
643
- if (hasExports && allExportsAreComponentsOrUnchanged === true) {
644
- enqueueUpdate()
645
- } else {
646
- return `Could not Fast Refresh ("${allExportsAreComponentsOrUnchanged}" export is incompatible). Learn more at __README_URL__#consistent-components-exports`
638
+ for (const key in prevExports) {
639
+ if (ignoredExports.includes(key)) continue
640
+ if (!(key in nextExports)) {
641
+ return `Could not Fast Refresh (export "${key}" removed)`
642
+ }
647
643
  }
648
- }
649
644
 
650
- function predicateOnExport(ignoredExports, moduleExports, predicate) {
651
- for (const key in moduleExports) {
645
+ for (const key in nextExports) {
652
646
  if (ignoredExports.includes(key)) continue
653
- if (!predicate(key, moduleExports[key])) return key
647
+ hasExports = true
648
+ if (!(key in prevExports)) {
649
+ return `Could not Fast Refresh (export "${key}" added)`
650
+ }
651
+ if (isLikelyComponentType(nextExports[key])) continue
652
+ if (isCompoundComponent(nextExports[key])) {
653
+ if (!isCompoundComponent(prevExports[key])) {
654
+ return `Could not Fast Refresh (compound component "${key}" added)`
655
+ }
656
+ for (const subKey in prevExports[key]) {
657
+ if (!(subKey in nextExports[key])) {
658
+ return `Could not Fast Refresh (compound component "${key}.${subKey}" removed)`
659
+ }
660
+ }
661
+ for (const subKey in nextExports[key]) {
662
+ if (!(subKey in prevExports[key])) {
663
+ return `Could not Fast Refresh (compound component "${key}.${subKey}" added)`
664
+ }
665
+ }
666
+ continue
667
+ }
668
+ if (prevExports[key] !== nextExports[key]) {
669
+ return `Could not Fast Refresh ("${key}" export is incompatible). Learn more at __README_URL__#consistent-components-exports`
670
+ }
671
+ }
672
+
673
+ if (hasExports) {
674
+ enqueueUpdate()
675
+ } else {
676
+ return `No exports`
654
677
  }
655
- return true
656
678
  }
657
679
 
658
680
  // Hides vite-ignored dynamic import so that Vite can skip analysis if no other
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-react",
3
- "version": "6.1.1",
3
+ "version": "6.1.2",
4
4
  "description": "The default Vite plugin for React projects",
5
5
  "keywords": [
6
6
  "fast refresh",
@@ -46,21 +46,20 @@
46
46
  "@rolldown/pluginutils": "^1.0.1"
47
47
  },
48
48
  "devDependencies": {
49
- "@babel/core": "8.0.1",
50
- "@rolldown/plugin-babel": "^0.2.3",
49
+ "@rolldown/plugin-babel": "^0.2.4",
51
50
  "@vitejs/react-common": "workspace:*",
52
51
  "babel-plugin-react-compiler": "^1.0.0",
53
- "oxc-transform-react": "^0.147.0",
54
- "react": "^19.2.8",
55
- "react-dom": "^19.2.8",
56
- "rolldown": "^1.2.6",
57
- "tsdown": "^0.22.14",
58
- "vite": "^8.2.2"
52
+ "oxc-transform-react": "^0.152.0",
53
+ "react": "^19.3.0",
54
+ "react-dom": "^19.3.0",
55
+ "rolldown": "^1.2.12",
56
+ "tsdown": "^0.23.0",
57
+ "vite": "^8.3.2"
59
58
  },
60
59
  "peerDependencies": {
61
60
  "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0",
62
61
  "babel-plugin-react-compiler": "^1.0.0",
63
- "oxc-transform-react": "^0.145.0",
62
+ "oxc-transform-react": "^0.152.0",
64
63
  "vite": "^8.0.0"
65
64
  },
66
65
  "peerDependenciesMeta": {