vinext 0.1.6 → 0.1.7

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 (32) hide show
  1. package/dist/build/client-build-config.d.ts +4 -6
  2. package/dist/build/client-build-config.js +27 -7
  3. package/dist/build/prerender.js +1 -2
  4. package/dist/entries/app-rsc-entry.d.ts +2 -1
  5. package/dist/entries/app-rsc-entry.js +35 -10
  6. package/dist/index.js +47 -20
  7. package/dist/plugins/og-assets.js +6 -6
  8. package/dist/plugins/remove-console.js +1 -1
  9. package/dist/plugins/strip-server-exports.js +2 -1
  10. package/dist/server/app-action-request.d.ts +4 -0
  11. package/dist/server/app-action-request.js +9 -0
  12. package/dist/server/app-bfcache-identity.d.ts +12 -2
  13. package/dist/server/app-bfcache-identity.js +52 -23
  14. package/dist/server/app-history-state.d.ts +1 -2
  15. package/dist/server/app-history-state.js +1 -1
  16. package/dist/server/app-page-method.js +1 -1
  17. package/dist/server/app-page-stream.js +2 -1
  18. package/dist/server/app-route-handler-cache.js +1 -1
  19. package/dist/server/app-route-handler-dispatch.js +2 -2
  20. package/dist/server/app-route-handler-execution.js +3 -2
  21. package/dist/server/app-route-handler-policy.d.ts +1 -1
  22. package/dist/server/app-route-handler-policy.js +1 -6
  23. package/dist/server/app-rsc-errors.d.ts +12 -1
  24. package/dist/server/app-rsc-errors.js +22 -2
  25. package/dist/server/app-rsc-handler.d.ts +13 -12
  26. package/dist/server/app-rsc-handler.js +24 -26
  27. package/dist/server/app-rsc-response-finalizer.js +5 -1
  28. package/dist/server/app-server-action-execution.js +1 -1
  29. package/dist/server/app-ssr-entry.js +7 -5
  30. package/dist/server/metadata-route-response.d.ts +1 -1
  31. package/dist/shims/dynamic.js +1 -1
  32. package/package.json +1 -1
