vinext 1.1.0 → 1.2.1

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.
Files changed (288) hide show
  1. package/README.md +22 -10
  2. package/dist/build/client-build-config.d.ts +10 -0
  3. package/dist/build/client-build-config.js +18 -2
  4. package/dist/build/output-root-externals.d.ts +21 -0
  5. package/dist/build/output-root-externals.js +40 -0
  6. package/dist/build/pages-client-assets-module.d.ts +8 -0
  7. package/dist/build/pages-client-assets-module.js +21 -1
  8. package/dist/build/prerender-paths.js +6 -4
  9. package/dist/build/prerender.js +1 -1
  10. package/dist/build/run-prerender.js +1 -1
  11. package/dist/build/ssr-manifest.d.ts +2 -0
  12. package/dist/build/ssr-manifest.js +6 -2
  13. package/dist/check.js +12 -12
  14. package/dist/cli-dev-config.js +3 -3
  15. package/dist/cli.js +3 -2
  16. package/dist/client/client-redirect-matcher.d.ts +14 -0
  17. package/dist/client/client-redirect-matcher.js +37 -0
  18. package/dist/client/client-redirects.d.ts +27 -0
  19. package/dist/client/client-redirects.js +28 -0
  20. package/dist/client/client-rewrites.d.ts +2 -1
  21. package/dist/client/client-rewrites.js +1 -1
  22. package/dist/config/config-matchers.d.ts +26 -11
  23. package/dist/config/config-matchers.js +90 -88
  24. package/dist/config/destination-params.d.ts +47 -0
  25. package/dist/config/destination-params.js +116 -0
  26. package/dist/config/next-config.d.ts +7 -0
  27. package/dist/config/next-config.js +3 -0
  28. package/dist/entries/app-rsc-entry.d.ts +4 -0
  29. package/dist/entries/app-rsc-entry.js +20 -6
  30. package/dist/entries/pages-client-entry.js +3 -1
  31. package/dist/entries/pages-server-entry.js +13 -37
  32. package/dist/index.d.ts +3 -1
  33. package/dist/index.js +246 -136
  34. package/dist/init-cloudflare.d.ts +9 -0
  35. package/dist/init-cloudflare.js +107 -31
  36. package/dist/init-platform.d.ts +4 -0
  37. package/dist/init-platform.js +27 -2
  38. package/dist/init.d.ts +2 -1
  39. package/dist/init.js +153 -9
  40. package/dist/plugins/ast-scope.d.ts +7 -0
  41. package/dist/plugins/ast-scope.js +59 -3
  42. package/dist/plugins/ast-utils.d.ts +53 -2
  43. package/dist/plugins/ast-utils.js +90 -2
  44. package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
  45. package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
  46. package/dist/plugins/commonjs-esm-facade.js +2 -2
  47. package/dist/plugins/css-module-imports.js +13 -20
  48. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  49. package/dist/plugins/dynamic-preload-metadata.js +11 -11
  50. package/dist/plugins/extensionless-dynamic-import.js +2 -3
  51. package/dist/plugins/fonts.d.ts +1 -1
  52. package/dist/plugins/fonts.js +3 -3
  53. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  54. package/dist/plugins/ignore-dynamic-requests.js +5 -7
  55. package/dist/plugins/import-meta-url.js +3 -4
  56. package/dist/plugins/instrumentation-client.js +3 -2
  57. package/dist/plugins/middleware-export-validation.js +2 -3
  58. package/dist/plugins/middleware-server-only.d.ts +5 -4
  59. package/dist/plugins/middleware-server-only.js +8 -5
  60. package/dist/plugins/og-harfbuzz.js +2 -3
  61. package/dist/plugins/optimize-imports.js +3 -4
  62. package/dist/plugins/pages-node-externals.js +3 -4
  63. package/dist/plugins/remove-console.js +2 -18
  64. package/dist/plugins/require-condition-resolution.js +3 -3
  65. package/dist/plugins/require-context.js +2 -3
  66. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  67. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  68. package/dist/plugins/strip-server-exports.js +265 -102
  69. package/dist/plugins/styled-jsx.js +2 -3
  70. package/dist/plugins/transform-result.d.ts +9 -5
  71. package/dist/plugins/transitive-externals.js +1 -1
  72. package/dist/plugins/typeof-window.d.ts +2 -2
  73. package/dist/plugins/use-cache-callable.d.ts +21 -2
  74. package/dist/plugins/use-cache-callable.js +84 -35
  75. package/dist/plugins/worker-image-imports.js +30 -33
  76. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  77. package/dist/plugins/worker-server-only-imports.js +31 -0
  78. package/dist/plugins/worker-use-server.d.ts +25 -0
  79. package/dist/plugins/worker-use-server.js +153 -0
  80. package/dist/server/api-handler.d.ts +1 -0
  81. package/dist/server/api-handler.js +3 -2
  82. package/dist/server/app-action-forwarding.js +2 -2
  83. package/dist/server/app-browser-action-result.d.ts +1 -1
  84. package/dist/server/app-browser-action-result.js +9 -2
  85. package/dist/server/app-browser-entry.js +3 -3
  86. package/dist/server/app-browser-interception-context.js +1 -1
  87. package/dist/server/app-browser-navigation-controller.js +1 -1
  88. package/dist/server/app-browser-prefetch-response.js +2 -2
  89. package/dist/server/app-browser-server-action-client.js +1 -1
  90. package/dist/server/app-browser-state.js +1 -1
  91. package/dist/server/app-browser-supplemental-refresh.js +1 -1
  92. package/dist/server/app-middleware.d.ts +11 -0
  93. package/dist/server/app-middleware.js +17 -2
  94. package/dist/server/app-optimistic-routing.js +1 -1
  95. package/dist/server/app-page-cache.d.ts +1 -1
  96. package/dist/server/app-page-cache.js +1 -1
  97. package/dist/server/app-page-dispatch.d.ts +3 -1
  98. package/dist/server/app-page-dispatch.js +5 -4
  99. package/dist/server/app-page-ppr-runtime.js +1 -1
  100. package/dist/server/app-page-render-observation.js +1 -1
  101. package/dist/server/app-page-render.js +1 -1
  102. package/dist/server/app-page-request.js +53 -15
  103. package/dist/server/app-page-route-wiring.js +2 -2
  104. package/dist/server/app-pages-bridge.d.ts +1 -1
  105. package/dist/server/app-pages-bridge.js +3 -4
  106. package/dist/server/app-prerender-endpoints.js +9 -6
  107. package/dist/server/app-render-abort-error.d.ts +19 -0
  108. package/dist/server/app-render-abort-error.js +31 -1
  109. package/dist/server/app-request-stage-dispatch.js +6 -2
  110. package/dist/server/app-request-stage-independent-entry.js +29 -9
  111. package/dist/server/app-response-stage-entry.js +11 -3
  112. package/dist/server/app-route-handler-cache.d.ts +1 -0
  113. package/dist/server/app-route-handler-cache.js +1 -0
  114. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  115. package/dist/server/app-route-handler-dispatch.js +5 -2
  116. package/dist/server/app-route-handler-execution.d.ts +1 -0
  117. package/dist/server/app-route-handler-execution.js +1 -0
  118. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  119. package/dist/server/app-route-handler-runtime.js +46 -25
  120. package/dist/server/app-router-entry.js +29 -10
  121. package/dist/server/app-rsc-cache-busting.d.ts +16 -0
  122. package/dist/server/app-rsc-cache-busting.js +30 -13
  123. package/dist/server/app-rsc-errors.js +20 -16
  124. package/dist/server/app-rsc-handler.d.ts +7 -0
  125. package/dist/server/app-rsc-handler.js +89 -39
  126. package/dist/server/app-rsc-request-normalization.js +3 -3
  127. package/dist/server/app-rsc-response-stage.js +5 -3
  128. package/dist/server/app-segment-config.d.ts +2 -1
  129. package/dist/server/app-server-action-execution.d.ts +2 -1
  130. package/dist/server/app-server-action-execution.js +62 -23
  131. package/dist/server/app-ssr-entry.js +7 -5
  132. package/dist/server/app-visited-response-cache.js +2 -2
  133. package/dist/server/app-worker-stages.d.ts +5 -0
  134. package/dist/server/app-worker-stages.js +1 -1
  135. package/dist/server/cacheability-request.js +2 -2
  136. package/dist/server/client-build-files.d.ts +16 -0
  137. package/dist/server/client-build-files.js +36 -0
  138. package/dist/server/client-reuse-manifest.js +1 -1
  139. package/dist/server/config-headers.js +1 -1
  140. package/dist/server/defer-until-stream-consumed.d.ts +2 -1
  141. package/dist/server/defer-until-stream-consumed.js +3 -1
  142. package/dist/server/dev-server.js +39 -28
  143. package/dist/server/dev-stack-sourcemap.js +18 -23
  144. package/dist/server/document-initial-head.d.ts +0 -11
  145. package/dist/server/document-initial-head.js +1 -1
  146. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  147. package/dist/server/forwarded-middleware-context.js +22 -0
  148. package/dist/server/headers.d.ts +4 -1
  149. package/dist/server/headers.js +4 -1
  150. package/dist/server/http-conditional.d.ts +11 -0
  151. package/dist/server/http-conditional.js +10 -1
  152. package/dist/server/http-error-responses.d.ts +1 -1
  153. package/dist/server/image-optimization.d.ts +38 -0
  154. package/dist/server/image-optimization.js +94 -4
  155. package/dist/server/isr-cache.d.ts +10 -0
  156. package/dist/server/isr-cache.js +41 -6
  157. package/dist/server/metadata-route-response.js +11 -10
  158. package/dist/server/middleware-matcher.d.ts +2 -0
  159. package/dist/server/middleware-matcher.js +23 -2
  160. package/dist/server/middleware-path-to-regexp.js +1 -1
  161. package/dist/server/middleware-runtime.d.ts +13 -0
  162. package/dist/server/middleware-runtime.js +38 -25
  163. package/dist/server/middleware.d.ts +1 -1
  164. package/dist/server/middleware.js +3 -1
  165. package/dist/server/multi-stage.d.ts +11 -0
  166. package/dist/server/navigation-planner.js +1 -1
  167. package/dist/server/normalize-path.d.ts +0 -13
  168. package/dist/server/normalize-path.js +1 -34
  169. package/dist/server/open-redirect.d.ts +11 -4
  170. package/dist/server/open-redirect.js +11 -4
  171. package/dist/server/pages-api-route.d.ts +3 -2
  172. package/dist/server/pages-api-route.js +6 -5
  173. package/dist/server/pages-cache-tag.d.ts +12 -0
  174. package/dist/server/pages-cache-tag.js +19 -0
  175. package/dist/server/pages-client-assets.d.ts +2 -0
  176. package/dist/server/pages-data-route.d.ts +10 -0
  177. package/dist/server/pages-data-route.js +21 -3
  178. package/dist/server/pages-document-asset-props.d.ts +5 -1
  179. package/dist/server/pages-document-asset-props.js +13 -5
  180. package/dist/server/pages-document-splice.d.ts +19 -0
  181. package/dist/server/pages-document-splice.js +55 -0
  182. package/dist/server/pages-i18n.d.ts +12 -1
  183. package/dist/server/pages-i18n.js +18 -4
  184. package/dist/server/pages-node-compat.d.ts +16 -5
  185. package/dist/server/pages-node-compat.js +20 -12
  186. package/dist/server/pages-page-data.d.ts +32 -24
  187. package/dist/server/pages-page-data.js +51 -121
  188. package/dist/server/pages-page-handler.d.ts +0 -6
  189. package/dist/server/pages-page-handler.js +189 -127
  190. package/dist/server/pages-page-response.d.ts +12 -6
  191. package/dist/server/pages-page-response.js +42 -35
  192. package/dist/server/pages-request-pipeline.d.ts +10 -2
  193. package/dist/server/pages-request-pipeline.js +41 -22
  194. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  195. package/dist/server/pages-request-stage-entry.js +75 -16
  196. package/dist/server/pages-response-stage-entry.js +4 -0
  197. package/dist/server/pages-revalidate.js +3 -3
  198. package/dist/server/pages-router-entry.js +5 -4
  199. package/dist/server/prerender-manifest.d.ts +3 -3
  200. package/dist/server/prerender-manifest.js +4 -3
  201. package/dist/server/prerender-work-unit-setup.js +4 -0
  202. package/dist/server/prod-server.d.ts +12 -0
  203. package/dist/server/prod-server.js +204 -74
  204. package/dist/server/proper-error.d.ts +4 -0
  205. package/dist/server/proper-error.js +31 -0
  206. package/dist/server/request-pipeline.d.ts +4 -1
  207. package/dist/server/request-pipeline.js +3 -2
  208. package/dist/server/revalidation-request.d.ts +1 -0
  209. package/dist/server/revalidation-request.js +1 -1
  210. package/dist/server/rsc-stream-hints.d.ts +1 -1
  211. package/dist/server/rsc-stream-hints.js +52 -5
  212. package/dist/server/seed-cache.d.ts +1 -0
  213. package/dist/server/seed-cache.js +5 -4
  214. package/dist/server/server-reference-loader.d.ts +4 -0
  215. package/dist/server/server-reference-loader.js +29 -0
  216. package/dist/server/socket-error-backstop.d.ts +9 -1
  217. package/dist/server/socket-error-backstop.js +46 -17
  218. package/dist/server/static-file-signal.d.ts +15 -4
  219. package/dist/server/static-file-signal.js +46 -12
  220. package/dist/server/worker-image-optimization.d.ts +34 -0
  221. package/dist/server/worker-image-optimization.js +99 -0
  222. package/dist/server/worker-stages.d.ts +1 -1
  223. package/dist/server/worker-stages.js +2 -2
  224. package/dist/server/worker-utils.d.ts +8 -3
  225. package/dist/server/worker-utils.js +12 -7
  226. package/dist/shims/app-router-scroll.js +4 -1
  227. package/dist/shims/app-router-tree-context.d.ts +5 -0
  228. package/dist/shims/app-router-tree-context.js +27 -0
  229. package/dist/shims/cache-callable-runtime.d.ts +4 -2
  230. package/dist/shims/cache-callable-runtime.js +21 -12
  231. package/dist/shims/cache-handler.js +1 -9
  232. package/dist/shims/cache-runtime.d.ts +6 -1
  233. package/dist/shims/cache-runtime.js +2 -1
  234. package/dist/shims/cache.d.ts +2 -2
  235. package/dist/shims/cache.js +40 -13
  236. package/dist/shims/cdn-cache.d.ts +8 -0
  237. package/dist/shims/cdn-cache.js +17 -1
  238. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  239. package/dist/shims/disable-smooth-scroll.js +36 -0
  240. package/dist/shims/document-placeholders.d.ts +19 -0
  241. package/dist/shims/document-placeholders.js +45 -0
  242. package/dist/shims/document.js +21 -5
  243. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  244. package/dist/shims/dynamic-preload-chunks.js +13 -9
  245. package/dist/shims/dynamic.d.ts +1 -1
  246. package/dist/shims/dynamic.js +60 -8
  247. package/dist/shims/fetch-cache-state.d.ts +66 -0
  248. package/dist/shims/fetch-cache-state.js +92 -0
  249. package/dist/shims/fetch-cache.d.ts +3 -67
  250. package/dist/shims/fetch-cache.js +160 -125
  251. package/dist/shims/head.d.ts +10 -6
  252. package/dist/shims/head.js +16 -14
  253. package/dist/shims/headers.js +2 -2
  254. package/dist/shims/image.js +2 -1
  255. package/dist/shims/internal/hybrid-client-route-owner-direct.js +1 -1
  256. package/dist/shims/internal/hybrid-client-route-owner.js +1 -0
  257. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  258. package/dist/shims/internal/work-store-scope.js +24 -0
  259. package/dist/shims/link-prefetch.js +5 -4
  260. package/dist/shims/link.js +2 -2
  261. package/dist/shims/navigation.js +34 -9
  262. package/dist/shims/request-context.d.ts +2 -0
  263. package/dist/shims/request-state-types.d.ts +2 -1
  264. package/dist/shims/router.js +21 -32
  265. package/dist/shims/server.d.ts +27 -4
  266. package/dist/shims/server.js +65 -9
  267. package/dist/shims/unified-request-context.d.ts +1 -1
  268. package/dist/shims/url-utils.d.ts +9 -0
  269. package/dist/shims/url-utils.js +15 -4
  270. package/dist/utils/client-runtime-metadata.js +1 -1
  271. package/dist/utils/domain-locale.js +1 -1
  272. package/dist/utils/hash.d.ts +7 -0
  273. package/dist/utils/hash.js +11 -1
  274. package/dist/utils/package-name.d.ts +6 -0
  275. package/dist/utils/package-name.js +12 -1
  276. package/dist/utils/plugin-rsc-version.d.ts +6 -0
  277. package/dist/utils/plugin-rsc-version.js +41 -0
  278. package/dist/utils/prerender-output-paths.js +15 -4
  279. package/dist/utils/public-file-path.d.ts +10 -2
  280. package/dist/utils/public-file-path.js +13 -9
  281. package/dist/utils/public-routes.js +2 -2
  282. package/dist/utils/react-version.d.ts +10 -0
  283. package/dist/utils/react-version.js +39 -16
  284. package/package.json +11 -7
  285. package/dist/build/nitro-route-rules.d.ts +0 -47
  286. package/dist/build/nitro-route-rules.js +0 -79
  287. package/dist/plugins/cache-flight-codec.d.ts +0 -19
  288. package/dist/plugins/cache-flight-codec.js +0 -68
