vinext 0.1.8 → 0.2.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.
Files changed (237) hide show
  1. package/README.md +51 -30
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/layout-classification.js +1 -1
  5. package/dist/build/nitro-route-rules.js +1 -1
  6. package/dist/build/pages-client-assets-module.d.ts +11 -0
  7. package/dist/build/pages-client-assets-module.js +27 -0
  8. package/dist/build/prerender.d.ts +2 -1
  9. package/dist/build/prerender.js +13 -6
  10. package/dist/build/report.d.ts +13 -2
  11. package/dist/build/report.js +99 -2
  12. package/dist/build/run-prerender.d.ts +7 -0
  13. package/dist/build/run-prerender.js +10 -1
  14. package/dist/build/standalone.js +2 -0
  15. package/dist/cache/cache-adapters-virtual.js +3 -3
  16. package/dist/check.js +40 -2
  17. package/dist/cli-args.d.ts +1 -2
  18. package/dist/cli-args.js +1 -1
  19. package/dist/cli-dev-config.d.ts +12 -0
  20. package/dist/cli-dev-config.js +23 -0
  21. package/dist/cli.js +111 -95
  22. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  23. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  24. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  25. package/dist/{server → client}/dev-error-overlay.js +2 -2
  26. package/dist/client/navigation-runtime.d.ts +2 -0
  27. package/dist/client/navigation-runtime.js +3 -1
  28. package/dist/client/window-next.d.ts +2 -1
  29. package/dist/cloudflare/index.d.ts +2 -2
  30. package/dist/cloudflare/index.js +2 -2
  31. package/dist/config/config-matchers.js +14 -10
  32. package/dist/config/next-config.d.ts +5 -3
  33. package/dist/config/next-config.js +44 -1
  34. package/dist/config/prerender.d.ts +34 -0
  35. package/dist/config/prerender.js +55 -0
  36. package/dist/entries/app-rsc-entry.d.ts +2 -1
  37. package/dist/entries/app-rsc-entry.js +40 -10
  38. package/dist/entries/app-rsc-manifest.js +2 -0
  39. package/dist/entries/pages-client-entry.d.ts +3 -0
  40. package/dist/entries/pages-client-entry.js +15 -1
  41. package/dist/entries/pages-server-entry.js +5 -2
  42. package/dist/image/image-adapters-virtual.d.ts +59 -0
  43. package/dist/image/image-adapters-virtual.js +59 -0
  44. package/dist/index.d.ts +33 -0
  45. package/dist/index.js +167 -100
  46. package/dist/init-cloudflare.d.ts +43 -0
  47. package/dist/init-cloudflare.js +839 -0
  48. package/dist/init-platform.d.ts +40 -0
  49. package/dist/init-platform.js +195 -0
  50. package/dist/init.d.ts +16 -38
  51. package/dist/init.js +209 -99
  52. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  53. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  54. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  55. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  56. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  57. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  58. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  59. package/dist/packages/cloudflare/src/deploy.js +276 -0
  60. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  61. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +18 -15
  62. package/dist/plugins/ast-scope.d.ts +16 -0
  63. package/dist/plugins/ast-scope.js +62 -0
  64. package/dist/plugins/ast-utils.d.ts +27 -1
  65. package/dist/plugins/ast-utils.js +32 -1
  66. package/dist/plugins/css-module-imports.d.ts +14 -0
  67. package/dist/plugins/css-module-imports.js +59 -0
  68. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  69. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  70. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  71. package/dist/plugins/typeof-window.d.ts +1 -1
  72. package/dist/plugins/typeof-window.js +28 -56
  73. package/dist/routing/app-route-graph.d.ts +23 -2
  74. package/dist/routing/app-route-graph.js +126 -32
  75. package/dist/routing/file-matcher.d.ts +3 -0
  76. package/dist/routing/file-matcher.js +3 -0
  77. package/dist/routing/pages-router.js +2 -2
  78. package/dist/server/api-handler.js +9 -14
  79. package/dist/server/app-browser-action-result.d.ts +4 -1
  80. package/dist/server/app-browser-action-result.js +8 -1
  81. package/dist/server/app-browser-entry.js +161 -52
  82. package/dist/server/app-browser-interception-context.d.ts +1 -0
  83. package/dist/server/app-browser-interception-context.js +4 -2
  84. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  85. package/dist/server/app-browser-navigation-controller.js +60 -31
  86. package/dist/server/app-browser-server-action-client.d.ts +1 -1
  87. package/dist/server/app-browser-server-action-client.js +3 -4
  88. package/dist/server/app-browser-state.d.ts +11 -1
  89. package/dist/server/app-browser-state.js +25 -8
  90. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  91. package/dist/server/app-browser-visible-commit.js +43 -25
  92. package/dist/server/app-elements-wire.d.ts +9 -2
  93. package/dist/server/app-elements-wire.js +8 -1
  94. package/dist/server/app-elements.d.ts +2 -2
  95. package/dist/server/app-elements.js +4 -3
  96. package/dist/server/app-fallback-renderer.d.ts +2 -1
  97. package/dist/server/app-fallback-renderer.js +10 -6
  98. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  99. package/dist/server/app-hydration-cache-publication.js +43 -0
  100. package/dist/server/app-middleware.d.ts +4 -3
  101. package/dist/server/app-middleware.js +8 -3
  102. package/dist/server/app-optimistic-routing.js +11 -4
  103. package/dist/server/app-page-cache-finalizer.js +2 -1
  104. package/dist/server/app-page-cache-render.d.ts +1 -0
  105. package/dist/server/app-page-cache-render.js +8 -4
  106. package/dist/server/app-page-cache.d.ts +1 -0
  107. package/dist/server/app-page-cache.js +5 -2
  108. package/dist/server/app-page-dispatch.js +1 -0
  109. package/dist/server/app-page-element-builder.d.ts +2 -1
  110. package/dist/server/app-page-element-builder.js +58 -4
  111. package/dist/server/app-page-probe.js +5 -0
  112. package/dist/server/app-page-render-identity.d.ts +1 -0
  113. package/dist/server/app-page-render-identity.js +1 -1
  114. package/dist/server/app-page-render.js +18 -0
  115. package/dist/server/app-page-request.d.ts +14 -0
  116. package/dist/server/app-page-request.js +69 -4
  117. package/dist/server/app-page-route-wiring.d.ts +8 -1
  118. package/dist/server/app-page-route-wiring.js +32 -18
  119. package/dist/server/app-page-segment-state.d.ts +2 -1
  120. package/dist/server/app-page-segment-state.js +3 -1
  121. package/dist/server/app-page-stream.d.ts +5 -0
  122. package/dist/server/app-page-stream.js +3 -1
  123. package/dist/server/app-route-handler-execution.js +5 -1
  124. package/dist/server/app-route-handler-response.js +1 -0
  125. package/dist/server/app-route-handler-runtime.js +1 -1
  126. package/dist/server/app-router-entry.js +9 -2
  127. package/dist/server/app-rsc-handler.d.ts +1 -0
  128. package/dist/server/app-rsc-handler.js +62 -31
  129. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  130. package/dist/server/app-rsc-request-normalization.js +6 -3
  131. package/dist/server/app-segment-config.d.ts +11 -0
  132. package/dist/server/app-segment-config.js +62 -6
  133. package/dist/server/app-server-action-execution.d.ts +1 -0
  134. package/dist/server/app-server-action-execution.js +58 -28
  135. package/dist/server/app-ssr-entry.d.ts +3 -0
  136. package/dist/server/app-ssr-entry.js +15 -7
  137. package/dist/server/app-ssr-stream.d.ts +7 -3
  138. package/dist/server/app-ssr-stream.js +10 -6
  139. package/dist/server/app-visited-response-cache.d.ts +6 -0
  140. package/dist/server/app-visited-response-cache.js +3 -1
  141. package/dist/server/client-trace-metadata.js +26 -0
  142. package/dist/server/default-global-not-found-module.d.ts +14 -0
  143. package/dist/server/default-global-not-found-module.js +14 -0
  144. package/dist/server/dev-route-files.js +4 -0
  145. package/dist/server/dev-server.js +19 -18
  146. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  147. package/dist/server/dev-stack-sourcemap.js +1 -1
  148. package/dist/server/fetch-handler.d.ts +2 -0
  149. package/dist/server/fetch-handler.js +18 -0
  150. package/dist/server/headers.d.ts +3 -15
  151. package/dist/server/headers.js +2 -15
  152. package/dist/server/image-optimization.d.ts +51 -1
  153. package/dist/server/image-optimization.js +52 -2
  154. package/dist/server/implicit-tags.js +1 -1
  155. package/dist/server/isr-cache.d.ts +1 -1
  156. package/dist/server/isr-cache.js +2 -2
  157. package/dist/server/metadata-routes.d.ts +3 -1
  158. package/dist/server/metadata-routes.js +12 -2
  159. package/dist/server/middleware-runtime.js +6 -1
  160. package/dist/server/navigation-planner.d.ts +1 -0
  161. package/dist/server/navigation-planner.js +14 -3
  162. package/dist/server/pages-api-route.js +2 -2
  163. package/dist/server/pages-asset-tags.d.ts +4 -6
  164. package/dist/server/pages-asset-tags.js +12 -12
  165. package/dist/server/pages-client-assets.d.ts +12 -0
  166. package/dist/server/pages-client-assets.js +10 -0
  167. package/dist/server/pages-node-compat.d.ts +8 -1
  168. package/dist/server/pages-node-compat.js +32 -4
  169. package/dist/server/pages-page-data.d.ts +24 -1
  170. package/dist/server/pages-page-data.js +45 -24
  171. package/dist/server/pages-page-handler.d.ts +2 -1
  172. package/dist/server/pages-page-handler.js +19 -12
  173. package/dist/server/pages-page-response.d.ts +7 -0
  174. package/dist/server/pages-page-response.js +4 -1
  175. package/dist/server/pages-request-pipeline.d.ts +2 -0
  176. package/dist/server/pages-request-pipeline.js +25 -1
  177. package/dist/server/pages-router-entry.d.ts +30 -0
  178. package/dist/server/pages-router-entry.js +108 -0
  179. package/dist/server/prerender-manifest.d.ts +3 -1
  180. package/dist/server/prerender-route-params.js +1 -1
  181. package/dist/server/prod-server.d.ts +1 -1
  182. package/dist/server/prod-server.js +33 -20
  183. package/dist/server/request-pipeline.js +1 -0
  184. package/dist/server/seed-cache.js +4 -4
  185. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  186. package/dist/shims/app-router-scroll-state.js +1 -0
  187. package/dist/shims/app-router-scroll.js +2 -1
  188. package/dist/shims/cache.js +19 -15
  189. package/dist/shims/cdn-cache.js +1 -1
  190. package/dist/shims/dynamic-preload-chunks.js +2 -1
  191. package/dist/shims/form.d.ts +3 -1
  192. package/dist/shims/form.js +37 -43
  193. package/dist/shims/headers.d.ts +7 -1
  194. package/dist/shims/headers.js +17 -3
  195. package/dist/shims/image.js +75 -14
  196. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  197. package/dist/shims/internal/app-route-detection.js +4 -17
  198. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  199. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  200. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -15
  201. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  202. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +9 -5
  203. package/dist/shims/internal/pages-data-fetch-dedup.js +73 -14
  204. package/dist/shims/internal/pages-data-target.d.ts +10 -9
  205. package/dist/shims/internal/pages-data-target.js +91 -12
  206. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  207. package/dist/shims/internal/pages-router-components.js +13 -0
  208. package/dist/shims/layout-segment-context.d.ts +4 -1
  209. package/dist/shims/layout-segment-context.js +18 -4
  210. package/dist/shims/link.js +55 -26
  211. package/dist/shims/navigation.d.ts +5 -1
  212. package/dist/shims/navigation.js +45 -10
  213. package/dist/shims/navigation.react-server.js +1 -1
  214. package/dist/shims/root-params.d.ts +15 -1
  215. package/dist/shims/root-params.js +21 -1
  216. package/dist/shims/router.d.ts +5 -7
  217. package/dist/shims/router.js +362 -93
  218. package/dist/shims/server.js +3 -2
  219. package/dist/shims/slot.js +3 -6
  220. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  221. package/dist/utils/client-runtime-metadata.js +31 -22
  222. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  223. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  224. package/dist/utils/domain-locale.d.ts +6 -3
  225. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  226. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  227. package/dist/utils/project.d.ts +48 -2
  228. package/dist/utils/project.js +225 -4
  229. package/dist/utils/protocol-headers.d.ts +17 -0
  230. package/dist/utils/protocol-headers.js +17 -0
  231. package/dist/utils/react-version.d.ts +4 -0
  232. package/dist/utils/react-version.js +44 -0
  233. package/package.json +47 -2
  234. package/dist/deploy.d.ts +0 -197
  235. package/dist/deploy.js +0 -1040
  236. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  237. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -1,5 +1,5 @@