@@ -26,12 +26,10 @@ declare function createClientAssetFileNames(assetsDir: string): (assetInfo: Clie
26
26
  *
27
27
  * Splits the client bundle into:
28
28
  * - "framework" — React, ReactDOM, and scheduler (loaded on every page)
29
- * - "vinext" — vinext shims (router, head, link, etc.)
29
+ * - "vinext" — shared vinext runtime shims
30
30
  *
31
- * All other vendor code is left to Rollup's default chunk-splitting
32
- * algorithm. Rollup automatically deduplicates shared modules into
33
- * common chunks based on the import graph — no manual intervention
34
- * needed.
31
+ * Route-owned client shims and all other vendor code are left to the bundler's
32
+ * graph-based chunking so they stay behind their client-reference boundaries.
35
33
  *
36
34
  * Why not split every npm package into its own chunk?
37
35
  * - Per-package splitting (`vendor-X`) creates 50-200+ chunks for a
@@ -48,7 +46,7 @@ declare function createClientAssetFileNames(assetsDir: string): (assetInfo: Clie
48
46
  * well: shared dependencies between routes get their own chunks,
49
47
  * and route-specific code stays in route chunks.
50
48
  */
51
- declare function createClientManualChunks(shimsDir: string): (id: string) => string | undefined;
49
+ declare function createClientManualChunks(shimsDir: string, preserveRouteBoundaries?: boolean): (id: string) => string | undefined;
52
50
  /**
53
51
  * Rollup output config with manualChunks for client code-splitting.
54
52
  * Used by both CLI builds and multi-environment builds.
@@ -1,4 +1,18 @@
1
1
  //#region src/build/client-build-config.ts
2
+ const ROUTE_OWNED_CLIENT_SHIMS = new Set([
3
+ "compat-router",
4
+ "dynamic",
5
+ "dynamic-preload-chunks",
6
+ "form",
7
+ "image",
8
+ "layout-segment-context",
9
+ "legacy-image",
10
+ "link",
11
+ "offline",
12
+ "router",
13
+ "script",
14
+ "web-vitals"
15
+ ]);
2
16
  const NEXT_CLIENT_CSS_ASSET_FILE_NAMES = "css/[name].[hash:8][extname]";
3
17
  const NEXT_CLIENT_STATIC_MEDIA_FILE_NAMES = "media/[name].[hash:8][extname]";
4
18
  function joinAssetFileNamePattern(assetsDir, pattern) {
@@ -48,12 +62,10 @@ function getPackageName(id) {
48
62
  *
49
63
  * Splits the client bundle into:
50
64
  * - "framework" — React, ReactDOM, and scheduler (loaded on every page)
51
- * - "vinext" — vinext shims (router, head, link, etc.)
65
+ * - "vinext" — shared vinext runtime shims
52
66
  *
53
- * All other vendor code is left to Rollup's default chunk-splitting
54
- * algorithm. Rollup automatically deduplicates shared modules into
55
- * common chunks based on the import graph — no manual intervention
56
- * needed.
67
+ * Route-owned client shims and all other vendor code are left to the bundler's
68
+ * graph-based chunking so they stay behind their client-reference boundaries.
57
69
  *
58
70
  * Why not split every npm package into its own chunk?
59
71
  * - Per-package splitting (`vendor-X`) creates 50-200+ chunks for a
@@ -70,7 +82,7 @@ function getPackageName(id) {
70
82
  * well: shared dependencies between routes get their own chunks,
71
83
  * and route-specific code stays in route chunks.
72
84
  */
73
- function createClientManualChunks(shimsDir) {
85
+ function createClientManualChunks(shimsDir, preserveRouteBoundaries = false) {
74
86
  return function clientManualChunks(id) {
75
87
  if (id.includes("node_modules")) {
76
88
  const pkg = getPackageName(id);
@@ -78,7 +90,15 @@ function createClientManualChunks(shimsDir) {
78
90
  if (pkg === "react" || pkg === "react-dom" || pkg === "scheduler") return "framework";
79
91
  return;
80
92
  }
81
- if (id.startsWith(shimsDir)) return "vinext";
93
+ if (id.startsWith(shimsDir)) {
94
+ if (preserveRouteBoundaries) {
95
+ const relativeId = id.slice(shimsDir.length).split("?", 1)[0] ?? "";
96
+ const extensionIndex = relativeId.lastIndexOf(".");
97
+ const shimName = extensionIndex === -1 ? relativeId : relativeId.slice(0, extensionIndex);
98
+ if (ROUTE_OWNED_CLIENT_SHIMS.has(shimName)) return void 0;
99
+ }
100
+ return "vinext";
101
+ }
82
102
  };
83
103
  }
84
104
  /**
@@ -306,7 +306,6 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
306
306
  for (const route of bundlePageRoutes) {
307
307
  if (BLOCKED_PAGES.includes(route.pattern)) continue;
308
308
  if (route.pattern === "/404") continue;
309
- if (!routes.find((r) => r.filePath === route.filePath || r.pattern === route.pattern)) continue;
310
309
  const { type, revalidate: classifiedRevalidate } = classifyPagesRoute(route.filePath);
311
310
  if (type === "ssr") {
312
311
  if (mode === "export") results.push({
@@ -648,7 +647,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
648
647
  });
649
648
  continue;
650
649
  }
651
- if (!Array.isArray(paramSets) || paramSets.length === 0) {
650
+ if (paramSets.length === 0) {
652
651
  results.push({
653
652
  route: route.pattern,
654
653
  status: "skipped",
@@ -44,7 +44,8 @@ type AppRouterConfig = {
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
46
  inlineCss?: boolean; /** Enables Next.js Cache Components semantics for App Router document HTML. */
47
- cacheComponents?: boolean; /** Internationalization routing config for middleware matcher locale handling. */
47
+ cacheComponents?: boolean; /** Whether the RSC build discovered any server references. Defaults to true. */
48
+ hasServerActions?: boolean; /** Internationalization routing config for middleware matcher locale handling. */
48
49
  i18n?: NextI18nConfig | null;
49
50
  imageConfig?: ImageConfig;
50
51
  /**
@@ -20,6 +20,8 @@ const middlewareRequestHeadersPath = resolveEntryPath("../server/middleware-requ
20
20
  const normalizePathModulePath = resolveEntryPath("../server/normalize-path.js", import.meta.url);
21
21
  const appRouteHandlerDispatchPath = resolveEntryPath("../server/app-route-handler-dispatch.js", import.meta.url);
22
22
  const appRouteHandlerResponsePath = resolveEntryPath("../server/app-route-handler-response.js", import.meta.url);
23
+ const appMiddlewarePath = resolveEntryPath("../server/app-middleware.js", import.meta.url);
24
+ const metadataRouteResponsePath = resolveEntryPath("../server/metadata-route-response.js", import.meta.url);
23
25
  const appServerActionExecutionPath = resolveEntryPath("../server/app-server-action-execution.js", import.meta.url);
24
26
  const appRscErrorsPath = resolveEntryPath("../server/app-rsc-errors.js", import.meta.url);
25
27
  const appPageExecutionPath = resolveEntryPath("../server/app-page-execution.js", import.meta.url);
@@ -73,6 +75,7 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
73
75
  const cacheMaxMemorySize = config?.cacheMaxMemorySize;
74
76
  const inlineCss = config?.inlineCss === true;
75
77
  const cacheComponents = config?.cacheComponents === true;
78
+ const hasServerActions = config?.hasServerActions !== false;
76
79
  const i18nConfig = config?.i18n ?? null;
77
80
  const hasPagesDir = config?.hasPagesDir ?? false;
78
81
  const publicFiles = config?.publicFiles ?? [];
@@ -93,12 +96,12 @@ async function __loadPrerenderPagesRoutes() {
93
96
  import ${JSON.stringify(serverGlobalsPath)};
94
97
  import {
95
98
  renderToReadableStream as _renderToReadableStream,
96
- decodeAction,
99
+ ${hasServerActions ? `decodeAction,
97
100
  decodeFormState,
98
101
  decodeReply,
99
102
  loadServerAction,
100
- createTemporaryReferenceSet,
101
- } from "@vitejs/plugin-rsc/rsc";
103
+ createTemporaryReferenceSet,` : ""}
104
+ } from ${JSON.stringify(hasServerActions ? "@vitejs/plugin-rsc/rsc" : "@vitejs/plugin-rsc/react/rsc")};
102
105
  import { createClientManifest as _createClientManifest } from "@vitejs/plugin-rsc/core/rsc";
103
106
  import { prerender as _prerender } from "@vitejs/plugin-rsc/vendor/react-server-dom/static.edge";
104
107
  import { createRscPrerenderer, createRscRenderer } from ${JSON.stringify(rscStreamHintsPath)};
@@ -112,7 +115,8 @@ import { getNavigationContext as _getNavigationContext } from "next/navigation";
112
115
  import { configureMemoryCacheHandler as __configureMemoryCacheHandler } from "vinext/shims/cache-handler";
113
116
  import { headersContextFromRequest, getDraftModeCookieHeader, getAndClearPendingCookies, consumeDynamicUsage, consumeInvalidDynamicUsageError, setHeadersAccessPhase } from "next/headers";
114
117
  import { mergeMetadata, resolveModuleMetadata, mergeViewport, resolveModuleViewport } from "vinext/metadata";
115
- ${middlewarePath ? `import * as middlewareModule from ${JSON.stringify(normalizePathSeparators(middlewarePath))};` : ""}
118
+ ${middlewarePath ? `import * as middlewareModule from ${JSON.stringify(normalizePathSeparators(middlewarePath))};
119
+ import { applyAppMiddleware as __applyAppMiddleware } from ${JSON.stringify(appMiddlewarePath)};` : ""}
116
120
  ${instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(normalizePathSeparators(instrumentationPath))};
117
121
  import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(instrumentationRuntimePath)};` : ""}
118
122
  import { createAppRscHandler } from "vinext/server/app-rsc-handler";
@@ -123,7 +127,8 @@ ${hasPagesDir ? `import {
123
127
  applyRouteHandlerMiddlewareContext as __applyRouteHandlerMiddlewareContext,
124
128
  } from ${JSON.stringify(appRouteHandlerResponsePath)};` : ""}
125
129
  const __loadAppRouteHandlerDispatch = () => import(${JSON.stringify(appRouteHandlerDispatchPath)});
126
- const __loadAppServerActionExecution = () => import(${JSON.stringify(appServerActionExecutionPath)});
130
+ ${hasServerActions ? `const __loadAppServerActionExecution = () => import(${JSON.stringify(appServerActionExecutionPath)});` : ""}
131
+ ${(metadataRoutes?.length ?? 0) > 0 ? `const __loadMetadataRouteResponse = () => import(${JSON.stringify(metadataRouteResponsePath)});` : ""}
127
132
  import {
128
133
  sanitizeErrorForClient as __sanitizeErrorForClient,
129
134
  } from ${JSON.stringify(appRscErrorsPath)};
@@ -683,6 +688,7 @@ export default createAppRscHandler({
683
688
  ${instrumentationPath ? `ensureInstrumentation() {
684
689
  return __ensureInstrumentationRegistered(_instrumentation);
685
690
  },` : ""}
691
+ ${hasServerActions ? `
686
692
  async handleProgressiveActionRequest({
687
693
  actionId,
688
694
  cleanPathname,
@@ -860,14 +866,33 @@ export default createAppRscHandler({
860
866
  },
861
867
  });
862
868
  },
869
+ ` : ""}
863
870
  i18nConfig: __i18nConfig,
864
- isMiddlewareProxy: ${JSON.stringify(middlewarePath ? isProxyFile(middlewarePath) : false)},
865
871
  ${hasPagesDir ? `loadPrerenderPagesRoutes: __loadPrerenderPagesRoutes,` : ""}
866
- makeThenableParams,
872
+ ${(metadataRoutes?.length ?? 0) > 0 ? `async handleMetadataRouteRequest(cleanPathname) {
873
+ const { handleMetadataRouteRequest: __handleMetadataRouteRequest } =
874
+ await __loadMetadataRouteResponse();
875
+ return __handleMetadataRouteRequest({
876
+ metadataRoutes,
877
+ cleanPathname,
878
+ makeThenableParams,
879
+ });
880
+ },` : ""}
867
881
  matchRoute,
868
- metadataRoutes,
869
- middlewareFilePath: ${middlewarePath ? JSON.stringify(normalizePathSeparators(middlewarePath)) : "null"},
870
- middlewareModule: ${middlewarePath ? "middlewareModule" : "null"},
882
+ ${middlewarePath ? `runMiddleware({ cleanPathname, context, isDataRequest, request }) {
883
+ return __applyAppMiddleware({
884
+ basePath: __basePath,
885
+ cleanPathname,
886
+ context,
887
+ filePath: ${JSON.stringify(middlewarePath ? normalizePathSeparators(middlewarePath) : "")},
888
+ i18nConfig: __i18nConfig,
889
+ isDataRequest,
890
+ isProxy: ${JSON.stringify(isProxyFile(middlewarePath))},
891
+ module: middlewareModule,
892
+ request,
893
+ trailingSlash: __trailingSlash,
894
+ });
895
+ },` : ""}
871
896
  publicFiles: __publicFiles,
872
897
  renderNotFound({ isRscRequest, matchedParams, middlewareContext, request, route, scriptNonce }) {
873
898
  const __isEdge = route ? __isEdgeRuntime(__resolveAppPageSegmentConfig({ layouts: route.layouts, page: route.page }).runtime) : false;
package/dist/index.js CHANGED
@@ -420,12 +420,16 @@ const _reactServerShims = new Map([
420
420
  ]);
421
421
  const clientManualChunks = createClientManualChunks(_shimsDir);
422
422
  const clientCodeSplittingConfig = createClientCodeSplittingConfig(clientManualChunks);
423
- function getClientOutputConfigForVite(viteMajorVersion, assetsDir) {
423
+ const appClientManualChunks = createClientManualChunks(_shimsDir, true);
424
+ const appClientCodeSplittingConfig = createClientCodeSplittingConfig(appClientManualChunks);
425
+ function getClientOutputConfigForVite(viteMajorVersion, assetsDir, preserveAppRouteBoundaries = false) {
426
+ const manualChunks = preserveAppRouteBoundaries ? appClientManualChunks : clientManualChunks;
427
+ const codeSplitting = preserveAppRouteBoundaries ? appClientCodeSplittingConfig : clientCodeSplittingConfig;
424
428
  return viteMajorVersion >= 8 ? {
425
429
  ...createClientFileNameConfig(assetsDir),
426
430
  assetFileNames: createClientAssetFileNames(assetsDir),
427
- codeSplitting: clientCodeSplittingConfig
428
- } : createClientOutputConfig(clientManualChunks, assetsDir);
431
+ codeSplitting
432
+ } : createClientOutputConfig(manualChunks, assetsDir);
429
433
  }
430
434
  function vinext(options = {}) {
431
435
  const viteMajorVersion = getViteMajorVersion();
@@ -507,13 +511,16 @@ function vinext(options = {}) {
507
511
  let resolvedReactPath = null;
508
512
  let resolvedRscPath = null;
509
513
  let resolvedRscTransformsPath = null;
514
+ let rscPluginModulePromise = null;
510
515
  resolvedReactPath = resolveOptionalDependency(earlyBaseDir, "@vitejs/plugin-react");
511
516
  resolvedRscPath = resolveOptionalDependency(earlyBaseDir, "@vitejs/plugin-rsc");
512
517
  resolvedRscTransformsPath = resolveOptionalDependency(earlyBaseDir, "@vitejs/plugin-rsc/transforms");
513
518
  let rscPluginPromise = null;
514
519
  if (earlyAppDirExists && autoRsc) {
515
520
  if (!resolvedRscPath) throw new Error("vinext: App Router detected but @vitejs/plugin-rsc is not installed.\nRun: " + detectPackageManager(process.cwd()) + " @vitejs/plugin-rsc");
516
- rscPluginPromise = import(pathToFileURL(resolvedRscPath).href).then((mod) => {
521
+ const rscImport = import(pathToFileURL(resolvedRscPath).href);
522
+ rscPluginModulePromise = rscImport;
523
+ rscPluginPromise = rscImport.then((mod) => {
517
524
  const rsc = mod.default;
518
525
  return rsc({ entries: {
519
526
  rsc: VIRTUAL_RSC_ENTRY,
@@ -890,6 +897,7 @@ function vinext(options = {}) {
890
897
  };
891
898
  const nextServerExternal = nextConfig?.serverExternalPackages ?? [];
892
899
  const userSsrExternal = Array.isArray(config.ssr?.external) ? [...config.ssr.external, ...nextServerExternal] : config.ssr?.external === true ? true : nextServerExternal;
900
+ const externalizeSsrReactInDev = env.command === "serve" && !hasCloudflarePlugin && !hasNitroPlugin;
893
901
  const incomingExclude = config.optimizeDeps?.exclude ?? [];
894
902
  const incomingInclude = config.optimizeDeps?.include ?? [];
895
903
  const depOptimizeAliasPlugin = {
@@ -944,11 +952,15 @@ function vinext(options = {}) {
944
952
  },
945
953
  ssr: {
946
954
  ...hasCloudflarePlugin || hasNitroPlugin ? {} : { resolve: {
947
- external: userSsrExternal === true ? true : [...userSsrExternal, "ipaddr.js"],
955
+ external: userSsrExternal === true ? true : [
956
+ ...userSsrExternal,
957
+ "ipaddr.js",
958
+ ...externalizeSsrReactInDev ? SSR_EXTERNAL_REACT_ENTRIES : []
959
+ ],
948
960
  ...userSsrExternal === true ? {} : { noExternal: true }
949
961
  } },
950
962
  optimizeDeps: {
951
- exclude: mergeOptimizeDepsExclude(incomingExclude, VINEXT_OPTIMIZE_DEPS_EXCLUDE, ["ipaddr.js"], userSsrExternal === true ? SSR_EXTERNAL_REACT_ENTRIES : []),
963
+ exclude: mergeOptimizeDepsExclude(incomingExclude, VINEXT_OPTIMIZE_DEPS_EXCLUDE, ["ipaddr.js"], userSsrExternal === true || externalizeSsrReactInDev ? SSR_EXTERNAL_REACT_ENTRIES : []),
952
964
  entries: optimizeEntries,
953
965
  ...depOptimizeNodeEnvOptions
954
966
  },
@@ -977,7 +989,7 @@ function vinext(options = {}) {
977
989
  assetsInlineLimit: clientAssetsInlineLimit,
978
990
  ...withBuildBundlerOptions(viteMajorVersion, {
979
991
  input: appClientInput,
980
- output: getClientOutputConfigForVite(viteMajorVersion, clientAssetsDir),
992
+ output: getClientOutputConfigForVite(viteMajorVersion, clientAssetsDir, true),
981
993
  treeshake: getClientTreeshakeConfigForVite(viteMajorVersion)
982
994
  })
983
995
  }
@@ -1127,6 +1139,12 @@ function vinext(options = {}) {
1127
1139
  if (id === RESOLVED_RSC_ENTRY && hasAppDir) {
1128
1140
  const routes = await appRouter(appDir, nextConfig?.pageExtensions, fileMatcher);
1129
1141
  const metaRoutes = scanMetadataFiles(appDir);
1142
+ let hasServerActions = true;
1143
+ if (this.environment?.config.command === "build" && rscPluginModulePromise) {
1144
+ const { getPluginApi } = await rscPluginModulePromise;
1145
+ const pluginApi = getPluginApi(this.environment.config);
1146
+ if (pluginApi && !pluginApi.manager.isScanBuild) hasServerActions = Object.keys(pluginApi.manager.serverReferenceMetaMap).length > 0;
1147
+ }
1130
1148
  const globalErrorPath = findFileWithExts(appDir, "global-error", fileMatcher);
1131
1149
  const globalNotFoundPath = findFileWithExts(appDir, "global-not-found", fileMatcher);
1132
1150
  rscClassificationManifest = collectRouteClassificationManifest(routes);
@@ -1146,6 +1164,7 @@ function vinext(options = {}) {
1146
1164
  cacheMaxMemorySize: nextConfig?.cacheMaxMemorySize,
1147
1165
  inlineCss: nextConfig?.inlineCss,
1148
1166
  cacheComponents: nextConfig?.cacheComponents,
1167
+ hasServerActions,
1149
1168
  i18n: nextConfig?.i18n,
1150
1169
  imageConfig: {
1151
1170
  deviceSizes: nextConfig?.images?.deviceSizes,
@@ -1304,15 +1323,19 @@ function vinext(options = {}) {
1304
1323
  const hook = mdxDelegate.config;
1305
1324
  return (typeof hook === "function" ? hook : hook.handler).call(this, config, env);
1306
1325
  },
1307
- async transform(code, id, options) {
1308
- if (id.includes("?")) return;
1309
- if (!id.toLowerCase().endsWith(".mdx")) return;
1310
- const delegate = mdxDelegate ?? await ensureMdxDelegate("on-demand");
1311
- if (delegate?.transform) {
1312
- const hook = delegate.transform;
1313
- return (typeof hook === "function" ? hook : hook.handler).call(this, code, id, options);
1326
+ transform: {
1327
+ filter: { id: {
1328
+ include: /\.mdx$/i,
1329
+ exclude: /\?/
1330
+ } },
1331
+ async handler(code, id, options) {
1332
+ const delegate = mdxDelegate ?? await ensureMdxDelegate("on-demand");
1333
+ if (delegate?.transform) {
1334
+ const hook = delegate.transform;
1335
+ return (typeof hook === "function" ? hook : hook.handler).call(this, code, id, options);
1336
+ }
1337
+ if (!hasUserMdxPlugin) throw new Error(`[vinext] Encountered MDX module ${id} but no MDX plugin is configured. Install @mdx-js/rollup or register an MDX plugin manually.`);
1314
1338
  }
1315
- if (!hasUserMdxPlugin) throw new Error(`[vinext] Encountered MDX module ${id} but no MDX plugin is configured. Install @mdx-js/rollup or register an MDX plugin manually.`);
1316
1339
  }
1317
1340
  },
1318
1341
  {
@@ -1358,6 +1381,7 @@ function vinext(options = {}) {
1358
1381
  configureServer(server) {
1359
1382
  const pageExtensions = fileMatcher.extensionRegex;
1360
1383
  let pagesRunner = null;
1384
+ let cachedSSRHandler = null;
1361
1385
  function getPagesRunner() {
1362
1386
  if (!pagesRunner) pagesRunner = createDirectRunner(server.environments["ssr"] ?? Object.values(server.environments).find((e) => e !== server.environments["rsc"]) ?? Object.values(server.environments)[0]);
1363
1387
  return pagesRunner;
@@ -1843,12 +1867,15 @@ function vinext(options = {}) {
1843
1867
  const appMatch = matchAppRoute(resolvedPathname, await appRouter(appDir, nextConfig?.pageExtensions, fileMatcher));
1844
1868
  if (appMatch && !pagesRouteHasPriorityOverAppRoute(renderMatch.route, appMatch.route)) return next();
1845
1869
  }
1846
- const handler = createSSRHandler(server, getPagesRunner(), routes, pagesDir, nextConfig?.i18n, fileMatcher, nextConfig?.basePath ?? "", nextConfig?.trailingSlash ?? false, middlewarePath !== null, (nextConfig?.rewrites.beforeFiles.length ?? 0) > 0 || (nextConfig?.rewrites.afterFiles.length ?? 0) > 0 || (nextConfig?.rewrites.fallback.length ?? 0) > 0, nextConfig?.clientTraceMetadata, nextConfig?.htmlLimitedBots);
1870
+ if (!cachedSSRHandler || cachedSSRHandler.routes !== routes) cachedSSRHandler = {
1871
+ routes,
1872
+ handler: createSSRHandler(server, getPagesRunner(), routes, pagesDir, nextConfig?.i18n, fileMatcher, nextConfig?.basePath ?? "", nextConfig?.trailingSlash ?? false, middlewarePath !== null, (nextConfig?.rewrites.beforeFiles.length ?? 0) > 0 || (nextConfig?.rewrites.afterFiles.length ?? 0) > 0 || (nextConfig?.rewrites.fallback.length ?? 0) > 0, nextConfig?.clientTraceMetadata, nextConfig?.htmlLimitedBots)
1873
+ };
1847
1874
  flushStagedHeaders();
1848
1875
  flushRequestHeaders();
1849
1876
  if (pipelineResult.middlewareStatus !== void 0) req.__vinextMiddlewareStatus = pipelineResult.middlewareStatus;
1850
1877
  req.url = pipelineResult.resolvedUrl;
1851
- await handler(req, res, pipelineResult.resolvedUrl, req.__vinextMiddlewareStatus, pipelineResult.isDataReq, originalRequestUrl);
1878
+ await cachedSSRHandler.handler(req, res, pipelineResult.resolvedUrl, req.__vinextMiddlewareStatus, pipelineResult.isDataReq, originalRequestUrl);
1852
1879
  }
1853
1880
  } catch (e) {
1854
1881
  next(e);
@@ -2068,7 +2095,7 @@ function vinext(options = {}) {
2068
2095
  imageImports.add(absImagePath);
2069
2096
  const urlVar = `__vinext_img_url_${varName}`;
2070
2097
  const metaVar = `__vinext_img_meta_${varName}`;
2071
- const replacement = `import ${urlVar} from ${JSON.stringify(absImagePath + "?vinext-image-url")};\nimport ${metaVar} from ${JSON.stringify(absImagePath + "?vinext-meta")};\nconst ${varName} = { src: ${urlVar}, width: ${metaVar}.width, height: ${metaVar}.height };`;
2098
+ const replacement = `import ${urlVar} from ${JSON.stringify(absImagePath + "?vinext-image-url")};\nimport ${metaVar} from ${JSON.stringify(absImagePath + "?vinext-meta")};\nvar ${varName} = { src: ${urlVar}, width: ${metaVar}.width, height: ${metaVar}.height };`;
2072
2099
  s.overwrite(importNode.start, importNode.end, replacement);
2073
2100
  hasChanges = true;
2074
2101
  }
@@ -2154,7 +2181,7 @@ function vinext(options = {}) {
2154
2181
  const { transformWrapExport, transformHoistInlineDirective } = await import(pathToFileURL(resolvedRscTransformsPath).href);
2155
2182
  if (cacheDirective) {
2156
2183
  const directiveValue = cacheDirective.expression.value;
2157
- const variant = directiveValue === "use cache" ? "" : directiveValue.replace("use cache:", "").replace("use cache: ", "").trim();
2184
+ const variant = directiveValue === "use cache" ? "" : directiveValue.replace("use cache:", "").trim();
2158
2185
  const isLayoutOrTemplate = /\/(layout|template)\.(tsx?|jsx?|mjs)$/.test(id);
2159
2186
  const modulePath = stripViteModuleQuery(id);
2160
2187
  const moduleFileName = path.basename(modulePath);
@@ -2194,7 +2221,7 @@ function vinext(options = {}) {
2194
2221
  directive: /^use cache(:\s*\w+)?$/,
2195
2222
  runtime: (value, name, meta) => {
2196
2223
  const directiveMatch = meta.directiveMatch[0];
2197
- const variant = directiveMatch === "use cache" ? "" : directiveMatch.replace("use cache:", "").replace("use cache: ", "").trim();
2224
+ const variant = directiveMatch === "use cache" ? "" : directiveMatch.replace("use cache:", "").trim();
2198
2225
  return `(await import(${JSON.stringify(runtimeModuleUrl2)})).registerCachedFunction(${value}, ${JSON.stringify(id + ":" + name)}, ${JSON.stringify(variant)})`;
2199
2226
  },
2200
2227
  rejectNonAsyncFunction: false
@@ -46,7 +46,7 @@ function createOgInlineFetchAssetsPlugin() {
46
46
  const boundary = await ownership.resolveModuleBoundary(id);
47
47
  if (boundary === null) return null;
48
48
  const { assetRoot, moduleDir } = boundary;
49
- let newCode = code;
49
+ const s = new MagicString(code);
50
50
  let didReplace = false;
51
51
  const readAsBase64 = async (absPath) => {
52
52
  const realPath = await ownership.resolveContainedAsset(assetRoot, absPath);
@@ -75,22 +75,22 @@ function createOgInlineFetchAssetsPlugin() {
75
75
  `return Promise.resolve(a.buffer);`,
76
76
  `})()`
77
77
  ].join("");
78
- newCode = newCode.replaceAll(fullMatch, inlined);
78
+ s.overwrite(match.index, match.index + fullMatch.length, inlined);
79
79
  didReplace = true;
80
80
  }
81
- if (code.includes("readFileSync(")) for (const match of newCode.matchAll(/[a-zA-Z_$][a-zA-Z0-9_$]*\.readFileSync\(\s*(?:[a-zA-Z_$][a-zA-Z0-9_$]*\.)?fileURLToPath\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)\s*\)/g)) {
81
+ if (code.includes("readFileSync(")) for (const match of code.matchAll(/[a-zA-Z_$][a-zA-Z0-9_$]*\.readFileSync\(\s*(?:[a-zA-Z_$][a-zA-Z0-9_$]*\.)?fileURLToPath\(\s*new URL\(\s*(["'])(\.[^"']+)\1\s*,\s*import\.meta\.url\s*\)\s*\)\s*\)/g)) {
82
82
  const fullMatch = match[0];
83
83
  const relPath = match[2];
84
84
  const fileBase64 = await readAsBase64(path.resolve(moduleDir, relPath));
85
85
  if (fileBase64 === null) continue;
86
86
  const inlined = `Buffer.from(${JSON.stringify(fileBase64)},"base64")`;
87
- newCode = newCode.replaceAll(fullMatch, inlined);
87
+ s.overwrite(match.index, match.index + fullMatch.length, inlined);
88
88
  didReplace = true;
89
89
  }
90
90
  if (!didReplace) return null;
91
91
  return {
92
- code: newCode,
93
- map: null
92
+ code: s.toString(),
93
+ map: s.generateMap({ hires: "boundary" })
94
94
  };
95
95
  }
96
96
  }
@@ -32,7 +32,6 @@ const SCOPE_ENTERING_TYPES = new Set([
32
32
  */
33
33
  function removeConsoleCalls(code, config) {
34
34
  if (config === false) return null;
35
- const excluded = typeof config === "object" ? new Set(config.exclude.map((s) => s.toLowerCase())) : /* @__PURE__ */ new Set();
36
35
  if (!code.match(/\bconsole\b/)) return null;
37
36
  let ast;
38
37
  try {
@@ -40,6 +39,7 @@ function removeConsoleCalls(code, config) {
40
39
  } catch {
41
40
  return null;
42
41
  }
42
+ const excluded = typeof config === "object" ? new Set(config.exclude.map((s) => s.toLowerCase())) : /* @__PURE__ */ new Set();
43
43
  const scopeStack = [{ shadowed: false }];
44
44
  function currentScope() {
45
45
  return scopeStack[scopeStack.length - 1];
@@ -13,7 +13,8 @@ const SERVER_EXPORTS = new Set([
13
13
  const SERVER_PROPS_SSG_CONFLICT = "You can not use getStaticProps or getStaticPaths with getServerSideProps. To use SSG, please remove getServerSideProps";
14
14
  const EXPORT_ALL_IN_PAGE_ERROR = "Using `export * from '...'` in a page is disallowed. Please use `export { default } from '...'` instead.\nRead more: https://nextjs.org/docs/messages/export-all-in-page";
15
15
  function hasServerExportCandidate(code) {
16
- return [...SERVER_EXPORTS].some((name) => code.includes(name));
16
+ for (const name of SERVER_EXPORTS) if (code.includes(name)) return true;
17
+ return false;
17
18
  }
18
19
  function hasExportAllCandidate(code) {
19
20
  let searchFrom = 0;
@@ -0,0 +1,4 @@
1
+ //#region src/server/app-action-request.d.ts
2
+ declare function isPossibleAppRouteActionRequest(request: Pick<Request, "headers" | "method">): boolean;
3
+ //#endregion
4
+ export { isPossibleAppRouteActionRequest };
@@ -0,0 +1,9 @@
1
+ import "./headers.js";
2
+ //#region src/server/app-action-request.ts
3
+ function isPossibleAppRouteActionRequest(request) {
4
+ if (request.method.toUpperCase() !== "POST") return false;
5
+ const contentType = request.headers.get("content-type");
6
+ return request.headers.has("x-rsc-action") || request.headers.has("next-action") || contentType === "application/x-www-form-urlencoded" || contentType?.startsWith("multipart/form-data") === true;
7
+ }
8
+ //#endregion
9
+ export { isPossibleAppRouteActionRequest };
@@ -1,13 +1,23 @@
1
- import { AppElements } from "./app-elements-wire.js";
1
+ import { AppElements, AppElementsWire } from "./app-elements-wire.js";
2
2
  import { BfcacheIdMap } from "./app-history-state.js";
3
3
 
4
4
  //#region src/server/app-bfcache-identity.d.ts
5
5
  type BfcacheStateKeyMap = Readonly<Record<string, string>>;
6
+ type InitialBfcacheMaps = Readonly<{
7
+ bfcacheIds: BfcacheIdMap;
8
+ stateKeys: BfcacheStateKeyMap;
9
+ }>;
10
+ type AppElementsMetadata = ReturnType<typeof AppElementsWire.readMetadata>;
6
11
  declare function createInitialBfcacheIdMap(elements: AppElements): BfcacheIdMap;
7
12
  declare function createBfcacheSegmentStateKeyMap(options: {
8
13
  elements: AppElements;
9
14
  pathname: string;
10
15
  }): BfcacheStateKeyMap;
16
+ declare function createInitialBfcacheMaps(options: {
17
+ elements: AppElements;
18
+ metadata: AppElementsMetadata;
19
+ pathname: string;
20
+ }): InitialBfcacheMaps;
11
21
  declare function createNextBfcacheIdMap(options: {
12
22
  current: BfcacheIdMap;
13
23
  currentElements: AppElements;
@@ -23,4 +33,4 @@ declare function preserveBfcacheIdsForMergedElements(options: {
23
33
  previous: BfcacheIdMap;
24
34
  }): BfcacheIdMap;
25
35
  //#endregion
26
- export { BfcacheStateKeyMap, createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements };
36
+ export { BfcacheStateKeyMap, InitialBfcacheMaps, createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createInitialBfcacheMaps, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements };
@@ -3,7 +3,6 @@ import { normalizePath } from "./normalize-path.js";
3
3
  import { AppElementsWire } from "./app-elements-wire.js";
4
4
  import "./app-elements.js";
5
5
  import "./app-bfcache-id.js";
6
- import { isBfcacheSegmentId } from "./app-history-state.js";
7
6
  //#region src/server/app-bfcache-identity.ts
8
7
  let nextBfcacheId = 0;
9
8
  function rememberBfcacheId(value) {
@@ -24,6 +23,14 @@ function getTreePathIdentityPrefix(pathname, treePath) {
24
23
  if (consumedPathnameSegments === 0) return "/";
25
24
  return `/${pathnameSegments.slice(0, consumedPathnameSegments).join("/")}`;
26
25
  }
26
+ function indexAppElementsMetadata(metadata) {
27
+ const slotBindingsBySlotId = /* @__PURE__ */ new Map();
28
+ for (const binding of metadata.slotBindings) slotBindingsBySlotId.set(binding.slotId, binding);
29
+ return {
30
+ metadata,
31
+ slotBindingsBySlotId
32
+ };
33
+ }
27
34
  function readAppElementsMetadata(elements) {
28
35
  let metadata;
29
36
  try {
@@ -31,12 +38,11 @@ function readAppElementsMetadata(elements) {
31
38
  } catch {
32
39
  return null;
33
40
  }
34
- const slotBindingsBySlotId = /* @__PURE__ */ new Map();
35
- for (const binding of metadata.slotBindings) slotBindingsBySlotId.set(binding.slotId, binding);
36
- return {
37
- metadata,
38
- slotBindingsBySlotId
39
- };
41
+ return indexAppElementsMetadata(metadata);
42
+ }
43
+ function parseBfcacheSegmentKey(id) {
44
+ const parsed = AppElementsWire.parseElementKey(id);
45
+ return parsed !== null && parsed.kind !== "route" ? parsed : null;
40
46
  }
41
47
  function createActiveSlotIdentity(id, parsed) {
42
48
  const activeSlotBinding = parsed?.slotBindingsBySlotId.get(id);
@@ -50,9 +56,7 @@ function createActiveSlotIdentity(id, parsed) {
50
56
  * contained here until vinext has a route-manifest authority equivalent to
51
57
  * Next.js CacheNode or segment-cache state.
52
58
  */
53
- function createBfcacheSegmentIdentity(id, options) {
54
- const parsed = AppElementsWire.parseElementKey(id);
55
- if (!parsed) return null;
59
+ function createBfcacheSegmentIdentity(id, parsed, options) {
56
60
  if (parsed.kind === "page") return `${id}@${options.pathname}`;
57
61
  if (parsed.kind === "slot") {
58
62
  const activeSlotIdentity = createActiveSlotIdentity(id, options.metadata);
@@ -62,16 +66,15 @@ function createBfcacheSegmentIdentity(id, options) {
62
66
  if (parsed.kind === "layout" || parsed.kind === "template") return `${id}@${getTreePathIdentityPrefix(options.pathname, parsed.treePath)}`;
63
67
  return null;
64
68
  }
65
- function collectBfcacheSegmentIds(elements, parsed) {
69
+ function collectBfcacheSegmentIdCandidates(elements, metadata = readAppElementsMetadata(elements)) {
66
70
  const ids = new Set(Object.keys(elements));
67
- const metadata = parsed === void 0 ? readAppElementsMetadata(elements) : parsed;
68
71
  for (const layoutId of metadata?.metadata.layoutIds ?? []) ids.add(layoutId);
69
- return Array.from(ids).filter(isBfcacheSegmentId);
72
+ return ids;
70
73
  }
71
74
  function createInitialBfcacheIdMap(elements) {
72
- const ids = {};
73
- for (const id of collectBfcacheSegmentIds(elements)) ids[id] = "0";
74
- return ids;
75
+ const bfcacheIds = {};
76
+ for (const id of collectBfcacheSegmentIdCandidates(elements)) if (parseBfcacheSegmentKey(id) !== null) bfcacheIds[id] = "0";
77
+ return bfcacheIds;
75
78
  }
76
79
  function normalizeBfcachePathname(pathname) {
77
80
  const normalized = normalizePath(normalizePathnameForRouteMatch(pathname));
@@ -81,8 +84,10 @@ function createBfcacheSegmentStateKeyMap(options) {
81
84
  const metadata = readAppElementsMetadata(options.elements);
82
85
  const normalizedPathname = normalizeBfcachePathname(options.pathname);
83
86
  const stateKeys = {};
84
- for (const id of collectBfcacheSegmentIds(options.elements, metadata)) {
85
- const stateKey = createBfcacheSegmentIdentity(id, {
87
+ for (const id of collectBfcacheSegmentIdCandidates(options.elements, metadata)) {
88
+ const parsed = parseBfcacheSegmentKey(id);
89
+ if (parsed === null) continue;
90
+ const stateKey = createBfcacheSegmentIdentity(id, parsed, {
86
91
  metadata,
87
92
  pathname: normalizedPathname
88
93
  });
@@ -90,6 +95,27 @@ function createBfcacheSegmentStateKeyMap(options) {
90
95
  }
91
96
  return stateKeys;
92
97
  }
98
+ function createInitialBfcacheMaps(options) {
99
+ const metadata = indexAppElementsMetadata(options.metadata);
100
+ const ids = collectBfcacheSegmentIdCandidates(options.elements, metadata);
101
+ const normalizedPathname = normalizeBfcachePathname(options.pathname);
102
+ const bfcacheIds = {};
103
+ const stateKeys = {};
104
+ for (const id of ids) {
105
+ const parsed = parseBfcacheSegmentKey(id);
106
+ if (parsed === null) continue;
107
+ bfcacheIds[id] = "0";
108
+ const stateKey = createBfcacheSegmentIdentity(id, parsed, {
109
+ metadata,
110
+ pathname: normalizedPathname
111
+ });
112
+ if (stateKey !== null) stateKeys[id] = stateKey;
113
+ }
114
+ return {
115
+ bfcacheIds,
116
+ stateKeys
117
+ };
118
+ }
93
119
  function createNextBfcacheIdMap(options) {
94
120
  const current = options.reuseCurrent === false ? {} : options.current;
95
121
  for (const value of Object.values(current)) rememberBfcacheId(value);
@@ -99,11 +125,13 @@ function createNextBfcacheIdMap(options) {
99
125
  const currentPathname = normalizeBfcachePathname(options.currentPathname);
100
126
  const nextPathname = normalizeBfcachePathname(options.nextPathname);
101
127
  const ids = {};
102
- for (const id of collectBfcacheSegmentIds(options.elements, nextMetadata)) {
103
- const currentValue = createBfcacheSegmentIdentity(id, {
128
+ for (const id of collectBfcacheSegmentIdCandidates(options.elements, nextMetadata)) {
129
+ const parsed = parseBfcacheSegmentKey(id);
130
+ if (parsed === null) continue;
131
+ const currentValue = createBfcacheSegmentIdentity(id, parsed, {
104
132
  metadata: currentMetadata,
105
133
  pathname: currentPathname
106
- }) === createBfcacheSegmentIdentity(id, {
134
+ }) === createBfcacheSegmentIdentity(id, parsed, {
107
135
  metadata: nextMetadata,
108
136
  pathname: nextPathname
109
137
  }) ? current[id] : void 0;
@@ -115,7 +143,8 @@ function createNextBfcacheIdMap(options) {
115
143
  }
116
144
  function preserveBfcacheIdsForMergedElements(options) {
117
145
  const ids = {};
118
- for (const id of collectBfcacheSegmentIds(options.elements)) {
146
+ for (const id of collectBfcacheSegmentIdCandidates(options.elements)) {
147
+ if (parseBfcacheSegmentKey(id) === null) continue;
119
148
  const value = options.next[id] ?? options.previous[id];
120
149
  if (value === void 0) continue;
121
150
  ids[id] = value;
@@ -124,4 +153,4 @@ function preserveBfcacheIdsForMergedElements(options) {
124
153
  return ids;
125
154
  }
126
155
  //#endregion
127
- export { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements };
156
+ export { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap, createInitialBfcacheMaps, createNextBfcacheIdMap, preserveBfcacheIdsForMergedElements };
@@ -63,7 +63,6 @@ declare function createHistoryStateWithNavigationMetadata(state: unknown, metada
63
63
  }): HistoryStateRecord | null;
64
64
  declare function createExternalHistoryStatePreservingMetadata(callerState: unknown, currentHistoryState: unknown): unknown;
65
65
  declare function readHistoryStatePreviousNextUrl(state: unknown): string | null;
66
- declare function isBfcacheSegmentId(id: string): boolean;
67
66
  declare function readHistoryStateBfcacheIds(state: unknown): BfcacheIdMap | null;
68
67
  declare function readHistoryStateBfcacheVersion(state: unknown): number | null;
69
68
  /**
@@ -83,4 +82,4 @@ declare function resolveHistoryTraversalIntent(options: {
83
82
  historyState: unknown;
84
83
  }): HistoryTraversalIntent;
85
84
  //#endregion
86
- export { BfcacheIdMap, HistoryStateSnapshotCache, HistoryTraversalIntent, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isBfcacheSegmentId, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
85
+ export { BfcacheIdMap, HistoryStateSnapshotCache, HistoryTraversalIntent, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
@@ -220,4 +220,4 @@ function resolveHistoryTraversalIntent(options) {
220
220
  };
221
221
  }
222
222
  //#endregion
223
- export { HistoryStateSnapshotCache, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isBfcacheSegmentId, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
223
+ export { HistoryStateSnapshotCache, RestorableClientStateController, createExternalHistoryStatePreservingMetadata, createHashOnlyHistoryStatePreservingNavigationMetadata, createHistoryStateWithNavigationMetadata, createHistoryStateWithPreviousNextUrl, isHistoryStateBfcacheVersionCurrent, readHistoryStateBfcacheIds, readHistoryStateBfcacheVersion, readHistoryStatePreviousNextUrl, readHistoryStateTraversalIndex, resolveHistoryTraversalIntent };
@@ -1,6 +1,6 @@
1
1
  import { methodNotAllowedResponse } from "./http-error-responses.js";
2
2
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
3
- import { isPossibleAppRouteActionRequest } from "./app-route-handler-policy.js";
3
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
4
4
  //#region src/server/app-page-method.ts
5
5
  function isNonGetOrHead(method) {
6
6
  const normalizedMethod = method.toUpperCase();
@@ -1,3 +1,4 @@
1
+ import { isNavigationSignalError } from "../utils/navigation-signal.js";
1
2
  import { VINEXT_RSC_VARY_HEADER } from "./app-rsc-cache-busting.js";
2
3
  import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
3
4
  import { applyEdgeRuntimeHeader } from "./app-page-response.js";
@@ -131,7 +132,7 @@ function createAppPageRscErrorTracker(baseOnError) {
131
132
  return capturedSpecialError;
132
133
  },
133
134
  onRenderError(error, requestInfo, errorContext) {
134
- if (error && typeof error === "object" && "digest" in error) {
135
+ if (isNavigationSignalError(error)) {
135
136
  if (capturedSpecialError === null) capturedSpecialError = error;
136
137
  } else capturedError = error;
137
138
  return baseOnError(error, requestInfo, errorContext);
@@ -1,6 +1,6 @@
1
1
  import { makeThenableParams } from "../shims/thenable-params.js";
2
- import { markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
3
2
  import { applyRouteHandlerMiddlewareContext, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, buildRouteHandlerCachedResponse } from "./app-route-handler-response.js";
3
+ import { markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
4
4
  import { runAppRouteHandler } from "./app-route-handler-execution.js";
5
5
  //#region src/server/app-route-handler-cache.ts
6
6
  const EMPTY_PARAMS = Object.freeze({});
@@ -7,10 +7,10 @@ import { setNavigationContext } from "../shims/navigation-context-state.js";
7
7
  import { makeThenableParams } from "../shims/thenable-params.js";
8
8
  import "../shims/navigation.js";
9
9
  import { buildPageCacheTags } from "./implicit-tags.js";
10
- import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
11
- import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
12
10
  import { applyRouteHandlerMiddlewareContext } from "./app-route-handler-response.js";
11
+ import { isKnownDynamicAppRoute, isValidHTTPMethod } from "./app-route-handler-runtime.js";
13
12
  import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
13
+ import { getAppRouteHandlerRevalidateSeconds, hasAppRouteHandlerDefaultExport, resolveAppRouteHandlerMethod, shouldReadAppRouteHandlerCache } from "./app-route-handler-policy.js";
14
14
  import { executeAppRouteHandler } from "./app-route-handler-execution.js";
15
15
  import { readAppRouteHandlerCacheResponse } from "./app-route-handler-cache.js";
16
16
  import { resolveAppRouteHandlerFetchCacheMode } from "./app-segment-config.js";
@@ -1,8 +1,9 @@
1
1
  import { setHeadersContext } from "../shims/headers.js";
2
- import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
3
- import { isPossibleAppRouteActionRequest, resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidateHeader, shouldWriteAppRouteHandlerCache } from "./app-route-handler-policy.js";
2
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
4
3
  import { applyRouteHandlerMiddlewareContext, applyRouteHandlerRevalidateHeader, assertSupportedAppRouteHandlerResponse, buildAppRouteCacheValue, finalizeRouteHandlerResponse, markRouteHandlerCacheMiss } from "./app-route-handler-response.js";
4
+ import { createTrackedAppRouteRequest, markKnownDynamicAppRoute } from "./app-route-handler-runtime.js";
5
5
  import { createStaticGenerationHeadersContext, getAppRouteStaticGenerationErrorMessage } from "./app-static-generation.js";
6
+ import { resolveAppRouteHandlerSpecialError, shouldApplyAppRouteHandlerRevalidateHeader, shouldWriteAppRouteHandlerCache } from "./app-route-handler-policy.js";
6
7
  //#region src/server/app-route-handler-execution.ts
7
8
  function configureAppRouteStaticGenerationContext(options) {
8
9
  if (options.dynamicConfig === "force-static" || options.dynamicConfig === "error") {
@@ -1,3 +1,4 @@
1
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
1
2
  import { RouteHandlerHttpMethod, RouteHandlerModule } from "./app-route-handler-runtime.js";
2
3
 
3
4
  //#region src/server/app-route-handler-policy.d.ts
@@ -43,7 +44,6 @@ type AppRouteHandlerSpecialError = {
43
44
  type AppRouteHandlerSpecialErrorOptions = {
44
45
  isAction: boolean;
45
46
  };
46
- declare function isPossibleAppRouteActionRequest(request: Pick<Request, "headers" | "method">): boolean;
47
47
  declare function getAppRouteHandlerRevalidateSeconds(handler: Pick<AppRouteHandlerModule, "revalidate">): number | null;
48
48
  declare function hasAppRouteHandlerDefaultExport(handler: RouteHandlerModule): boolean;
49
49
  declare function resolveAppRouteHandlerMethod(handler: AppRouteHandlerModule, method: string): ResolvedAppRouteHandlerMethod;
@@ -1,12 +1,7 @@
1
- import "./headers.js";
2
1
  import { parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
2
+ import { isPossibleAppRouteActionRequest } from "./app-action-request.js";
3
3
  import { buildRouteHandlerAllowHeader, collectRouteHandlerMethods } from "./app-route-handler-runtime.js";
4
4
  //#region src/server/app-route-handler-policy.ts
5
- function isPossibleAppRouteActionRequest(request) {
6
- if (request.method.toUpperCase() !== "POST") return false;
7
- const contentType = request.headers.get("content-type");
8
- return request.headers.has("x-rsc-action") || request.headers.has("next-action") || contentType === "application/x-www-form-urlencoded" || contentType?.startsWith("multipart/form-data") === true;
9
- }
10
5
  function getAppRouteHandlerRevalidateSeconds(handler) {
11
6
  const { revalidate } = handler;
12
7
  if (revalidate === false) return Infinity;
@@ -19,6 +19,17 @@ type CreateRscOnErrorHandlerOptions = {
19
19
  declare function hasDigest(error: unknown): error is {
20
20
  digest: unknown;
21
21
  };
22
+ /**
23
+ * vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
24
+ * string only when the error is a genuine control-flow signal — a redirect,
25
+ * notFound/HTTP-access fallback, bail-out-to-client-side-rendering, or
26
+ * dynamic-server-usage throw. Any other digest (e.g. a hashed digest stamped on
27
+ * a real error, or an obfuscated digest transported from a nested boundary)
28
+ * returns undefined so the caller still reports it as a real error. Mere
29
+ * presence of a `digest` field is NOT enough — that conflation swallowed a class
30
+ * of server render errors with no instrumentation/telemetry.
31
+ */
32
+ declare function getDigestForWellKnownError(error: unknown): string | undefined;
22
33
  /**
23
34
  * djb2 hash matching Next.js's string-hash package for RSC error digests.
24
35
  */
@@ -26,4 +37,4 @@ declare function errorDigest(input: string): string;
26
37
  declare function sanitizeErrorForClient(error: unknown, nodeEnv?: string | undefined): unknown;
27
38
  declare function createRscOnErrorHandler(options: CreateRscOnErrorHandlerOptions): (error: unknown) => string | undefined;
28
39
  //#endregion
29
- export { createRscOnErrorHandler, errorDigest, hasDigest, sanitizeErrorForClient };
40
+ export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
@@ -1,8 +1,26 @@
1
+ import { isNavigationSignalError } from "../utils/navigation-signal.js";
1
2
  import { resolveAppPageSpecialError } from "./app-page-execution.js";
2
3
  //#region src/server/app-rsc-errors.ts
3
4
  function hasDigest(error) {
4
5
  return Boolean(error && typeof error === "object" && "digest" in error);
5
6
  }
7
+ const BAILOUT_TO_CSR_DIGEST = "BAILOUT_TO_CLIENT_SIDE_RENDERING";
8
+ const DYNAMIC_SERVER_USAGE_DIGEST = "DYNAMIC_SERVER_USAGE";
9
+ /**
10
+ * vinext's mirror of Next.js's `getDigestForWellKnownError`: returns the digest
11
+ * string only when the error is a genuine control-flow signal — a redirect,
12
+ * notFound/HTTP-access fallback, bail-out-to-client-side-rendering, or
13
+ * dynamic-server-usage throw. Any other digest (e.g. a hashed digest stamped on
14
+ * a real error, or an obfuscated digest transported from a nested boundary)
15
+ * returns undefined so the caller still reports it as a real error. Mere
16
+ * presence of a `digest` field is NOT enough — that conflation swallowed a class
17
+ * of server render errors with no instrumentation/telemetry.
18
+ */
19
+ function getDigestForWellKnownError(error) {
20
+ if (!hasDigest(error)) return;
21
+ const digest = String(error.digest);
22
+ if (isNavigationSignalError(error) || digest === BAILOUT_TO_CSR_DIGEST || digest === DYNAMIC_SERVER_USAGE_DIGEST) return digest;
23
+ }
6
24
  function getThrownValueMessage(error) {
7
25
  return error instanceof Error ? error.message : String(error);
8
26
  }
@@ -27,14 +45,16 @@ function sanitizeErrorForClient(error, nodeEnv = process.env.NODE_ENV) {
27
45
  function createRscOnErrorHandler(options) {
28
46
  return (error) => {
29
47
  const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV;
30
- if (hasDigest(error)) return String(error.digest);
48
+ const wellKnownDigest = getDigestForWellKnownError(error);
49
+ if (wellKnownDigest !== void 0) return wellKnownDigest;
31
50
  if (nodeEnv !== "production" && error instanceof Error && error.message.includes("Only plain objects, and a few built-ins, can be passed to Client Components")) {
32
51
  console.error("[vinext] RSC serialization error: a non-plain object was passed from a Server Component to a Client Component.\n\nCommon causes:\n * Passing a module namespace (import * as X) directly as a prop.\n Unlike Next.js (webpack), Vite produces real ESM module namespace objects\n which are not serializable. Fix: pass individual values instead,\n e.g. <Comp value={module.value} />\n * Passing a class instance (new Foo()) as a prop.\n Fix: convert to a plain object, e.g. { id: foo.id, name: foo.name }\n * Passing a Date, Map, or Set. Use .toISOString(), [...map.entries()], etc.\n * Passing Object.create(null). Use { ...obj } to restore a prototype.\n\nOriginal error:", error.message);
33
52
  return;
34
53
  }
35
54
  if (options.requestInfo && options.errorContext && error) options.reportRequestError(error instanceof Error ? error : new Error(getThrownValueMessage(error)), options.requestInfo, options.errorContext);
55
+ if (hasDigest(error)) return String(error.digest);
36
56
  if (nodeEnv === "production" && error) return errorDigest(getThrownValueMessage(error) + getThrownValueStack(error));
37
57
  };
38
58
  }
39
59
  //#endregion
40
- export { createRscOnErrorHandler, errorDigest, hasDigest, sanitizeErrorForClient };
60
+ export { createRscOnErrorHandler, errorDigest, getDigestForWellKnownError, hasDigest, sanitizeErrorForClient };
@@ -2,21 +2,25 @@ import { NextHeader, NextI18nConfig, NextRedirect, NextRewrite } from "../config
2
2
  import { ImageConfig } from "./image-optimization.js";
3
3
  import { ClientReuseManifestParseResult } from "./client-reuse-manifest.js";
4
4
  import { RootParams } from "../shims/root-params.js";
5
- import { MiddlewareModule } from "./middleware-runtime.js";
6
- import { AppMiddlewareContext } from "./app-middleware.js";
5
+ import { AppMiddlewareContext, ApplyAppMiddlewareResult } from "./app-middleware.js";
7
6
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
8
7
  import { AppPrerenderRootParamNamesMap, AppPrerenderStaticParamsMap } from "./app-prerender-endpoints.js";
9
- import { MetadataRouteMakeThenableParams, MetadataRuntimeRoute } from "./metadata-route-response.js";
10
8
  import { ReactFormState } from "react-dom/client";
11
9
 
12
10
  //#region src/server/app-rsc-handler.d.ts
13
11
  type AppPageParams = Record<string, string | string[]>;
14
- type MetadataRoutes = readonly MetadataRuntimeRoute[];
15
- type MakeThenableParams = MetadataRouteMakeThenableParams;
16
12
  type StaticParamsMap = AppPrerenderStaticParamsMap;
17
13
  type RootParamNamesMap = AppPrerenderRootParamNamesMap;
18
14
  type AppRscMiddlewareContext = AppMiddlewareContext;
15
+ type RunAppMiddlewareOptions = {
16
+ cleanPathname: string;
17
+ context: AppRscMiddlewareContext;
18
+ isDataRequest: boolean;
19
+ request: Request;
20
+ };
19
21
  type AppRscHandlerRoute = {
22
+ __loadPage?: unknown;
23
+ __loadRouteHandler?: unknown;
20
24
  isDynamic: boolean;
21
25
  params?: readonly string[];
22
26
  page?: unknown;
@@ -173,18 +177,15 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
173
177
  * Node server and dev included, not just the Cloudflare worker entry.
174
178
  */
175
179
  registerCacheAdapters: (env?: Record<string, unknown>) => void;
176
- handleProgressiveActionRequest: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
177
- handleServerActionRequest: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
180
+ handleProgressiveActionRequest?: (options: HandleProgressiveActionRequestOptions) => Promise<Response | ProgressiveActionFormStateResult | null>;
181
+ handleMetadataRouteRequest?: (cleanPathname: string) => Promise<Response | null>;
182
+ handleServerActionRequest?: (options: HandleServerActionRequestOptions) => Promise<Response | null>;
178
183
  i18nConfig: NextI18nConfig | null;
179
184
  imageConfig?: ImageConfig;
180
185
  isDev: boolean;
181
- isMiddlewareProxy: boolean;
182
186
  loadPrerenderPagesRoutes?: () => Promise<unknown>;
183
- makeThenableParams: MakeThenableParams;
184
187
  matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;
185
- metadataRoutes: MetadataRoutes;
186
- middlewareFilePath: string | null;
187
- middlewareModule: MiddlewareModule | null;
188
+ runMiddleware?: (options: RunAppMiddlewareOptions) => Promise<ApplyAppMiddlewareResult>;
188
189
  publicFiles: ReadonlySet<string>;
189
190
  renderNotFound: (options: RenderNotFoundOptions<TRoute>) => Promise<Response | null>;
190
191
  renderPagesFallback?: (options: RenderPagesFallbackOptions) => Promise<Response | null>;
@@ -17,8 +17,9 @@ import "./app-page-response.js";
17
17
  import { buildNextDataNotFoundResponse, normalizePagesDataRequest } from "./pages-data-route.js";
18
18
  import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
19
19
  import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
20
- import { pickRootParams, setRootParams } from "../shims/root-params.js";
21
20
  import { flattenErrorCauses } from "../utils/error-cause.js";
21
+ import { pickRootParams, setRootParams } from "../shims/root-params.js";
22
+ import { createServerActionNotFoundResponse, getServerActionNotFoundMessage } from "./server-action-not-found.js";
22
23
  import { buildPageCacheTags } from "./implicit-tags.js";
23
24
  import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
24
25
  import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
@@ -47,6 +48,11 @@ function isExecutionContextLike(value) {
47
48
  if (!value || typeof value !== "object") return false;
48
49
  return hasProperty(value, "waitUntil") && typeof value.waitUntil === "function";
49
50
  }
51
+ function createMissingServerActionResponse(options, actionId) {
52
+ console.warn(getServerActionNotFoundMessage(actionId));
53
+ options.clearRequestContext();
54
+ return createServerActionNotFoundResponse();
55
+ }
50
56
  function redirectDestinationWithBasePath(destination, basePath) {
51
57
  if (!basePath || isExternalUrl(destination) || hasBasePath(destination, basePath)) return destination;
52
58
  return basePath + destination;
@@ -165,19 +171,12 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
165
171
  status: null
166
172
  };
167
173
  let didMiddlewareRewrite = false;
168
- if (options.middlewareModule) {
169
- const { applyAppMiddleware } = await import("./app-middleware.js");
170
- const middlewareResult = await applyAppMiddleware({
171
- basePath: options.basePath,
174
+ if (options.runMiddleware) {
175
+ const middlewareResult = await options.runMiddleware({
172
176
  cleanPathname,
173
177
  context: middlewareContext,
174
- filePath: options.middlewareFilePath ?? void 0,
175
- i18nConfig: options.i18nConfig,
176
178
  isDataRequest,
177
- isProxy: options.isMiddlewareProxy,
178
- module: options.middlewareModule,
179
- request: userlandRequest,
180
- trailingSlash: options.trailingSlash
179
+ request: userlandRequest
181
180
  });
182
181
  if (middlewareResult.kind === "response") return applyConfigHeadersToMiddlewareRedirect(middlewareResult.response, {
183
182
  basePathState,
@@ -211,13 +210,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
211
210
  if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
212
211
  return Response.redirect(new URL(imageRedirect, url.origin).href, 302);
213
212
  }
214
- if (options.metadataRoutes.length > 0) {
215
- const { handleMetadataRouteRequest } = await import("./metadata-route-response.js");
216
- const metadataRouteResponse = await handleMetadataRouteRequest({
217
- metadataRoutes: options.metadataRoutes,
218
- cleanPathname,
219
- makeThenableParams: options.makeThenableParams
220
- });
213
+ if (options.handleMetadataRouteRequest) {
214
+ const metadataRouteResponse = await options.handleMetadataRouteRequest(cleanPathname);
221
215
  if (metadataRouteResponse) {
222
216
  applyConfigHeadersToResponse(metadataRouteResponse.headers, {
223
217
  basePathState,
@@ -255,13 +249,16 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
255
249
  const contentType = request.headers.get("content-type") || "";
256
250
  const isPostRequest = request.method.toUpperCase() === "POST";
257
251
  let progressiveActionResult = null;
258
- if (isPostRequest && contentType.startsWith("multipart/form-data") && !actionId) progressiveActionResult = await options.handleProgressiveActionRequest({
259
- actionId,
260
- cleanPathname,
261
- contentType,
262
- middlewareContext,
263
- request
264
- });
252
+ if (isPostRequest && contentType.startsWith("multipart/form-data") && !actionId) {
253
+ if (options.handleProgressiveActionRequest) progressiveActionResult = await options.handleProgressiveActionRequest({
254
+ actionId,
255
+ cleanPathname,
256
+ contentType,
257
+ middlewareContext,
258
+ request
259
+ });
260
+ else if (preActionMatch?.route.__loadPage && !preActionMatch.route.__loadRouteHandler) return createMissingServerActionResponse(options, null);
261
+ }
265
262
  if (progressiveActionResult instanceof Response) return progressiveActionResult;
266
263
  const progressiveActionFormState = progressiveActionResult?.kind === "form-state" ? progressiveActionResult : null;
267
264
  const isProgressiveActionRender = progressiveActionFormState !== null;
@@ -269,7 +266,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
269
266
  const failedProgressiveActionResult = progressiveActionFormState && "actionError" in progressiveActionFormState ? progressiveActionFormState : null;
270
267
  const actionFailed = failedProgressiveActionResult !== null;
271
268
  const actionError = failedProgressiveActionResult?.actionError;
272
- const serverActionResponse = isPostRequest && actionId ? await options.handleServerActionRequest({
269
+ const serverActionResponse = isPostRequest && actionId && options.handleServerActionRequest ? await options.handleServerActionRequest({
273
270
  actionId,
274
271
  cleanPathname,
275
272
  contentType,
@@ -281,6 +278,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
281
278
  searchParams: getResolvedSearchParams()
282
279
  }) : null;
283
280
  if (serverActionResponse) return serverActionResponse;
281
+ if (isPostRequest && actionId && !options.handleServerActionRequest) return createMissingServerActionResponse(options, actionId);
284
282
  let match = preActionMatch;
285
283
  const renderPagesForMatchKind = async (matchKind) => {
286
284
  const response = match === null || match.route.isDynamic ? await options.renderPagesFallback?.({
@@ -22,7 +22,11 @@ import { mergeVaryHeader } from "./middleware-response-headers.js";
22
22
  */
23
23
  function finalizeAppRscResponse(response, request, options) {
24
24
  if (response.status >= 300 && response.status < 400) return response;
25
- if (!response.headers.has("x-vinext-static-file")) mergeVaryHeader(response.headers, VINEXT_RSC_VARY_HEADER);
25
+ if (!response.headers.has("x-vinext-static-file")) {
26
+ const varyHeader = response.headers.get("Vary");
27
+ if (varyHeader === null) response.headers.set("Vary", VINEXT_RSC_VARY_HEADER);
28
+ else if (varyHeader !== VINEXT_RSC_VARY_HEADER) mergeVaryHeader(response.headers, VINEXT_RSC_VARY_HEADER);
29
+ }
26
30
  if (!response.headers.has("Cache-Control")) applyCdnResponseHeaders(response.headers, { cacheControl: "" });
27
31
  if (!options.configHeaders.length) return response;
28
32
  const url = new URL(request.url);
@@ -377,7 +377,7 @@ async function handleProgressiveServerActionRequest(options) {
377
377
  options.setHeadersAccessPhase(previousHeadersPhase);
378
378
  }
379
379
  if (!actionRedirect) {
380
- const actionPendingCookies = options.getAndClearPendingCookies();
380
+ const actionPendingCookies = dedupePendingCookies(options.getAndClearPendingCookies());
381
381
  const actionDraftCookie = options.getDraftModeCookieHeader();
382
382
  const revalidationKind = resolveActionRevalidationKind(actionPendingCookies.length > 0 || Boolean(actionDraftCookie));
383
383
  if (actionFailed) return {
@@ -18,7 +18,7 @@ import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
18
18
  import { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform } from "./app-ssr-stream.js";
19
19
  import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
20
20
  import { runWithRootParamsScope } from "../shims/root-params.js";
21
- import { createBfcacheSegmentStateKeyMap, createInitialBfcacheIdMap } from "./app-bfcache-identity.js";
21
+ import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
22
22
  import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
23
23
  import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
24
24
  import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
@@ -186,12 +186,14 @@ async function handleSsr(rscStream, navContext, fontData, options) {
186
186
  const wireElements = use(flightRoot);
187
187
  const elements = AppElementsWire.decode(wireElements);
188
188
  const metadata = AppElementsWire.readMetadata(elements);
189
- const routeTree = createElement(ElementsContext.Provider, { value: elements }, createElement(Slot, { id: metadata.routeId }));
190
- const stateKeyTree = createElement(BfcacheStateKeyMapContext.Provider, { value: createBfcacheSegmentStateKeyMap({
189
+ const bfcacheMaps = createInitialBfcacheMaps({
191
190
  elements,
191
+ metadata,
192
192
  pathname: ssrNavigationContext.pathname
193
- }) }, routeTree);
194
- return BfcacheIdMapContext ? createElement(BfcacheIdMapContext.Provider, { value: createInitialBfcacheIdMap(elements) }, stateKeyTree) : stateKeyTree;
193
+ });
194
+ const routeTree = createElement(ElementsContext.Provider, { value: elements }, createElement(Slot, { id: metadata.routeId }));
195
+ const stateKeyTree = createElement(BfcacheStateKeyMapContext.Provider, { value: bfcacheMaps.stateKeys }, routeTree);
196
+ return BfcacheIdMapContext ? createElement(BfcacheIdMapContext.Provider, { value: bfcacheMaps.bfcacheIds }, stateKeyTree) : stateKeyTree;
195
197
  }
196
198
  const flightRootElement = createElement(VinextFlightRoot);
197
199
  const root = AppRouterContext ? createElement(AppRouterContext.Provider, { value: ssrAppRouterInstance }, flightRootElement) : flightRootElement;
@@ -13,4 +13,4 @@ type MetadataRouteRequestOptions = {
13
13
  };
14
14
  declare function handleMetadataRouteRequest(options: MetadataRouteRequestOptions): Promise<Response | null>;
15
15
  //#endregion
16
- export { MetadataRouteMakeThenableParams, MetadataRuntimeRoute, handleMetadataRouteRequest };
16
+ export { MetadataRuntimeRoute, handleMetadataRouteRequest };
@@ -127,7 +127,7 @@ function dynamic(dynamicInput, options) {
127
127
  const preloadModuleIds = loadableGenerated?.modules ?? modules;
128
128
  if (!ssr) {
129
129
  if (isServer) {
130
- const SSRFalse = (_props) => LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps({ pastDelay: false })) : null;
130
+ const SSRFalse = (_props) => LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps()) : null;
131
131
  SSRFalse.displayName = "DynamicSSRFalse";
132
132
  return SSRFalse;
133
133
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinext",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Run Next.js apps on Vite. Drop-in replacement for the next CLI.",
5
5
  "license": "MIT",
6
6
  "repository": {