@@ -42,7 +42,7 @@ function getDomainLocaleUrl(url, locale, { basePath, currentHostname, domainItem
42
42
  const targetDomain = detectDomainLocale(domainItems, void 0, locale);
43
43
  if (!targetDomain) return void 0;
44
44
  const currentDomain = detectDomainLocale(domainItems, currentHostname ?? void 0);
45
- const localizedPath = addLocalePrefix(url, locale, targetDomain.defaultLocale);
45
+ const localizedPath = addLocalePrefix(/^[/?#]/.test(url) ? url : `/${url}`, locale, targetDomain.defaultLocale);
46
46
  if (currentDomain && normalizeDomainHostname(currentDomain.domain) === normalizeDomainHostname(targetDomain.domain)) return;
47
47
  return `${`http${targetDomain.http ? "" : "s"}://`}${targetDomain.domain}${prefixBasePath(localizedPath, basePath)}`;
48
48
  }
@@ -20,4 +20,11 @@ export declare function fnv1a64(input: string): string;
20
20
  * key format and produces different values. Do not swap one for the other.
21
21
  */
22
22
  export declare function fnv1a52(str: string): number;
23
+ /**
24
+ * Hex-encoded SHA-256 digest of a string's UTF-8 bytes, via Web Crypto so it
25
+ * runs unchanged in Node.js, Workers and browsers. Used for cache keys built
26
+ * from inputs a request can influence, where crafted inputs could collide
27
+ * under a non-cryptographic hash like `fnv1a64`.
28
+ */
29
+ export declare function sha256Hex(input: string): Promise<string>;
23
30
  //#endregion
@@ -51,5 +51,15 @@ function fnv1a52(str) {
51
51
  }
52
52
  return (v3 & 15) * 281474976710656 + v2 * 4294967296 + v1 * 65536 + (v0 ^ v3 >> 4);
53
53
  }
54
+ /**
55
+ * Hex-encoded SHA-256 digest of a string's UTF-8 bytes, via Web Crypto so it
56
+ * runs unchanged in Node.js, Workers and browsers. Used for cache keys built
57
+ * from inputs a request can influence, where crafted inputs could collide
58
+ * under a non-cryptographic hash like `fnv1a64`.
59
+ */
60
+ async function sha256Hex(input) {
61
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
62
+ return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("");
63
+ }
54
64
  //#endregion
55
- export { fnv1a52, fnv1a64 };
65
+ export { fnv1a52, fnv1a64, sha256Hex };
@@ -7,4 +7,10 @@ export declare const BARE_PACKAGE_SPECIFIER_RE: RegExp;
7
7
  * scoped names, and Node builtins are not npm package references.
8
8
  */
9
9
  export declare function packageNameFromSpecifier(specifier: string): string | null;
10
+ /**
11
+ * Turbopack's "foreign code" condition: a module under node_modules whose
12
+ * package is not in the (Turbopack) transpile list. Next.js skips its
13
+ * app-code transforms, such as next/dynamic, for foreign code.
14
+ */
15
+ export declare function isForeignNodeModule(id: string, transpiledPackages: readonly string[]): boolean;
10
16
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
1
2
  import { builtinModules } from "node:module";
2
3
  //#region src/utils/package-name.ts
3
4
  const BUILTIN_MODULES = new Set(builtinModules.flatMap((name) => name.startsWith("node:") ? [name, name.slice(5)] : [name, `node:${name}`]));
@@ -14,5 +15,15 @@ function packageNameFromSpecifier(specifier) {
14
15
  if (!packageName || BUILTIN_MODULES.has(packageName)) return null;
15
16
  return packageName;
16
17
  }
18
+ /**
19
+ * Turbopack's "foreign code" condition: a module under node_modules whose
20
+ * package is not in the (Turbopack) transpile list. Next.js skips its
21
+ * app-code transforms, such as next/dynamic, for foreign code.
22
+ */
23
+ function isForeignNodeModule(id, transpiledPackages) {
24
+ const normalizedId = toSlash(id);
25
+ if (!normalizedId.includes("/node_modules/")) return false;
26
+ return !transpiledPackages.some((packageName) => normalizedId.includes(`/node_modules/${packageName}/`));
27
+ }
17
28
  //#endregion
18
- export { BARE_PACKAGE_SPECIFIER_RE, packageNameFromSpecifier };
29
+ export { BARE_PACKAGE_SPECIFIER_RE, isForeignNodeModule, packageNameFromSpecifier };
@@ -0,0 +1,6 @@
1
+ //#region src/utils/plugin-rsc-version.d.ts
2
+ /** Return the installed @vitejs/plugin-rsc version, or throw if it is unsupported. */
3
+ export declare function assertPluginRscVersion(resolvedRscPath: string): string;
4
+ /** Whether the package owning `dir` must install its own react-server-dom-webpack. */
5
+ export declare function needsAppReactServerDom(dir: string, pluginRscVersion: string): boolean;
6
+ //#endregion
@@ -0,0 +1,41 @@
1
+ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
+ import { MINIMUM_REACT_VERSION, findPackageVersion, isVersionBelow } from "./react-version.js";
3
+ import { createRequire } from "node:module";
4
+ import fs from "node:fs";
5
+ //#region src/utils/plugin-rsc-version.ts
6
+ const MINIMUM_PLUGIN_RSC_VERSION = [
7
+ 0,
8
+ 5,
9
+ 37
10
+ ];
11
+ /** Return the installed @vitejs/plugin-rsc version, or throw if it is unsupported. */
12
+ function assertPluginRscVersion(resolvedRscPath) {
13
+ const version = findPackageVersion(resolvedRscPath, "@vitejs/plugin-rsc");
14
+ if (!version || isVersionBelow(version, MINIMUM_PLUGIN_RSC_VERSION)) throw new Error(`vinext: App Router requires @vitejs/plugin-rsc ${MINIMUM_PLUGIN_RSC_VERSION.join(".")} or newer (found ${version ?? "an unknown version"}). Upgrade @vitejs/plugin-rsc.`);
15
+ return version;
16
+ }
17
+ const FIRST_PLUGIN_RSC_WITH_SUPPORTED_RSDW = [
18
+ 0,
19
+ 5,
20
+ 38
21
+ ];
22
+ /** Whether the package owning `dir` must install its own react-server-dom-webpack. */
23
+ function needsAppReactServerDom(dir, pluginRscVersion) {
24
+ if (!isVersionBelow(pluginRscVersion, FIRST_PLUGIN_RSC_WITH_SUPPORTED_RSDW)) return false;
25
+ let manifest = path.join(dir, "package.json");
26
+ while (!fs.existsSync(manifest)) {
27
+ const parent = path.dirname(path.dirname(manifest));
28
+ if (parent === path.dirname(manifest)) return true;
29
+ manifest = path.join(parent, "package.json");
30
+ }
31
+ try {
32
+ const pkg = JSON.parse(fs.readFileSync(manifest, "utf-8"));
33
+ if (!pkg.dependencies?.["react-server-dom-webpack"] && !pkg.devDependencies?.["react-server-dom-webpack"]) return true;
34
+ const version = findPackageVersion(createRequire(manifest).resolve("react-server-dom-webpack"), "react-server-dom-webpack");
35
+ return !version || isVersionBelow(version, MINIMUM_REACT_VERSION);
36
+ } catch {
37
+ return true;
38
+ }
39
+ }
40
+ //#endregion
41
+ export { assertPluginRscVersion, needsAppReactServerDom };
@@ -1,11 +1,22 @@
1
1
  //#region src/utils/prerender-output-paths.ts
2
2
  /**
3
+ * Map a prerendered URL to the file path its artifacts are written under, as
4
+ * Next.js's `normalizePagePath` does. `/index` becomes `/index/index` (and
5
+ * `/index/foo` becomes `/index/index/foo`) so it never shares `/`'s files.
6
+ * Unlike Next.js, dynamic fallback-shell paths such as `/index/[slug]` are
7
+ * also prefixed; build and seed both use this mapping, so they stay in step.
8
+ * Source: https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/page-path/normalize-page-path.ts
9
+ */
10
+ function toOutputUrlPath(urlPath) {
11
+ return /^\/index(?:\/|$)/.test(urlPath) ? `/index${urlPath}` : urlPath;
12
+ }
13
+ /**
3
14
  * Determine the HTML output file path for a prerendered URL.
4
15
  * Respects trailingSlash config.
5
16
  */
6
17
  function getOutputPath(urlPath, trailingSlash, basePath = "") {
7
18
  if (urlPath === "/" && basePath === "") return "index.html";
8
- const clean = (basePath === "" ? urlPath : urlPath === "/" ? trailingSlash ? `${basePath}/` : basePath : `${basePath}${urlPath}`).replace(/^\//, "").replace(/\/$/, "");
19
+ const clean = (basePath === "" ? toOutputUrlPath(urlPath) : urlPath === "/" ? trailingSlash ? `${basePath}/` : basePath : `${basePath}${toOutputUrlPath(urlPath)}`).replace(/^\//, "").replace(/\/$/, "");
9
20
  if (trailingSlash) return `${clean}/index.html`;
10
21
  return `${clean}.html`;
11
22
  }
@@ -19,16 +30,16 @@ function getRscOutputPath(urlPath, options = {
19
30
  const cleanBasePath = options.basePath?.replace(/^\//, "");
20
31
  return cleanBasePath ? `${cleanBasePath}/index.txt` : "index.txt";
21
32
  }
22
- const clean = (options.basePath ? `${options.basePath}${urlPath}` : urlPath).replace(/^\//, "").replace(/\/$/, "");
33
+ const clean = `${options.basePath ?? ""}${toOutputUrlPath(urlPath)}`.replace(/^\//, "").replace(/\/$/, "");
23
34
  return options.trailingSlash ? `${clean}/index.txt` : `${clean}.txt`;
24
35
  }
25
36
  if (urlPath === "/") return "index.rsc";
26
- return urlPath.replace(/^\//, "") + ".rsc";
37
+ return toOutputUrlPath(urlPath).replace(/^\//, "") + ".rsc";
27
38
  }
28
39
  /** Determine the binary artifact path for a prerendered App Route response. */
29
40
  function getAppRouteOutputPath(urlPath) {
30
41
  if (urlPath === "/") return "index.route";
31
- return urlPath.replace(/^\//, "") + ".route";
42
+ return toOutputUrlPath(urlPath).replace(/^\//, "") + ".route";
32
43
  }
33
44
  //#endregion
34
45
  export { getAppRouteOutputPath, getOutputPath, getRscOutputPath };
@@ -1,4 +1,12 @@
1
1
  //#region src/utils/public-file-path.d.ts
2
- /** Precompute keys for both encoded requests and decoded proxy/dev variants. */
3
- export declare function publicFilePathVariants(pathname: string): string[];
2
+ /**
3
+ * Key a public file by the normalized pathname a request for it matches with.
4
+ *
5
+ * Request pathnames are decoded once per segment with path delimiters kept
6
+ * encoded, so `public/a b.txt` is `/a b.txt` and `public/C#.txt` is
7
+ * `/C%23.txt`. Keying only this form keeps a double-encoded alias such as
8
+ * `/a%2520b.txt`, which middleware matchers see as `/a%20b.txt`, from
9
+ * reaching `public/a b.txt`.
10
+ */
11
+ export declare function publicFileRouteKey(pathname: string): string;
4
12
  //#endregion
@@ -1,12 +1,16 @@
1
+ import { normalizePathnameForRouteMatch } from "../routing/utils.js";
1
2
  //#region src/utils/public-file-path.ts
2
- /** Encode each pathname segment without encoding `/` separators. */
3
- function encodePublicFilePath(pathname) {
4
- return pathname.split("/").map((segment) => encodeURIComponent(segment)).join("/");
5
- }
6
- /** Precompute keys for both encoded requests and decoded proxy/dev variants. */
7
- function publicFilePathVariants(pathname) {
8
- const encoded = encodePublicFilePath(pathname);
9
- return encoded === pathname ? [pathname] : [pathname, encoded];
3
+ /**
4
+ * Key a public file by the normalized pathname a request for it matches with.
5
+ *
6
+ * Request pathnames are decoded once per segment with path delimiters kept
7
+ * encoded, so `public/a b.txt` is `/a b.txt` and `public/C#.txt` is
8
+ * `/C%23.txt`. Keying only this form keeps a double-encoded alias such as
9
+ * `/a%2520b.txt`, which middleware matchers see as `/a%20b.txt`, from
10
+ * reaching `public/a b.txt`.
11
+ */
12
+ function publicFileRouteKey(pathname) {
13
+ return normalizePathnameForRouteMatch(pathname.split("/").map((segment) => encodeURIComponent(segment)).join("/"));
10
14
  }
11
15
  //#endregion
12
- export { publicFilePathVariants };
16
+ export { publicFileRouteKey };
@@ -1,5 +1,5 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
- import { publicFilePathVariants } from "./public-file-path.js";
2
+ import { publicFileRouteKey } from "./public-file-path.js";
3
3
  import fs from "node:fs";
4
4
  //#region src/utils/public-routes.ts
5
5
  function scanPublicFileRoutes(root, configuredPublicDir = "public") {
@@ -37,7 +37,7 @@ function scanPublicFileRoutes(root, configuredPublicDir = "public") {
37
37
  if (!stat.isFile()) continue;
38
38
  } else if (!entry.isFile()) continue;
39
39
  const relativePath = path.relative(publicDir, fullPath);
40
- routes.push(...publicFilePathVariants("/" + relativePath));
40
+ routes.push(publicFileRouteKey("/" + relativePath));
41
41
  }
42
42
  }
43
43
  if (fs.existsSync(publicDir)) try {
@@ -1,5 +1,15 @@
1
1
  //#region src/utils/react-version.d.ts
2
+ /**
3
+ * Lowest React accepted for App Router builds. react-server-dom-webpack 19.3.0
4
+ * shares typed-array buffers across Flight chunks, fixed in 19.3.1.
5
+ */
6
+ export declare const MINIMUM_REACT_VERSION: [number, number, number];
2
7
  export declare function getReactUpgradeDeps(root: string, options?: {
3
8
  fromManifest?: boolean;
9
+ installing?: boolean;
4
10
  }): string[];
11
+ export declare function reactUpgradeRequiredMessage(installCommand: string, upgrades: string[], pluginRscVersion?: string): string;
12
+ export declare function isVersionBelow(version: string, minimum: [number, number, number]): boolean;
13
+ /** Walk up from a resolved module entry to find its package version. */
14
+ export declare function findPackageVersion(resolvedEntry: string, packageName: string): string | null;
5
15
  //#endregion
@@ -12,17 +12,27 @@ function getDependencyUpgradeDeps(root, recommendations) {
12
12
  }
13
13
  return [];
14
14
  }
15
+ /**
16
+ * Lowest React accepted for App Router builds. react-server-dom-webpack 19.3.0
17
+ * shares typed-array buffers across Flight chunks, fixed in 19.3.1.
18
+ */
19
+ const MINIMUM_REACT_VERSION = [
20
+ 19,
21
+ 3,
22
+ 1
23
+ ];
15
24
  function getReactUpgradeDeps(root, options = {}) {
16
25
  if (options.fromManifest) {
17
26
  const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
18
- for (const name of ["react", "react-dom"]) {
27
+ for (const name of [
28
+ "react",
29
+ "react-dom",
30
+ "react-server-dom-webpack"
31
+ ]) {
19
32
  const declared = pkg.dependencies?.[name] ?? pkg.devDependencies?.[name];
20
- const version = /^[~^]?([0-9]+(?:\.[0-9]+){0,2}(?:-[0-9A-Za-z.*-]+)?)(?:\.[x*])?$/.exec(declared ?? "")?.[1];
21
- if (version && (version.includes("-") || isVersionBelow(version, [
22
- 19,
23
- 2,
24
- 6
25
- ]))) {
33
+ const version = (options.installing ? /^([0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?)$/ : /^[~^]?([0-9]+(?:\.[0-9]+){0,2}(?:-[0-9A-Za-z.*-]+)?)(?:\.[x*])?$/).exec(declared ?? "")?.[1];
34
+ const canary = !options.installing && version?.includes("-");
35
+ if (version && (canary || isVersionBelow(version, MINIMUM_REACT_VERSION))) {
26
36
  const upgrades = ["react@latest", "react-dom@latest"];
27
37
  const rsdw = pkg.dependencies?.["react-server-dom-webpack"] ?? pkg.devDependencies?.["react-server-dom-webpack"];
28
38
  if (rsdw && rsdw !== "latest") upgrades.push("react-server-dom-webpack@latest");
@@ -31,14 +41,27 @@ function getReactUpgradeDeps(root, options = {}) {
31
41
  }
32
42
  return [];
33
43
  }
34
- return getDependencyUpgradeDeps(root, { react: {
35
- minimumVersion: [
36
- 19,
37
- 2,
38
- 6
39
- ],
40
- upgrades: ["react@latest", "react-dom@latest"]
41
- } });
44
+ return getDependencyUpgradeDeps(root, {
45
+ "react-server-dom-webpack": {
46
+ minimumVersion: MINIMUM_REACT_VERSION,
47
+ upgrades: [
48
+ "react@latest",
49
+ "react-dom@latest",
50
+ "react-server-dom-webpack@latest"
51
+ ]
52
+ },
53
+ react: {
54
+ minimumVersion: MINIMUM_REACT_VERSION,
55
+ upgrades: ["react@latest", "react-dom@latest"]
56
+ },
57
+ "react-dom": {
58
+ minimumVersion: MINIMUM_REACT_VERSION,
59
+ upgrades: ["react@latest", "react-dom@latest"]
60
+ }
61
+ });
62
+ }
63
+ function reactUpgradeRequiredMessage(installCommand, upgrades, pluginRscVersion) {
64
+ return `vinext: App Router requires react, react-dom, and react-server-dom-webpack ${MINIMUM_REACT_VERSION.join(".")} or later.\n` + (pluginRscVersion ? `@vitejs/plugin-rsc ${pluginRscVersion} bundles an older react-server-dom-webpack, so install the latest in your app.\n` : "") + `Run: ${installCommand} ${upgrades.join(" ")}`;
42
65
  }
43
66
  function isVersionBelow(version, minimum) {
44
67
  const current = version.split(".").map((part) => parseInt(part, 10));
@@ -59,4 +82,4 @@ function findPackageVersion(resolvedEntry, packageName) {
59
82
  return null;
60
83
  }
61
84
  //#endregion
62
- export { getReactUpgradeDeps };
85
+ export { MINIMUM_REACT_VERSION, findPackageVersion, getReactUpgradeDeps, isVersionBelow, reactUpgradeRequiredMessage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinext",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "homepage": "https://vinext.dev/",
6
6
  "license": "MIT",
@@ -98,6 +98,10 @@
98
98
  "types": "./dist/server/headers.d.ts",
99
99
  "import": "./dist/server/headers.js"
100
100
  },
101
+ "./internal/server/http-conditional": {
102
+ "types": "./dist/server/http-conditional.d.ts",
103
+ "import": "./dist/server/http-conditional.js"
104
+ },
101
105
  "./internal/server/isr-cache": {
102
106
  "types": "./dist/server/isr-cache.d.ts",
103
107
  "import": "./dist/server/isr-cache.js"
@@ -234,12 +238,12 @@
234
238
  "@types/react-dom": "^19.2.3",
235
239
  "@types/ua-parser-js": "0.7.36",
236
240
  "@vitejs/plugin-react": "^6.1.0",
237
- "@vitejs/plugin-rsc": "^0.5.34",
241
+ "@vitejs/plugin-rsc": "^0.5.38",
238
242
  "am-i-vibing": "^0.5.0",
239
243
  "ignore": "5.3.2",
240
244
  "image-size": "2.0.2",
241
245
  "pathslash": "^0.1.0",
242
- "react-server-dom-webpack": "^19.2.7",
246
+ "react-server-dom-webpack": "^19.3.1",
243
247
  "ua-parser-js": "1.0.35",
244
248
  "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
245
249
  "vite-plus": "1.1.0"
@@ -247,10 +251,10 @@
247
251
  "peerDependencies": {
248
252
  "@mdx-js/rollup": "^3.0.0",
249
253
  "@vitejs/plugin-react": "^5.1.4 || ^6.0.0",
250
- "@vitejs/plugin-rsc": "^0.5.34",
251
- "react": "^19.2.6",
252
- "react-dom": "^19.2.6",
253
- "react-server-dom-webpack": "^19.2.6",
254
+ "@vitejs/plugin-rsc": "^0.5.37",
255
+ "react": "^19.3.1",
256
+ "react-dom": "^19.3.1",
257
+ "react-server-dom-webpack": "^19.3.1",
254
258
  "vite": "^8.0.0"
255
259
  },
256
260
  "peerDependenciesMeta": {
@@ -1,47 +0,0 @@
1
- import { RouteRow } from "./report.js";
2
- //#region src/build/nitro-route-rules.d.ts
3
- export type NitroRouteRuleConfig = Record<string, unknown> & {
4
- swr?: boolean | number;
5
- cache?: unknown;
6
- static?: boolean;
7
- isr?: boolean | number;
8
- prerender?: boolean;
9
- };
10
- type NitroRouteRules = Record<string, {
11
- swr: number;
12
- }>;
13
- /**
14
- * Scans the filesystem for route files and generates Nitro `routeRules` for ISR routes.
15
- *
16
- * Note: this duplicates the filesystem scanning that `printBuildReport` also performs.
17
- * The `nitro.setup` hook runs during Nitro initialization (before the build), while
18
- * `printBuildReport` runs after the build, so sharing results is non-trivial. This is
19
- * a future optimization target.
20
- *
21
- * Unlike `printBuildReport`, this path does not receive `prerenderResult`, so routes
22
- * classified as `unknown` by static analysis (which `printBuildReport` might upgrade
23
- * to `static` via speculative prerender) are skipped here.
24
- */
25
- export declare function collectNitroRouteRules(options: {
26
- appDir?: string | null;
27
- pagesDir?: string | null;
28
- pageExtensions: string[];
29
- }): Promise<NitroRouteRules>;
30
- export declare function generateNitroRouteRules(rows: RouteRow[]): NitroRouteRules;
31
- /**
32
- * Converts vinext's internal `:param` route syntax to Nitro's rou3
33
- * pattern format. Nitro uses `rou3` for routeRules matching, which
34
- * supports `*` (single-segment) and `**` (multi-segment) wildcards.
35
- *
36
- * /blog/:slug -> /blog/* (single segment)
37
- * /docs/:slug+ -> /docs/** (one or more segments — catch-all)
38
- * /docs/:slug* -> /docs/** (zero or more segments — optional catch-all)
39
- * /about -> /about (unchanged)
40
- * /:a/:b produces `/*`/`/*` (consecutive single-segment params)
41
- */
42
- export declare function convertToNitroPattern(pattern: string): string;
43
- export declare function mergeNitroRouteRules(existingRouteRules: Record<string, NitroRouteRuleConfig> | undefined, generatedRouteRules: NitroRouteRules): {
44
- routeRules: Record<string, NitroRouteRuleConfig>;
45
- skippedRoutes: string[];
46
- };
47
- //#endregion
@@ -1,79 +0,0 @@
1
- import { appRouter } from "../routing/app-router.js";
2
- import { apiRouter, pagesRouter } from "../routing/pages-router.js";
3
- import { buildReportRows } from "./report.js";
4
- //#region src/build/nitro-route-rules.ts
5
- /**
6
- * Scans the filesystem for route files and generates Nitro `routeRules` for ISR routes.
7
- *
8
- * Note: this duplicates the filesystem scanning that `printBuildReport` also performs.
9
- * The `nitro.setup` hook runs during Nitro initialization (before the build), while
10
- * `printBuildReport` runs after the build, so sharing results is non-trivial. This is
11
- * a future optimization target.
12
- *
13
- * Unlike `printBuildReport`, this path does not receive `prerenderResult`, so routes
14
- * classified as `unknown` by static analysis (which `printBuildReport` might upgrade
15
- * to `static` via speculative prerender) are skipped here.
16
- */
17
- async function collectNitroRouteRules(options) {
18
- const { appDir, pageExtensions, pagesDir } = options;
19
- let appRoutes = [];
20
- let pageRoutes = [];
21
- let apiRoutes = [];
22
- if (appDir) appRoutes = await appRouter(appDir, pageExtensions);
23
- if (pagesDir) {
24
- const [pages, apis] = await Promise.all([pagesRouter(pagesDir, pageExtensions), apiRouter(pagesDir, pageExtensions)]);
25
- pageRoutes = pages;
26
- apiRoutes = apis;
27
- }
28
- return generateNitroRouteRules(buildReportRows({
29
- appRoutes,
30
- pageRoutes,
31
- apiRoutes
32
- }));
33
- }
34
- function generateNitroRouteRules(rows) {
35
- const rules = {};
36
- for (const row of rows) if (row.type === "isr" && typeof row.revalidate === "number" && Number.isFinite(row.revalidate) && row.revalidate > 0) rules[convertToNitroPattern(row.pattern)] = { swr: row.revalidate };
37
- return rules;
38
- }
39
- /**
40
- * Converts vinext's internal `:param` route syntax to Nitro's rou3
41
- * pattern format. Nitro uses `rou3` for routeRules matching, which
42
- * supports `*` (single-segment) and `**` (multi-segment) wildcards.
43
- *
44
- * /blog/:slug -> /blog/* (single segment)
45
- * /docs/:slug+ -> /docs/** (one or more segments — catch-all)
46
- * /docs/:slug* -> /docs/** (zero or more segments — optional catch-all)
47
- * /about -> /about (unchanged)
48
- * /:a/:b produces `/*`/`/*` (consecutive single-segment params)
49
- */
50
- function convertToNitroPattern(pattern) {
51
- return pattern.split("/").map((segment) => {
52
- if (segment.startsWith(":")) return segment.endsWith("+") || segment.endsWith("*") ? "**" : "*";
53
- return segment;
54
- }).join("/");
55
- }
56
- function mergeNitroRouteRules(existingRouteRules, generatedRouteRules) {
57
- const routeRules = { ...existingRouteRules };
58
- const skippedRoutes = [];
59
- for (const [route, generatedRule] of Object.entries(generatedRouteRules)) {
60
- const existingRule = routeRules[route];
61
- if (existingRule && hasUserDefinedCacheRule(existingRule)) {
62
- skippedRoutes.push(route);
63
- continue;
64
- }
65
- routeRules[route] = {
66
- ...existingRule,
67
- ...generatedRule
68
- };
69
- }
70
- return {
71
- routeRules,
72
- skippedRoutes
73
- };
74
- }
75
- function hasUserDefinedCacheRule(rule) {
76
- return rule.swr !== void 0 || rule.cache !== void 0 || rule.static !== void 0 || rule.isr !== void 0 || rule.prerender !== void 0;
77
- }
78
- //#endregion
79
- export { collectNitroRouteRules, convertToNitroPattern, generateNitroRouteRules, mergeNitroRouteRules };
@@ -1,19 +0,0 @@
1
- import { MagicStringTransformResult } from "./transform-result.js";
2
- import { Plugin } from "vite";
3
- //#region src/plugins/cache-flight-codec.d.ts
4
- /**
5
- * Version of the Flight codec package that owns `id`. plugin-rsc resolves the
6
- * app's own react-server-dom-webpack when installed and its vendored copy
7
- * otherwise; reading the codec file's own package.json follows that choice.
8
- */
9
- export declare function readFlightCodecVersion(id: string): string;
10
- /**
11
- * Backport React 19.3's root-element temporary reference branch to older Flight
12
- * codecs, so a "use cache" argument like `Promise<ReactElement>` encodes as a
13
- * temporary reference instead of throwing. Remove it once React 19.3 is the
14
- * minimum supported version.
15
- * https://github.com/facebook/react/blob/v19.3.0/packages/react-client/src/ReactFlightReplyClient.js#L486
16
- */
17
- export declare function patchCacheFlightCodec(code: string, id: string, version?: string): MagicStringTransformResult | null;
18
- export declare function cacheFlightCodecPlugin(): Plugin;
19
- //#endregion
@@ -1,68 +0,0 @@
1
- import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
- import { magicStringTransformResult } from "./transform-result.js";
3
- import fs from "node:fs";
4
- import MagicString from "magic-string";
5
- //#region src/plugins/cache-flight-codec.ts
6
- const CLIENT_CODEC = /\/react-server-dom-(?:webpack|turbopack)-client\.edge\.(?:development|production)\.js$/;
7
- const ELEMENT_CASE = /case REACT_ELEMENT_TYPE:[\s\S]*?throw Error\(\s*"React Element cannot be passed/;
8
- /**
9
- * Version of the Flight codec package that owns `id`. plugin-rsc resolves the
10
- * app's own react-server-dom-webpack when installed and its vendored copy
11
- * otherwise; reading the codec file's own package.json follows that choice.
12
- */
13
- function readFlightCodecVersion(id) {
14
- for (let dir = path.dirname(id);; dir = path.dirname(dir)) {
15
- const manifest = path.join(dir, "package.json");
16
- if (fs.existsSync(manifest)) {
17
- const pkg = JSON.parse(fs.readFileSync(manifest, "utf8"));
18
- if (/^react-server-dom-(?:webpack|turbopack)$/.test(pkg.name ?? "") && pkg.version) return pkg.version;
19
- }
20
- if (path.dirname(dir) === dir) throw new Error(`vinext: cannot find the react-server-dom package version for ${id}`);
21
- }
22
- }
23
- /** React 19.3 ships the branch; 0.0.0-* experimental builds track main. */
24
- function needsElementTemporaryReferenceBackport(version) {
25
- const match = /^(\d+)\.(\d+)\./.exec(version);
26
- if (!match || version.startsWith("0.0.0-")) return false;
27
- const [major, minor] = [Number(match[1]), Number(match[2])];
28
- return major < 19 || major === 19 && minor < 3;
29
- }
30
- /**
31
- * Backport React 19.3's root-element temporary reference branch to older Flight
32
- * codecs, so a "use cache" argument like `Promise<ReactElement>` encodes as a
33
- * temporary reference instead of throwing. Remove it once React 19.3 is the
34
- * minimum supported version.
35
- * https://github.com/facebook/react/blob/v19.3.0/packages/react-client/src/ReactFlightReplyClient.js#L486
36
- */
37
- function patchCacheFlightCodec(code, id, version = readFlightCodecVersion(id)) {
38
- if (!needsElementTemporaryReferenceBackport(version)) return null;
39
- const elementCase = ELEMENT_CASE.exec(code);
40
- if (!elementCase) throw new Error(`vinext: react-server-dom-webpack ${version} (${id}) is not supported. Upgrade react, react-dom, and react-server-dom-webpack to 19.3 or later. If your app does not depend on react-server-dom-webpack directly, upgrade @vitejs/plugin-rsc to 0.5.35 or later instead.`);
41
- const output = new MagicString(code);
42
- output.appendLeft(elementCase.index + elementCase[0].lastIndexOf("throw Error("), "if (void 0 !== temporaryReferences && modelRoot === value) return (modelRoot = null), \"$T\";\n");
43
- return magicStringTransformResult(output, {
44
- hires: "boundary",
45
- source: id
46
- });
47
- }
48
- function cacheFlightCodecPlugin() {
49
- const transform = {
50
- filter: { id: CLIENT_CODEC },
51
- handler: (code, id) => patchCacheFlightCodec(code, id)
52
- };
53
- return {
54
- name: "vinext:cache-flight-codec",
55
- enforce: "pre",
56
- applyToEnvironment: (environment) => environment.name === "rsc",
57
- configEnvironment(name) {
58
- if (name !== "rsc") return;
59
- return { optimizeDeps: { rolldownOptions: { plugins: [{
60
- name: "vinext:cache-flight-codec-optimizer",
61
- transform
62
- }] } } };
63
- },
64
- transform
65
- };
66
- }
67
- //#endregion
68
- export { cacheFlightCodecPlugin, patchCacheFlightCodec, readFlightCodecVersion };