1
- import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../server/headers.js";
2
- import { buildRequestHeadersFromMiddlewareResponse } from "../server/middleware-request-headers.js";
1
+ import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../utils/protocol-headers.js";
2
+ import { buildRequestHeadersFromMiddlewareResponse } from "../utils/middleware-request-headers.js";
3
3
  import { parseCookieHeader } from "../utils/parse-cookie.js";
4
4
  //#region src/config/config-matchers.ts
5
5
  /**
@@ -526,11 +526,13 @@ function extractConstraint(str, re) {
526
526
  *
527
527
  * The root path `"/"` is preserved as-is.
528
528
  */
529
- function stripTrailingSlashForConfigMatch(pathname) {
530
- return pathname.length > 1 && pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
529
+ function stripTrailingSlashForConfigMatch(value) {
530
+ return value.length > 1 && value.endsWith("/") ? value.slice(0, -1) : value;
531
531
  }
532
532
  function matchConfigPattern(pathname, pattern) {
533
+ const pathnameHadTrailingSlash = pathname.length > 1 && pathname.endsWith("/");
533
534
  pathname = stripTrailingSlashForConfigMatch(pathname);
535
+ if (pathnameHadTrailingSlash) pattern = stripTrailingSlashForConfigMatch(pattern);
534
536
  const catchAllAnchor = /:[\w-]+[*+]/.test(pattern);
535
537
  const namedParamCount = (pattern.match(/:[\w-]+/g) || []).length;
536
538
  if (pattern.includes("(") || pattern.includes("\\") || /:[\w-]+[*+][^/]/.test(pattern) || /:[\w-]+\./.test(pattern) || /[^/]:[\w-]+/.test(pattern) || catchAllAnchor && namedParamCount > 1) try {
@@ -628,12 +630,12 @@ function matchConfigPattern(pathname, pattern) {
628
630
  */
629
631
  function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAULT) {
630
632
  if (redirects.length === 0) return null;
631
- pathname = stripTrailingSlashForConfigMatch(pathname);
633
+ const normalizedPathname = stripTrailingSlashForConfigMatch(pathname);
632
634
  const index = _getRedirectIndex(redirects);
633
635
  let localeMatch = null;
634
636
  let localeMatchIndex = Infinity;
635
637
  if (index.localeStatic.size > 0) {
636
- const noLocaleBucket = index.localeStatic.get(pathname);
638
+ const noLocaleBucket = index.localeStatic.get(normalizedPathname);
637
639
  if (noLocaleBucket) for (const entry of noLocaleBucket) {
638
640
  if (!entry.optional) continue;
639
641
  if (entry.originalIndex >= localeMatchIndex) continue;
@@ -651,10 +653,10 @@ function matchRedirect(pathname, redirects, ctx, basePathState = _BASEPATH_DEFAU
651
653
  localeMatchIndex = entry.originalIndex;
652
654
  break;
653
655
  }
654
- const slashTwo = pathname.indexOf("/", 1);
656
+ const slashTwo = normalizedPathname.indexOf("/", 1);
655
657
  if (slashTwo !== -1) {
656
- const suffix = pathname.slice(slashTwo);
657
- const localePart = pathname.slice(1, slashTwo);
658
+ const suffix = normalizedPathname.slice(slashTwo);
659
+ const localePart = normalizedPathname.slice(1, slashTwo);
658
660
  const localeBucket = index.localeStatic.get(suffix);
659
661
  if (localeBucket) for (const entry of localeBucket) {
660
662
  if (entry.originalIndex >= localeMatchIndex) continue;
@@ -956,11 +958,13 @@ async function proxyExternalRequest(request, externalUrl) {
956
958
  * when evaluating headers, so this parameter is required.
957
959
  */
958
960
  function matchHeaders(pathname, headers, ctx, basePathState = _BASEPATH_DEFAULT) {
961
+ const pathnameHadTrailingSlash = pathname.length > 1 && pathname.endsWith("/");
959
962
  pathname = stripTrailingSlashForConfigMatch(pathname);
960
963
  const result = [];
961
964
  for (const rule of headers) {
962
965
  if (!shouldEvaluateRule(rule.basePath, basePathState)) continue;
963
- const sourceRegex = getCachedRegex(_compiledHeaderSourceCache, rule.source, () => safeRegExp("^" + escapeHeaderSource(rule.source) + "$"));
966
+ const source = pathnameHadTrailingSlash ? stripTrailingSlashForConfigMatch(rule.source) : rule.source;
967
+ const sourceRegex = getCachedRegex(_compiledHeaderSourceCache, source, () => safeRegExp("^" + escapeHeaderSource(source) + "$"));
964
968
  if (sourceRegex && sourceRegex.test(pathname)) {
965
969
  if (rule.has || rule.missing) {
966
970
  if (!checkHasConditions(rule.has, rule.missing, ctx)) continue;
@@ -107,7 +107,7 @@ type NextConfig = {
107
107
  }; /** Custom response headers */
108
108
  headers?: () => Promise<NextHeader[]> | NextHeader[]; /** Image optimization config */
109
109
  images?: {
110
- remotePatterns?: Array<{
110
+ remotePatterns?: Array<URL | {
111
111
  protocol?: string;
112
112
  hostname: string;
113
113
  port?: string;
@@ -273,8 +273,10 @@ type ResolvedNextConfig = {
273
273
  allowedDevOrigins: string[]; /** Extra allowed origins for server action CSRF validation (from experimental.serverActions.allowedOrigins). */
274
274
  serverActionsAllowedOrigins: string[]; /** Packages whose barrel imports should be optimized (from experimental.optimizePackageImports). */
275
275
  optimizePackageImports: string[]; /** Packages explicitly requested for server/client transpilation. */
276
- transpilePackages: string[]; /** Inline app CSS into production HTML (from experimental.inlineCss). */
277
- inlineCss: boolean; /** Parsed body size limit for server actions in bytes (from experimental.serverActions.bodySizeLimit). Defaults to 1MB. */
276
+ transpilePackages: string[]; /** Packages treated as application code by Turbopack's foreign-code condition. */
277
+ turbopackTranspilePackages: string[]; /** Inline app CSS into production HTML (from experimental.inlineCss). */
278
+ inlineCss: boolean; /** Enable standalone route-miss 404 handling (from experimental.globalNotFound). */
279
+ globalNotFound: boolean; /** Parsed body size limit for server actions in bytes (from experimental.serverActions.bodySizeLimit). Defaults to 1MB. */
278
280
  serverActionsBodySizeLimit: number; /** Verbatim body size limit config value (e.g. "2mb") for the "Body exceeded {limit} limit" error. Defaults to "1 MB". */
279
281
  serverActionsBodySizeLimitLabel: string; /** Route-level expire fallback in seconds for ISR entries with numeric revalidate. */
280
282
  expireTime: number;
@@ -72,6 +72,7 @@ const CONFIG_FILES = [
72
72
  "next.config.cjs"
73
73
  ];
74
74
  const DEFAULT_EXPIRE_TIME = 31536e3;
75
+ const DEFAULT_TRANSPILED_PACKAGES = ["geist"];
75
76
  /**
76
77
  * Default cap for the App Router preload `Link` header length, matching the
77
78
  * Next.js `defaultConfig.reactMaxHeadersLength`.
@@ -252,6 +253,31 @@ function findNextConfigPath(root) {
252
253
  }
253
254
  return null;
254
255
  }
256
+ function hasConfigProperty(config, propertyPath) {
257
+ let current = config;
258
+ for (const property of propertyPath.split(".")) {
259
+ if (!isUnknownRecord(current) || current[property] === void 0) return false;
260
+ current = current[property];
261
+ }
262
+ return true;
263
+ }
264
+ const emittedConfigWarnings = /* @__PURE__ */ new Set();
265
+ function warnConfigOnce(message) {
266
+ if (emittedConfigWarnings.has(message)) return;
267
+ emittedConfigWarnings.add(message);
268
+ console.warn(message);
269
+ }
270
+ function warnDeprecatedConfigOptions(config, root) {
271
+ const configFileName = path.basename(findNextConfigPath(root) ?? "next.config.js");
272
+ const warnings = [
273
+ ["experimental.middlewarePrefetch", `\`experimental.middlewarePrefetch\` is deprecated. Please use \`experimental.proxyPrefetch\` instead in ${configFileName}.`],
274
+ ["experimental.middlewareClientMaxBodySize", `\`experimental.middlewareClientMaxBodySize\` is deprecated. Please use \`experimental.proxyClientMaxBodySize\` instead in ${configFileName}.`],
275
+ ["experimental.externalMiddlewareRewritesResolve", `\`experimental.externalMiddlewareRewritesResolve\` is deprecated. Please use \`experimental.externalProxyRewritesResolve\` instead in ${configFileName}.`],
276
+ ["skipMiddlewareUrlNormalize", `\`skipMiddlewareUrlNormalize\` is deprecated. Please use \`skipProxyUrlNormalize\` instead in ${configFileName}.`],
277
+ ["experimental.instrumentationHook", `\`experimental.instrumentationHook\` is no longer needed, because \`instrumentation.js\` is available by default. You can remove it from ${configFileName}.`]
278
+ ];
279
+ for (const [propertyPath, warning] of warnings) if (hasConfigProperty(config, propertyPath)) warnConfigOnce(warning);
280
+ }
255
281
  async function resolveNextConfigInput(config, phase = PHASE_DEVELOPMENT_SERVER) {
256
282
  return await resolveConfigValue(config, phase);
257
283
  }
@@ -570,7 +596,9 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
570
596
  serverActionsAllowedOrigins: [],
571
597
  optimizePackageImports: [],
572
598
  transpilePackages: [],
599
+ turbopackTranspilePackages: [...DEFAULT_TRANSPILED_PACKAGES],
573
600
  inlineCss: false,
601
+ globalNotFound: false,
574
602
  serverActionsBodySizeLimit: 1 * 1024 * 1024,
575
603
  serverActionsBodySizeLimitLabel: "1 MB",
576
604
  expireTime: DEFAULT_EXPIRE_TIME,
@@ -602,6 +630,7 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
602
630
  detectNextIntlConfig(root, resolved);
603
631
  return resolved;
604
632
  }
633
+ warnDeprecatedConfigOptions(config, root);
605
634
  let redirects = [];
606
635
  if (config.redirects) {
607
636
  const result = await config.redirects();
@@ -653,6 +682,7 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
653
682
  const rawOptimize = experimental?.optimizePackageImports;
654
683
  const optimizePackageImports = Array.isArray(rawOptimize) ? rawOptimize.filter((x) => typeof x === "string") : [];
655
684
  const inlineCss = experimental?.inlineCss === true;
685
+ const globalNotFound = experimental?.globalNotFound === true;
656
686
  const prefetchInlining = experimental?.prefetchInlining === true || isUnknownRecord(experimental?.prefetchInlining);
657
687
  const appShells = experimental?.appShells === true;
658
688
  if (appShells) {
@@ -668,6 +698,7 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
668
698
  const legacyServerComponentsExternal = readStringArray(experimental?.serverComponentsExternalPackages);
669
699
  const serverExternalPackages = topLevelServerExternalPackages ?? legacyServerComponentsExternal;
670
700
  const transpilePackages = readStringArray(config.transpilePackages);
701
+ const turbopackTranspilePackages = [...transpilePackages, ...DEFAULT_TRANSPILED_PACKAGES];
671
702
  if (experimental?.swcEnvOptions !== void 0) console.warn("[vinext] next.config option \"experimental.swcEnvOptions\" is not applicable and will be ignored (vinext uses Vite, not SWC). A Vite-compatible polyfill solution may be explored in the future.");
672
703
  if (experimental?.rootParams !== void 0) console.warn("[vinext] `experimental.rootParams` is no longer needed, because `next/root-params` is available by default. You can remove it from next.config.(js|mjs|ts).");
673
704
  const useLightningcss = experimental?.useLightningcss === true;
@@ -706,6 +737,16 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
706
737
  fallback: applyLocaleToRoutes(rewrites.fallback, i18n, "rewrite", opts)
707
738
  };
708
739
  }
740
+ const images = config.images ? {
741
+ ...config.images,
742
+ remotePatterns: config.images.remotePatterns?.map((pattern) => pattern instanceof URL ? {
743
+ protocol: pattern.protocol.slice(0, -1),
744
+ hostname: pattern.hostname,
745
+ port: pattern.port,
746
+ pathname: pattern.pathname,
747
+ search: pattern.search
748
+ } : { ...pattern })
749
+ } : void 0;
709
750
  const resolved = {
710
751
  env: config.env ?? {},
711
752
  basePath: config.basePath ?? "",
@@ -723,7 +764,7 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
723
764
  redirects,
724
765
  rewrites,
725
766
  headers,
726
- images: config.images,
767
+ images,
727
768
  i18n,
728
769
  mdx,
729
770
  aliases,
@@ -731,7 +772,9 @@ async function resolveNextConfig(config, root = process.cwd(), options = {}) {
731
772
  serverActionsAllowedOrigins,
732
773
  optimizePackageImports,
733
774
  transpilePackages,
775
+ turbopackTranspilePackages,
734
776
  inlineCss,
777
+ globalNotFound,
735
778
  serverActionsBodySizeLimit,
736
779
  serverActionsBodySizeLimitLabel,
737
780
  expireTime: typeof config.expireTime === "number" ? config.expireTime : DEFAULT_EXPIRE_TIME,
@@ -0,0 +1,34 @@
1
+ import { PluginOption } from "vite";
2
+
3
+ //#region src/config/prerender.d.ts
4
+ type VinextPrerenderConfig = true | {
5
+ /**
6
+ * Routes to pre-render after the production build.
7
+ *
8
+ * Currently only `"*"` is supported, which pre-renders every discovered
9
+ * App Router and Pages Router route that vinext can statically render.
10
+ */
11
+ routes: "*";
12
+ };
13
+ type ResolvedVinextPrerenderConfig = {
14
+ routes: "*";
15
+ };
16
+ type VinextPrerenderDecisionReason = "flag" | "next-export" | "vinext-config";
17
+ type VinextPrerenderDecision = ResolvedVinextPrerenderConfig & {
18
+ reason: VinextPrerenderDecisionReason;
19
+ };
20
+ declare const VINEXT_PRERENDER_CONFIG_PLUGIN_PROPERTY = "__vinextPrerenderConfig";
21
+ type ViteConfigLoader = {
22
+ loadConfigFromFile: typeof import("vite").loadConfigFromFile;
23
+ };
24
+ declare function normalizeVinextPrerenderConfig(config: VinextPrerenderConfig | undefined): ResolvedVinextPrerenderConfig | null;
25
+ declare function findVinextPrerenderConfigInPlugins(plugins: PluginOption[] | undefined): ResolvedVinextPrerenderConfig | null;
26
+ declare function loadVinextPrerenderConfigFromViteConfig(vite: ViteConfigLoader, root: string): Promise<ResolvedVinextPrerenderConfig | null>;
27
+ declare function resolveVinextPrerenderDecision(options: {
28
+ prerenderAllFlag?: boolean;
29
+ vinextPrerenderConfig?: ResolvedVinextPrerenderConfig | null;
30
+ nextOutput?: string;
31
+ }): VinextPrerenderDecision | null;
32
+ declare function formatVinextPrerenderLabel(decision: VinextPrerenderDecision): string;
33
+ //#endregion
34
+ export { ResolvedVinextPrerenderConfig, VINEXT_PRERENDER_CONFIG_PLUGIN_PROPERTY, VinextPrerenderConfig, VinextPrerenderDecision, VinextPrerenderDecisionReason, findVinextPrerenderConfigInPlugins, formatVinextPrerenderLabel, loadVinextPrerenderConfigFromViteConfig, normalizeVinextPrerenderConfig, resolveVinextPrerenderDecision };
@@ -0,0 +1,55 @@
1
+ import { isUnknownRecord } from "../utils/record.js";
2
+ //#region src/config/prerender.ts
3
+ const VINEXT_PRERENDER_CONFIG_PLUGIN_PROPERTY = "__vinextPrerenderConfig";
4
+ function normalizeVinextPrerenderConfig(config) {
5
+ if (config === void 0) return null;
6
+ if (config === true) return { routes: "*" };
7
+ if (!isUnknownRecord(config)) throw new Error("[vinext] Invalid `prerender` config. Use `true` or `{ routes: \"*\" }`.");
8
+ if (config.routes === "*") return { routes: "*" };
9
+ throw new Error("[vinext] Unsupported `prerender.routes` config. Currently only `routes: \"*\"` is supported.");
10
+ }
11
+ function flattenPluginOptions(value, target) {
12
+ if (Array.isArray(value)) {
13
+ for (const item of value) flattenPluginOptions(item, target);
14
+ return;
15
+ }
16
+ if (value) target.push(value);
17
+ }
18
+ function findVinextPrerenderConfigInPlugins(plugins) {
19
+ const flattened = [];
20
+ flattenPluginOptions(plugins, flattened);
21
+ for (const plugin of flattened) {
22
+ if (!isUnknownRecord(plugin)) continue;
23
+ const prerenderConfig = plugin[VINEXT_PRERENDER_CONFIG_PLUGIN_PROPERTY];
24
+ if (prerenderConfig) return prerenderConfig;
25
+ }
26
+ return null;
27
+ }
28
+ async function loadVinextPrerenderConfigFromViteConfig(vite, root) {
29
+ return findVinextPrerenderConfigInPlugins((await vite.loadConfigFromFile({
30
+ command: "build",
31
+ mode: "production"
32
+ }, void 0, root))?.config.plugins);
33
+ }
34
+ function resolveVinextPrerenderDecision(options) {
35
+ if (options.prerenderAllFlag) return {
36
+ routes: "*",
37
+ reason: "flag"
38
+ };
39
+ if (options.nextOutput === "export") return {
40
+ routes: "*",
41
+ reason: "next-export"
42
+ };
43
+ if (options.vinextPrerenderConfig?.routes === "*") return {
44
+ routes: "*",
45
+ reason: "vinext-config"
46
+ };
47
+ return null;
48
+ }
49
+ function formatVinextPrerenderLabel(decision) {
50
+ if (decision.reason === "next-export") return "Pre-rendering all routes (output: 'export')...";
51
+ if (decision.reason === "vinext-config") return "Pre-rendering all routes (vinext prerender config)...";
52
+ return "Pre-rendering all routes...";
53
+ }
54
+ //#endregion
55
+ export { VINEXT_PRERENDER_CONFIG_PLUGIN_PROPERTY, findVinextPrerenderConfigInPlugins, formatVinextPrerenderLabel, loadVinextPrerenderConfigFromViteConfig, normalizeVinextPrerenderConfig, resolveVinextPrerenderDecision };
@@ -43,7 +43,8 @@ type AppRouterConfig = {
43
43
  */
44
44
  reactMaxHeadersLength?: number; /** Maximum in-memory cache size in bytes. 0 disables the default memory cache. */
45
45
  cacheMaxMemorySize?: number; /** Inline app CSS into production HTML (from experimental.inlineCss). */
46
- inlineCss?: boolean; /** Enables Next.js Cache Components semantics for App Router document HTML. */
46
+ inlineCss?: boolean; /** Enable standalone route-miss 404 handling (from experimental.globalNotFound). */
47
+ globalNotFound?: boolean; /** Enables Next.js Cache Components semantics for App Router document HTML. */
47
48
  cacheComponents?: boolean; /** Whether the RSC build discovered any server references. Defaults to true. */
48
49
  hasServerActions?: boolean; /** Internationalization routing config for middleware matcher locale handling. */
49
50
  i18n?: NextI18nConfig | null;
@@ -1,6 +1,7 @@
1
1
  import { normalizePathSeparators } from "../utils/path.js";
2
2
  import { resolveEntryPath } from "./runtime-entry-module.js";
3
3
  import { isProxyFile } from "../server/middleware.js";
4
+ import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES } from "../server/image-optimization.js";
4
5
  import { buildAppRscManifestCode } from "./app-rsc-manifest.js";
5
6
  import { generateDevOriginCheckCode } from "../server/dev-origin-check.js";
6
7
  import { randomUUID } from "node:crypto";
@@ -16,7 +17,7 @@ import { randomUUID } from "node:crypto";
16
17
  */
17
18
  const DEFAULT_EXPIRE_TIME = 31536e3;
18
19
  const DEFAULT_REACT_MAX_HEADERS_LENGTH = 6e3;
19
- const middlewareRequestHeadersPath = resolveEntryPath("../server/middleware-request-headers.js", import.meta.url);
20
+ const middlewareRequestHeadersPath = resolveEntryPath("../utils/middleware-request-headers.js", import.meta.url);
20
21
  const normalizePathModulePath = resolveEntryPath("../server/normalize-path.js", import.meta.url);
21
22
  const appRouteHandlerDispatchPath = resolveEntryPath("../server/app-route-handler-dispatch.js", import.meta.url);
22
23
  const appRouteHandlerResponsePath = resolveEntryPath("../server/app-route-handler-response.js", import.meta.url);
@@ -82,11 +83,19 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
82
83
  const hasPagesDir = config?.hasPagesDir ?? false;
83
84
  const publicFiles = config?.publicFiles ?? [];
84
85
  const draftModeSecret = config?.draftModeSecret ?? randomUUID();
86
+ const imageAllowedWidths = [...config?.imageConfig?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...config?.imageConfig?.imageSizes ?? DEFAULT_IMAGE_SIZES];
87
+ const imageConfig = {
88
+ qualities: config?.imageConfig?.qualities,
89
+ dangerouslyAllowSVG: config?.imageConfig?.dangerouslyAllowSVG,
90
+ dangerouslyAllowLocalIP: config?.imageConfig?.dangerouslyAllowLocalIP,
91
+ contentDispositionType: config?.imageConfig?.contentDispositionType,
92
+ contentSecurityPolicy: config?.imageConfig?.contentSecurityPolicy
93
+ };
85
94
  const { imports, routeEntries, metaRouteEntries, generateStaticParamsEntries, rootParamNameEntries, rootNotFoundVar, rootForbiddenVar, rootUnauthorizedVar, rootLayoutVars, globalErrorVar, globalNotFoundImportSpecifier } = buildAppRscManifestCode({
86
95
  routes,
87
96
  metadataRoutes,
88
97
  globalErrorPath,
89
- globalNotFoundPath: config?.globalNotFoundPath ?? null
98
+ globalNotFoundPath: config?.globalNotFound === true ? config.globalNotFoundPath ?? null : null
90
99
  });
91
100
  const loadPrerenderPagesRoutesCode = hasPagesDir ? `
92
101
  async function __loadPrerenderPagesRoutes() {
@@ -123,6 +132,8 @@ ${instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(norm
123
132
  import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(instrumentationRuntimePath)};` : ""}
124
133
  import { createAppRscHandler } from "vinext/server/app-rsc-handler";
125
134
  import { registerConfiguredCacheAdapters as __registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
135
+ import __pagesClientAssets from "virtual:vinext-pages-client-assets";
136
+ import { setPagesClientAssets as __setPagesClientAssets } from "vinext/server/pages-client-assets";
126
137
  import { decodePathParams as __decodePathParams } from ${JSON.stringify(normalizePathModulePath)};
127
138
  import { buildRequestHeadersFromMiddlewareResponse as __buildRequestHeadersFromMiddlewareResponse } from ${JSON.stringify(middlewareRequestHeadersPath)};
128
139
  ${hasPagesDir ? `import {
@@ -354,6 +365,7 @@ const __fallbackRenderer = __createAppFallbackRenderer({
354
365
  },
355
366
  globalErrorModule: ${globalErrorVar ? globalErrorVar : "null"},
356
367
  loadGlobalNotFoundModule: __loadGlobalNotFoundModule,
368
+ globalNotFoundEnabled: ${config?.globalNotFound === true},
357
369
  metadataRoutes,
358
370
  ssrLoader() {
359
371
  return import.meta.viteRsc.loadModule("ssr", "index");
@@ -415,7 +427,7 @@ const __i18nConfig = ${JSON.stringify(i18nConfig)};
415
427
  const __configRedirects = ${JSON.stringify(redirects)};
416
428
  const __configRewrites = ${JSON.stringify(rewrites)};
417
429
  const __configHeaders = ${JSON.stringify(headers)};
418
- const __imageConfig = ${JSON.stringify(config?.imageConfig)};
430
+ const __runtimeImageConfig = ${JSON.stringify(config?.imageConfig)};
419
431
  const __publicFiles = new Set(${JSON.stringify(publicFiles)});
420
432
  const __allowedOrigins = ${JSON.stringify(allowedOrigins)};
421
433
  const __expireTime = ${JSON.stringify(expireTime)};
@@ -426,6 +438,8 @@ const __reactMaxHeadersLength = ${JSON.stringify(reactMaxHeadersLength)};
426
438
  // mirrors the embedded \`__basePath\` pattern (and Pages Router's
427
439
  // \`vinextConfig\` export). Empty string when unset.
428
440
  export const __assetPrefix = ${JSON.stringify(assetPrefix)};
441
+ export const __imageAllowedWidths = ${JSON.stringify(imageAllowedWidths)};
442
+ export const __imageConfig = ${JSON.stringify(imageConfig)};
429
443
  export const __inlineCss = ${JSON.stringify(inlineCss)};
430
444
  export const __hasPagesDir = ${JSON.stringify(hasPagesDir)};
431
445
  export const getRenderedConcreteUrlPathsForRoute = __getRenderedConcreteUrlPathsForRoute;
@@ -474,6 +488,7 @@ const rootParamNamesMap = {
474
488
  ${rootParamNameEntries.join("\n")}
475
489
  };
476
490
 
491
+ __setPagesClientAssets(__pagesClientAssets);
477
492
  export default createAppRscHandler({
478
493
  basePath: __basePath,
479
494
  buildId: process.env.__VINEXT_BUILD_ID ?? null,
@@ -488,7 +503,7 @@ export default createAppRscHandler({
488
503
  },` : ""}
489
504
  configRedirects: __configRedirects,
490
505
  configRewrites: __configRewrites,
491
- imageConfig: __imageConfig,
506
+ imageConfig: __runtimeImageConfig,
492
507
  isDev: process.env.NODE_ENV !== "production",
493
508
  draftModeSecret: __draftModeSecret,
494
509
  dispatchMatchedPage({
@@ -520,18 +535,32 @@ export default createAppRscHandler({
520
535
  const PageComponent = route.page?.default;
521
536
  const __segmentConfig = __resolveAppPageSegmentConfig({
522
537
  layouts: route.layouts,
538
+ layoutTreePositions: route.layoutTreePositions,
523
539
  page: route.page,
540
+ parallelBranches: Object.values(route.slots ?? {}).map((slot) => ({
541
+ layout: slot.layout,
542
+ configLayouts: slot.configLayouts,
543
+ configLayoutTreePositions: slot.configLayoutTreePositions,
544
+ page: slot.page ?? slot.default,
545
+ routeSegments: slot.routeSegments,
546
+ })),
524
547
  parallelPages: Object.values(route.slots ?? {}).map((slot) => slot.page ?? slot.default),
525
- parallelSegments: Object.values(route.slots ?? {}).flatMap((slot) => [
526
- slot.layout,
527
- ...(slot.configLayouts ?? []),
528
- slot.page ?? slot.default,
529
- ]),
548
+ routeSegments: route.routeSegments,
530
549
  });
531
550
  const __generateStaticParams = __resolveAppPageGenerateStaticParamsSources({
532
551
  layouts: route.layouts,
533
552
  layoutTreePositions: route.layoutTreePositions,
534
553
  page: route.page,
554
+ parallelBranches: Object.values(route.slots ?? {}).map((slot) => ({
555
+ layout: slot.layout,
556
+ configLayouts: slot.configLayouts,
557
+ configLayoutTreePositions: slot.configLayoutTreePositions,
558
+ page: slot.page ?? slot.default,
559
+ paramNames: slot.slotParamNames,
560
+ patternParts: slot.slotPatternParts,
561
+ routeSegments: slot.routeSegments,
562
+ })),
563
+ routePatternParts: route.patternParts,
535
564
  routeSegments: route.routeSegments,
536
565
  });
537
566
  const _asyncRouteParams = makeThenableParams(params);
@@ -923,11 +952,12 @@ export default createAppRscHandler({
923
952
  });
924
953
  },` : ""}
925
954
  matchRoute,
926
- ${middlewarePath ? `runMiddleware({ cleanPathname, context, isDataRequest, request }) {
955
+ ${middlewarePath ? `runMiddleware({ cleanPathname, context, hadBasePath, isDataRequest, request }) {
927
956
  return __applyAppMiddleware({
928
957
  basePath: __basePath,
929
958
  cleanPathname,
930
959
  context,
960
+ hadBasePath,
931
961
  filePath: ${JSON.stringify(middlewarePath ? normalizePathSeparators(middlewarePath) : "")},
932
962
  i18nConfig: __i18nConfig,
933
963
  isDataRequest,
@@ -181,6 +181,7 @@ ${interceptEntries.join(",\n")}
181
181
  layouts: ${moduleArray(route.layouts.length)},
182
182
  __loadLayouts: ${layoutLoaders},
183
183
  routeSegments: ${JSON.stringify(route.routeSegments)},
184
+ childrenRouteSegments: ${JSON.stringify(route.childrenRouteSegments ?? null)},
184
185
  templateTreePositions: ${JSON.stringify(route.templateTreePositions)},
185
186
  layoutTreePositions: ${JSON.stringify(route.layoutTreePositions)},
186
187
  templates: ${moduleArray(route.templates.length)},
@@ -193,6 +194,7 @@ ${interceptEntries.join(",\n")}
193
194
  slots: {
194
195
  ${slotEntries.join(",\n")}
195
196
  },
197
+ childrenSlot: ${JSON.stringify(route.childrenSlot ?? null)},
196
198
  siblingIntercepts: [
197
199
  ${siblingInterceptEntries.join(",\n")}
198
200
  ],
@@ -1,11 +1,14 @@
1
1
  import { ResolvedNextConfig } from "../config/next-config.js";
2
2
  import { createValidFileMatcher } from "../routing/file-matcher.js";
3
+ import { StaticMiddlewareMatcher } from "../build/report.js";
3
4
  import { VinextLinkPrefetchRoute } from "../client/vinext-next-data.js";
4
5
 
5
6
  //#region src/entries/pages-client-entry.d.ts
6
7
  declare function generateClientEntry(pagesDir: string, nextConfig: ResolvedNextConfig, fileMatcher: ReturnType<typeof createValidFileMatcher>, options?: {
7
8
  appPrefetchRoutes?: readonly VinextLinkPrefetchRoute[];
8
9
  instrumentationClientPath?: string | null;
10
+ middlewareMatcher?: StaticMiddlewareMatcher | undefined;
11
+ reactPreamble?: boolean;
9
12
  }): Promise<string>;
10
13
  //#endregion
11
14
  export { generateClientEntry };
@@ -3,6 +3,8 @@ import { findFileWithExts } from "../routing/file-matcher.js";
3
3
  import { patternToNextFormat } from "../routing/route-validation.js";
4
4
  import { apiRouter, pagesRouter } from "../routing/pages-router.js";
5
5
  import "./pages-entry-helpers.js";
6
+ import { hasExportedName } from "../build/report.js";
7
+ import { readFile } from "node:fs/promises";
6
8
  //#region src/entries/pages-client-entry.ts
7
9
  /**
8
10
  * Pages Router client hydration entry generator.
@@ -30,6 +32,12 @@ function toPagesLinkPrefetchRoute(route) {
30
32
  patternParts: [...route.patternParts]
31
33
  };
32
34
  }
35
+ async function hasGetStaticPropsExport(filePath) {
36
+ return hasExportedName(await readFile(filePath, "utf8"), "getStaticProps");
37
+ }
38
+ async function hasGetServerSidePropsExport(filePath) {
39
+ return hasExportedName(await readFile(filePath, "utf8"), "getServerSideProps");
40
+ }
33
41
  async function generateClientEntry(pagesDir, nextConfig, fileMatcher, options = {}) {
34
42
  const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);
35
43
  const apiRoutes = await apiRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);
@@ -40,6 +48,8 @@ async function generateClientEntry(pagesDir, nextConfig, fileMatcher, options =
40
48
  ...toPagesLinkPrefetchRoute(route),
41
49
  documentOnly: true
42
50
  }))];
51
+ const pagesSsgPatterns = (await Promise.all(pageRoutes.map(async (route) => await hasGetStaticPropsExport(route.filePath) ? patternToNextFormat(route.pattern) : null))).filter((pattern) => pattern !== null);
52
+ const pagesSspPatterns = (await Promise.all(pageRoutes.map(async (route) => await hasGetServerSidePropsExport(route.filePath) ? patternToNextFormat(route.pattern) : null))).filter((pattern) => pattern !== null);
43
53
  const instrumentationClientPath = options.instrumentationClientPath ?? null;
44
54
  const loaderEntries = pageRoutes.map((r) => {
45
55
  const absPath = normalizePathSeparators(r.filePath);
@@ -47,7 +57,7 @@ async function generateClientEntry(pagesDir, nextConfig, fileMatcher, options =
47
57
  return ` ${JSON.stringify(nextFormatPattern)}: () => import(${JSON.stringify(absPath)})`;
48
58
  });
49
59
  const appFileBase = appFilePath ? normalizePathSeparators(appFilePath) : void 0;
50
- return `${instrumentationClientPath ? `import ${JSON.stringify(normalizePathSeparators(instrumentationClientPath))};\n` : ""}
60
+ return `${instrumentationClientPath ? `import ${JSON.stringify(normalizePathSeparators(instrumentationClientPath))};\n` : ""}${options.reactPreamble === false ? "" : "import \"@vitejs/plugin-react/preamble\";\n"}
51
61
  import "vinext/instrumentation-client";
52
62
  import React from "react";
53
63
  import { hydrateRoot } from "react-dom/client";
@@ -79,6 +89,9 @@ const appLoader = undefined;
79
89
  // can iterate in order and trust the first match.
80
90
  window.__VINEXT_PAGE_LOADERS__ = pageLoaders;
81
91
  window.__VINEXT_PAGE_PATTERNS__ = Object.keys(pageLoaders);
92
+ window.__VINEXT_PAGES_SSG_PATTERNS__ = ${JSON.stringify(pagesSsgPatterns)};
93
+ window.__VINEXT_PAGES_SSP_PATTERNS__ = ${JSON.stringify(pagesSspPatterns)};
94
+ window.__VINEXT_MIDDLEWARE_MATCHER__ = ${JSON.stringify(options.middlewareMatcher)};
82
95
  window.__VINEXT_APP_LOADER__ = appLoader;
83
96
  // Expose the App Router prefetch manifest so Pages Router \`<Link>\`s and
84
97
  // \`Router.prefetch\` can detect when a prefetch target is actually an App
@@ -100,6 +113,7 @@ window.__VINEXT_LINK_PREFETCH_ROUTES__ = ${JSON.stringify(appPrefetchRoutes)};
100
113
  // instead of issuing an RSC request). Set here AND in app-browser-entry.ts
101
114
  // so whichever entry runs first emits the Pages manifest.
102
115
  window.__VINEXT_PAGES_LINK_PREFETCH_ROUTES__ = ${JSON.stringify(pagesPrefetchRoutes)};
116
+ window.__VINEXT_CLIENT_REDIRECTS__ = ${JSON.stringify(nextConfig.redirects)};
103
117
  window.__VINEXT_CLIENT_REWRITES__ = ${JSON.stringify(nextConfig.rewrites)};
104
118
 
105
119
  const nextDataElement = document.getElementById("__NEXT_DATA__");
@@ -128,6 +128,8 @@ import Router, { setSSRContext, wrapWithRouterContext, getPagesNavigationIsReady
128
128
  import { _runWithCacheState } from "vinext/shims/cache-request-state";
129
129
  import { configureMemoryCacheHandler as __configureMemoryCacheHandler } from "vinext/shims/cache-handler";
130
130
  import { registerConfiguredCacheAdapters as __registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
131
+ import __pagesClientAssets from "virtual:vinext-pages-client-assets";
132
+ import { setPagesClientAssets as __setPagesClientAssets } from "vinext/server/pages-client-assets";
131
133
  import { runWithPrivateCache } from "vinext/cache-runtime";
132
134
  import { ensureFetchPatch, runWithFetchCache } from "vinext/fetch-cache";
133
135
  import "vinext/router-state";
@@ -164,7 +166,7 @@ export const buildId = ${buildIdJson};
164
166
  export function normalizeDataRequest(request) {
165
167
  return __normalizePagesDataRequest(request, buildId);
166
168
  }
167
- const __hasMiddleware = ${JSON.stringify(Boolean(middlewarePath))};
169
+ export const hasMiddleware = ${JSON.stringify(Boolean(middlewarePath))};
168
170
 
169
171
  // Full resolved config for production server (embedded at build time)
170
172
  export const vinextConfig = ${vinextConfigJson};
@@ -271,6 +273,7 @@ export function matchApiRoute(url, request) {
271
273
  // All next/*-derived values are passed as closures so the handler module
272
274
  // stays importable in test environments (the root vite.config.ts only
273
275
  // aliases vinext/shims/*, not next/*).
276
+ __setPagesClientAssets(__pagesClientAssets);
274
277
  const _renderPage = __createPagesPageHandler({
275
278
  pageRoutes,
276
279
  errorPageRoute: _errorPageRoute,
@@ -286,7 +289,7 @@ const _renderPage = __createPagesPageHandler({
286
289
  disableOptimizedLoading: vinextConfig.disableOptimizedLoading,
287
290
  },
288
291
  buildId,
289
- hasMiddleware: __hasMiddleware,
292
+ hasMiddleware,
290
293
  appAssetPath: _appAssetPath,
291
294
  hasRewrites:
292
295
  vinextConfig.rewrites.beforeFiles.length > 0 ||
@@ -0,0 +1,59 @@
1
+ //#region src/image/image-adapters-virtual.d.ts
2
+ /**
3
+ * Code generation for the `virtual:vinext-image-adapters` module, resolved by
4
+ * the vinext vite plugin from the user's `images` config ({@link VinextImageConfig}).
5
+ *
6
+ * The generated module exports `registerConfiguredImageOptimizer(env)`, which the
7
+ * server entries call on each request. It self-guards (the optimizer instantiates
8
+ * once per isolate) and is a no-op when nothing is configured. Registration is
9
+ * resilient: a factory that throws (e.g. a Cloudflare Images adapter on the
10
+ * Node.js server, where the `IMAGES` binding can't exist) is logged and skipped
11
+ * rather than failing every request, so the same config can be registered from
12
+ * every runtime/router entry. When no optimizer is registered, image requests
13
+ * fall back to serving the original asset unoptimized.
14
+ *
15
+ * Descriptor `options` are inlined into the generated module and forwarded to the
16
+ * factory at runtime, so a config-time builder like `imagesOptimizer({ binding })`
17
+ * never touches the Workers runtime — instantiation is deferred to the first
18
+ * request.
19
+ *
20
+ * This mirrors the cache-adapter pattern in `cache/cache-adapters-virtual.ts`.
21
+ */
22
+ /**
23
+ * A serializable pointer to an image optimizer adapter module — the shape of the
24
+ * `images.optimizer` slot in the vinext() plugin config. Produced by an adapter
25
+ * builder (e.g. `imagesOptimizer(...)` from `@vinext/cloudflare/images/images-optimizer`)
26
+ * or written by hand. `options` must be JSON-serializable: it is inlined into the
27
+ * generated registration module and forwarded to the adapter factory at runtime.
28
+ */
29
+ type ImageAdapterDescriptor<O extends Record<string, unknown> = Record<string, unknown>> = {
30
+ /**
31
+ * Module specifier (or absolute path, e.g. from `require.resolve(...)`) whose
32
+ * default export is an image optimizer factory.
33
+ */
34
+ adapter: string; /** JSON-serializable options forwarded to the factory at runtime. */
35
+ options?: O;
36
+ };
37
+ /**
38
+ * The `images` option of the vinext() plugin: declaratively register the
39
+ * server-side image optimizer (transform backend) instead of wiring `env.IMAGES`
40
+ * into a custom worker entry.
41
+ *
42
+ * This is complementary to the `images` field in `next.config.js`, which
43
+ * configures the standard Next.js image options (`remotePatterns`, `deviceSizes`,
44
+ * `dangerouslyAllowSVG`, etc.). Those continue to be read from next.config; this
45
+ * option only selects the runtime transform backend, which can't be expressed as
46
+ * serializable next.config data.
47
+ */
48
+ type VinextImageConfig = {
49
+ /** Server-side image optimizer adapter (the `/_next/image` transform backend). */optimizer?: ImageAdapterDescriptor;
50
+ };
51
+ /** Public virtual module id imported by the server entries. */
52
+ declare const VIRTUAL_IMAGE_ADAPTERS = "virtual:vinext-image-adapters";
53
+ /**
54
+ * Generate the source of the `virtual:vinext-image-adapters` module for the
55
+ * given config. Always exports `registerConfiguredImageOptimizer(env)`.
56
+ */
57
+ declare function generateImageAdaptersModule(images?: VinextImageConfig): string;
58
+ //#endregion
59
+ export { VIRTUAL_IMAGE_ADAPTERS, VinextImageConfig, generateImageAdaptersModule };