vinext 0.2.0 → 1.0.0-beta.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 (168) hide show
  1. package/README.md +50 -29
  2. package/dist/build/client-build-config.d.ts +13 -92
  3. package/dist/build/client-build-config.js +17 -95
  4. package/dist/build/css-url-assets.d.ts +3 -1
  5. package/dist/build/css-url-assets.js +18 -1
  6. package/dist/build/inject-pregenerated-paths.d.ts +3 -0
  7. package/dist/build/inject-pregenerated-paths.js +4 -1
  8. package/dist/build/prerender-paths.d.ts +23 -0
  9. package/dist/build/prerender-paths.js +296 -0
  10. package/dist/build/prerender-server-entry.d.ts +1 -0
  11. package/dist/build/prerender-server-entry.js +49 -0
  12. package/dist/build/prerender-server-pool.d.ts +44 -0
  13. package/dist/build/prerender-server-pool.js +194 -0
  14. package/dist/build/prerender.d.ts +12 -1
  15. package/dist/build/prerender.js +87 -23
  16. package/dist/build/run-prerender.js +2 -1
  17. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  18. package/dist/cache/cache-adapters-virtual.js +26 -2
  19. package/dist/check.d.ts +4 -6
  20. package/dist/check.js +13 -9
  21. package/dist/cli.js +34 -54
  22. package/dist/client/vinext-next-data.d.ts +4 -1
  23. package/dist/config/config-matchers.js +33 -11
  24. package/dist/config/next-config.d.ts +36 -6
  25. package/dist/config/next-config.js +17 -4
  26. package/dist/config/prerender.d.ts +11 -1
  27. package/dist/config/prerender.js +19 -1
  28. package/dist/config/tsconfig-paths.js +5 -1
  29. package/dist/entries/app-browser-entry.js +5 -1
  30. package/dist/entries/app-rsc-entry.d.ts +3 -2
  31. package/dist/entries/app-rsc-entry.js +4 -0
  32. package/dist/entries/pages-client-entry.js +14 -3
  33. package/dist/entries/pages-server-entry.js +18 -4
  34. package/dist/image/image-adapters-virtual.js +1 -0
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.js +549 -152
  37. package/dist/init-cloudflare.js +12 -3
  38. package/dist/init-platform.d.ts +10 -1
  39. package/dist/init-platform.js +78 -12
  40. package/dist/init.d.ts +11 -3
  41. package/dist/init.js +129 -31
  42. package/dist/plugins/fonts.js +1 -1
  43. package/dist/plugins/ignore-dynamic-requests.js +1 -1
  44. package/dist/plugins/og-assets.js +2 -1
  45. package/dist/plugins/optimize-imports.js +1 -1
  46. package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
  47. package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
  48. package/dist/plugins/sass.d.ts +17 -1
  49. package/dist/plugins/sass.js +74 -1
  50. package/dist/plugins/styled-jsx.d.ts +16 -0
  51. package/dist/plugins/styled-jsx.js +149 -0
  52. package/dist/routing/app-route-graph.js +22 -16
  53. package/dist/routing/file-matcher.d.ts +8 -1
  54. package/dist/routing/file-matcher.js +15 -3
  55. package/dist/server/app-browser-entry.js +44 -14
  56. package/dist/server/app-browser-navigation-controller.js +5 -2
  57. package/dist/server/app-browser-server-action-client.js +5 -3
  58. package/dist/server/app-browser-state.d.ts +1 -0
  59. package/dist/server/app-browser-state.js +1 -1
  60. package/dist/server/app-layout-param-observation.d.ts +1 -1
  61. package/dist/server/app-page-boundary.js +2 -1
  62. package/dist/server/app-page-cache-finalizer.d.ts +1 -0
  63. package/dist/server/app-page-cache-finalizer.js +3 -3
  64. package/dist/server/app-page-cache-render.d.ts +1 -1
  65. package/dist/server/app-page-cache.js +23 -6
  66. package/dist/server/app-page-dispatch.d.ts +2 -1
  67. package/dist/server/app-page-dispatch.js +27 -10
  68. package/dist/server/app-page-element-builder.js +1 -0
  69. package/dist/server/app-page-execution.js +2 -1
  70. package/dist/server/app-page-render-identity.d.ts +1 -0
  71. package/dist/server/app-page-render-identity.js +2 -1
  72. package/dist/server/app-page-render.d.ts +3 -1
  73. package/dist/server/app-page-render.js +67 -16
  74. package/dist/server/app-page-response.d.ts +7 -0
  75. package/dist/server/app-page-response.js +16 -4
  76. package/dist/server/app-page-route-wiring.js +3 -3
  77. package/dist/server/app-page-stream.d.ts +2 -1
  78. package/dist/server/app-page-stream.js +1 -1
  79. package/dist/server/app-route-handler-execution.d.ts +1 -1
  80. package/dist/server/app-route-tree-prefetch.d.ts +43 -0
  81. package/dist/server/app-route-tree-prefetch.js +187 -0
  82. package/dist/server/app-router-entry.js +1 -1
  83. package/dist/server/app-rsc-cache-busting.d.ts +2 -1
  84. package/dist/server/app-rsc-cache-busting.js +9 -5
  85. package/dist/server/app-rsc-handler.d.ts +6 -0
  86. package/dist/server/app-rsc-handler.js +88 -10
  87. package/dist/server/app-rsc-render-mode.d.ts +3 -5
  88. package/dist/server/app-rsc-render-mode.js +5 -12
  89. package/dist/server/app-rsc-request-normalization.d.ts +3 -4
  90. package/dist/server/app-rsc-request-normalization.js +4 -5
  91. package/dist/server/app-server-action-execution.js +6 -5
  92. package/dist/server/app-ssr-entry.js +1 -1
  93. package/dist/server/cache-control.d.ts +3 -1
  94. package/dist/server/cache-control.js +13 -1
  95. package/dist/server/dev-module-runner.js +1 -1
  96. package/dist/server/dev-origin-check.d.ts +2 -2
  97. package/dist/server/dev-origin-check.js +2 -2
  98. package/dist/server/dev-server.d.ts +11 -1
  99. package/dist/server/dev-server.js +82 -24
  100. package/dist/server/headers.d.ts +6 -2
  101. package/dist/server/headers.js +11 -5
  102. package/dist/server/image-optimization.d.ts +12 -1
  103. package/dist/server/image-optimization.js +13 -1
  104. package/dist/server/isr-cache.d.ts +13 -4
  105. package/dist/server/isr-cache.js +8 -4
  106. package/dist/server/pages-data-route.d.ts +4 -2
  107. package/dist/server/pages-data-route.js +18 -4
  108. package/dist/server/pages-dev-module-url.d.ts +2 -1
  109. package/dist/server/pages-dev-module-url.js +6 -3
  110. package/dist/server/pages-node-compat.d.ts +12 -1
  111. package/dist/server/pages-node-compat.js +50 -1
  112. package/dist/server/pages-page-data.d.ts +9 -0
  113. package/dist/server/pages-page-data.js +18 -10
  114. package/dist/server/pages-page-handler.js +19 -7
  115. package/dist/server/pages-page-response.d.ts +1 -0
  116. package/dist/server/pages-page-response.js +5 -4
  117. package/dist/server/pages-request-pipeline.d.ts +8 -6
  118. package/dist/server/pages-request-pipeline.js +31 -7
  119. package/dist/server/pages-router-entry.js +1 -1
  120. package/dist/server/prerender-manifest.d.ts +15 -1
  121. package/dist/server/prerender-manifest.js +29 -1
  122. package/dist/server/prod-server.d.ts +10 -7
  123. package/dist/server/prod-server.js +43 -28
  124. package/dist/server/request-pipeline.js +1 -1
  125. package/dist/server/static-file-cache.js +1 -1
  126. package/dist/shims/cache-handler.js +8 -1
  127. package/dist/shims/cache.d.ts +1 -1
  128. package/dist/shims/cache.js +3 -0
  129. package/dist/shims/cdn-cache.d.ts +2 -7
  130. package/dist/shims/cdn-cache.js +2 -14
  131. package/dist/shims/fetch-cache.d.ts +3 -1
  132. package/dist/shims/fetch-cache.js +77 -52
  133. package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
  134. package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
  135. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -1
  136. package/dist/shims/internal/hybrid-client-route-owner.js +34 -1
  137. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +2 -1
  138. package/dist/shims/internal/pages-data-fetch-dedup.js +13 -2
  139. package/dist/shims/internal/pages-data-target.d.ts +8 -3
  140. package/dist/shims/internal/pages-data-target.js +9 -4
  141. package/dist/shims/link.d.ts +1 -1
  142. package/dist/shims/link.js +179 -42
  143. package/dist/shims/navigation.d.ts +15 -3
  144. package/dist/shims/navigation.js +202 -39
  145. package/dist/shims/request-context.js +18 -0
  146. package/dist/shims/request-state-types.d.ts +2 -2
  147. package/dist/shims/router.js +31 -15
  148. package/dist/shims/unified-request-context.d.ts +1 -1
  149. package/dist/shims/unified-request-context.js +1 -0
  150. package/dist/typegen.js +1 -1
  151. package/dist/utils/middleware-request-headers.js +1 -1
  152. package/dist/utils/project.d.ts +1 -1
  153. package/dist/utils/protocol-headers.d.ts +7 -1
  154. package/dist/utils/protocol-headers.js +7 -1
  155. package/dist/utils/vite-version.d.ts +4 -12
  156. package/dist/utils/vite-version.js +39 -21
  157. package/package.json +31 -13
  158. package/dist/cloudflare/index.d.ts +0 -3
  159. package/dist/cloudflare/index.js +0 -3
  160. package/dist/packages/cloudflare/src/cache/cdn-adapter.runtime.js +0 -102
  161. package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +0 -126
  162. package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.js +0 -435
  163. package/dist/packages/cloudflare/src/deploy-config.js +0 -150
  164. package/dist/packages/cloudflare/src/deploy-help.js +0 -55
  165. package/dist/packages/cloudflare/src/deploy.js +0 -276
  166. package/dist/packages/cloudflare/src/tpr.d.ts +0 -45
  167. package/dist/packages/cloudflare/src/tpr.js +0 -561
  168. package/dist/packages/cloudflare/src/utils/cache-control-metadata.js +0 -20
@@ -1,6 +1,6 @@
1
1
  import { createAppRenderDependency, registerAppElementRenderDependencies, renderAfterAppDependencies, renderWithAppDependencyBarrier } from "./app-render-dependency.js";
2
2
  import { APP_STATIC_SIBLINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
3
- import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, shouldSuppressLoadingBoundaries } from "./app-rsc-render-mode.js";
3
+ import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "./app-rsc-render-mode.js";
4
4
  import { APP_PREFETCH_LOADING_SHELL_MARKER_KEY } from "./app-elements.js";
5
5
  import DefaultGlobalError from "../shims/default-global-error.js";
6
6
  import { ErrorBoundary, ForbiddenBoundary, GlobalErrorBoundary, NotFoundBoundary, RedirectBoundary, UnauthorizedBoundary } from "../shims/error-boundary.js";
@@ -353,7 +353,7 @@ function buildAppPageElements(options) {
353
353
  children: slotElement
354
354
  });
355
355
  const slotLoadingComponent = getDefaultExport(slot.loading);
356
- if (slotLoadingComponent && !shouldSuppressLoadingBoundaries(renderMode)) slotElement = /* @__PURE__ */ jsx(Suspense, {
356
+ if (slotLoadingComponent) slotElement = /* @__PURE__ */ jsx(Suspense, {
357
357
  fallback: /* @__PURE__ */ jsx(slotLoadingComponent, {}),
358
358
  children: slotElement
359
359
  }, slotResetKey);
@@ -374,7 +374,7 @@ function buildAppPageElements(options) {
374
374
  else routeChildren = /* @__PURE__ */ jsx(routeLoadingComponent, {});
375
375
  else {
376
376
  routeChildren = /* @__PURE__ */ jsx(RedirectBoundary, { children: routeChildren });
377
- if (routeLoadingComponent && !shouldSuppressLoadingBoundaries(renderMode)) routeChildren = /* @__PURE__ */ jsx(Suspense, {
377
+ if (routeLoadingComponent) routeChildren = /* @__PURE__ */ jsx(Suspense, {
378
378
  fallback: /* @__PURE__ */ jsx(routeLoadingComponent, {}),
379
379
  children: routeChildren
380
380
  }, routeResetKey);
@@ -107,7 +107,8 @@ type RenderAppPageHtmlStreamOptions = {
107
107
  value: Promise<ArrayBuffer> | null;
108
108
  }; /** Abort signal for a build-time PPR fallback-shell static render. */
109
109
  pprFallbackShellSignal?: AbortSignal; /** When true, wait for the full React tree before emitting bytes. */
110
- waitForAllReady?: boolean; /** Dev-only: original server error to surface in the browser overlay. */
110
+ waitForAllReady?: boolean; /** Override the default shell-error recovery decision passed to handleSsr. */
111
+ fallbackToErrorDocumentOnShellError?: boolean; /** Dev-only: original server error to surface in the browser overlay. */
111
112
  initialDevServerError?: unknown;
112
113
  /** True when the app supplies a custom global-error.tsx. Disables the
113
114
  * default error-document shell fallback so SSR shell errors keep driving
@@ -68,7 +68,7 @@ async function renderAppPageHtmlStream(options) {
68
68
  pprFallbackShellSignal: options.pprFallbackShellSignal,
69
69
  waitForAllReady: options.waitForAllReady,
70
70
  initialDevServerError: options.initialDevServerError,
71
- fallbackToErrorDocumentOnShellError: options.waitForAllReady !== true && options.hasCustomGlobalError === false,
71
+ fallbackToErrorDocumentOnShellError: options.fallbackToErrorDocumentOnShellError ?? (options.waitForAllReady !== true && options.hasCustomGlobalError === false),
72
72
  dynamicStaleTimeSeconds: options.dynamicStaleTimeSeconds,
73
73
  getInitialNavigationCacheMetadata: options.getInitialNavigationCacheMetadata
74
74
  };
@@ -1,7 +1,7 @@
1
1
  import { NextI18nConfig } from "../config/next-config.js";
2
- import { CachedRouteValue } from "../shims/cache-handler.js";
3
2
  import { ExecutionContextLike } from "../shims/request-context.js";
4
3
  import { NextRequest } from "../shims/server.js";
4
+ import { CachedRouteValue } from "../shims/cache-handler.js";
5
5
  import { HeadersAccessPhase } from "../shims/headers.js";
6
6
  import { RouteHandlerMiddlewareContext } from "./app-route-handler-response.js";
7
7
  import { AppRouteHandlerModule } from "./app-route-handler-policy.js";
@@ -0,0 +1,43 @@
1
+ //#region src/server/app-route-tree-prefetch.d.ts
2
+ type DynamicParamTypeShort = "d" | "c" | "oc";
3
+ type TreePrefetchParam = {
4
+ type: DynamicParamTypeShort;
5
+ key: null;
6
+ siblings: readonly string[] | null;
7
+ };
8
+ type AppRouteTreePrefetchSlot = {
9
+ configLayouts?: readonly unknown[] | null;
10
+ configLayoutTreePositions?: readonly number[] | null;
11
+ default?: unknown;
12
+ layout?: unknown;
13
+ layoutIndex?: number;
14
+ name: string;
15
+ page?: unknown;
16
+ routeSegments?: readonly string[] | null;
17
+ };
18
+ type AppRouteTreePrefetchRoute = {
19
+ layoutTreePositions?: readonly number[];
20
+ layouts?: readonly unknown[];
21
+ page?: unknown;
22
+ routeSegments: readonly string[];
23
+ slots?: Readonly<Record<string, AppRouteTreePrefetchSlot>> | null;
24
+ };
25
+ type TreePrefetch = {
26
+ name: string;
27
+ param: TreePrefetchParam | null;
28
+ prefetchHints: number;
29
+ slots: null | Record<string, TreePrefetch>;
30
+ };
31
+ type RouteTreePrefetchResponseOptions = {
32
+ buildId?: string | null;
33
+ deploymentId?: string;
34
+ prefetchInlining?: PrefetchInliningConfig;
35
+ };
36
+ type PrefetchInliningConfig = false | {
37
+ maxBundleSize: number;
38
+ maxSize: number;
39
+ };
40
+ declare function isRouteTreePrefetchRequest(request: Request): boolean;
41
+ declare function createRouteTreePrefetchResponse(route: AppRouteTreePrefetchRoute, options?: RouteTreePrefetchResponseOptions): Promise<Response>;
42
+ //#endregion
43
+ export { AppRouteTreePrefetchRoute, PrefetchInliningConfig, TreePrefetch, createRouteTreePrefetchResponse, isRouteTreePrefetchRequest };
@@ -0,0 +1,187 @@
1
+ import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
2
+ import { getDeploymentId } from "../utils/deployment-id.js";
3
+ import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader } from "./app-rsc-cache-busting.js";
4
+ //#region src/server/app-route-tree-prefetch.ts
5
+ const PARENT_INLINED_INTO_SELF = 32;
6
+ const INLINED_INTO_CHILD = 64;
7
+ const HEAD_INLINED_INTO_SELF = 128;
8
+ const PAGE_SEGMENT = "__PAGE__";
9
+ const SLOT_SEGMENT = "(__SLOT__)";
10
+ const SEGMENT_INLINE_SIZE = 1;
11
+ const SEGMENT_OUTLINE_SIZE = 4096;
12
+ const DEFAULT_SEGMENT_INLINE_THRESHOLD = 2048;
13
+ const HEAD_INLINE_SIZE = 1;
14
+ const DEFAULT_MAX_INLINE_BUNDLE_SIZE = 10240;
15
+ const NEXT_DID_POSTPONE_HEADER = "x-nextjs-postponed";
16
+ function isRouteTreePrefetchRequest(request) {
17
+ return request.headers.get("RSC") === "1" && request.headers.get("Next-Router-Prefetch") === "1" && request.headers.get("Next-Router-Segment-Prefetch") === "/_tree";
18
+ }
19
+ function createNode(segment, module) {
20
+ const { name, param } = routeTreeSegment(segment);
21
+ return {
22
+ name,
23
+ param,
24
+ prefetchSize: estimatePrefetchSize(module) ?? ((module === null || module === void 0) && segment !== PAGE_SEGMENT ? SEGMENT_INLINE_SIZE : null),
25
+ prefetchHints: 0,
26
+ slots: null
27
+ };
28
+ }
29
+ function ensureSlots(node) {
30
+ if (node.slots === null) node.slots = {};
31
+ return node.slots;
32
+ }
33
+ function addChild(node, key, child) {
34
+ ensureSlots(node)[key] = child;
35
+ }
36
+ function routeTreeSegment(segment) {
37
+ if (segment.startsWith(":")) {
38
+ const rest = segment.slice(1);
39
+ if (rest.endsWith("+")) return dynamicRouteTreeSegment(rest.slice(0, -1), "c");
40
+ if (rest.endsWith("*")) return dynamicRouteTreeSegment(rest.slice(0, -1), "oc");
41
+ return dynamicRouteTreeSegment(rest, "d");
42
+ }
43
+ if (segment.startsWith("[[...") && segment.endsWith("]]")) return dynamicRouteTreeSegment(segment.slice(5, -2), "oc");
44
+ if (segment.startsWith("[...") && segment.endsWith("]")) return dynamicRouteTreeSegment(segment.slice(4, -1), "c");
45
+ if (segment.startsWith("[") && segment.endsWith("]")) return dynamicRouteTreeSegment(segment.slice(1, -1), "d");
46
+ return {
47
+ name: segment,
48
+ param: null
49
+ };
50
+ }
51
+ function dynamicRouteTreeSegment(name, type) {
52
+ return {
53
+ name,
54
+ param: {
55
+ key: null,
56
+ siblings: null,
57
+ type
58
+ }
59
+ };
60
+ }
61
+ function explicitPrefetchSize(module) {
62
+ if (typeof module !== "object" || module === null) return null;
63
+ const value = module.prefetchSize;
64
+ if (value === "large") return SEGMENT_OUTLINE_SIZE;
65
+ if (value === "small") return SEGMENT_INLINE_SIZE;
66
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
67
+ }
68
+ function estimatePrefetchSize(module) {
69
+ const explicitSize = explicitPrefetchSize(module);
70
+ if (explicitSize !== null) return explicitSize;
71
+ if (typeof module !== "object" || module === null) return null;
72
+ return typeof module.default === "function" ? SEGMENT_INLINE_SIZE : null;
73
+ }
74
+ function layoutModuleByTreePosition(route) {
75
+ const layouts = route.layouts ?? [];
76
+ const positions = route.layoutTreePositions ?? [];
77
+ const byPosition = /* @__PURE__ */ new Map();
78
+ for (const [index, position] of positions.entries()) byPosition.set(position, layouts[index]);
79
+ return byPosition;
80
+ }
81
+ function modulesByTreePosition(modules, positions) {
82
+ const byPosition = /* @__PURE__ */ new Map();
83
+ for (const [index, position] of (positions ?? []).entries()) byPosition.set(position, modules?.[index]);
84
+ return byPosition;
85
+ }
86
+ async function buildTree(route) {
87
+ const layoutsByPosition = layoutModuleByTreePosition(route);
88
+ const root = createNode("", layoutsByPosition.get(0));
89
+ const nodesByPosition = new Map([[0, root]]);
90
+ let current = root;
91
+ for (const [index, segment] of route.routeSegments.entries()) {
92
+ const position = index + 1;
93
+ const child = createNode(segment, layoutsByPosition.get(position));
94
+ addChild(current, "children", child);
95
+ nodesByPosition.set(position, child);
96
+ current = child;
97
+ }
98
+ addChild(current, "children", createNode(PAGE_SEGMENT, route.page));
99
+ for (const slot of Object.values(route.slots ?? {})) {
100
+ const ownerPosition = slot.layoutIndex === void 0 || slot.layoutIndex < 0 ? route.routeSegments.length : route.layoutTreePositions?.[slot.layoutIndex] ?? route.routeSegments.length;
101
+ const owner = nodesByPosition.get(ownerPosition) ?? current;
102
+ const slotRoot = createNode(SLOT_SEGMENT, slot.layout);
103
+ let slotCurrent = slotRoot;
104
+ const slotConfigLayoutsByPosition = modulesByTreePosition(slot.configLayouts, slot.configLayoutTreePositions);
105
+ const slotRouteSegments = slot.routeSegments ?? [];
106
+ for (const [index, segment] of slotRouteSegments.entries()) {
107
+ const position = index + 1;
108
+ const child = createNode(segment, slotConfigLayoutsByPosition.get(position));
109
+ addChild(slotCurrent, "children", child);
110
+ slotCurrent = child;
111
+ }
112
+ addChild(slotCurrent, "children", createNode(PAGE_SEGMENT, slot.page ?? slot.default));
113
+ addChild(owner, slot.name, slotRoot);
114
+ }
115
+ return root;
116
+ }
117
+ function computePrefetchHints(node, parentGzipSize, headInlineState, config) {
118
+ const currentGzipSize = node.prefetchSize;
119
+ const sizeToInline = currentGzipSize !== null && currentGzipSize < config.maxSize ? currentGzipSize : null;
120
+ let didInlineIntoChild = false;
121
+ let acceptingChildInlinedBytes = 0;
122
+ let smallestChildInlinedBytes = Number.POSITIVE_INFINITY;
123
+ let hasChildren = false;
124
+ for (const child of Object.values(node.slots ?? {})) {
125
+ hasChildren = true;
126
+ const childInlinedBytes = computePrefetchHints(child, didInlineIntoChild ? null : sizeToInline, headInlineState, config);
127
+ if ((child.prefetchHints & PARENT_INLINED_INTO_SELF) !== 0) {
128
+ didInlineIntoChild = true;
129
+ acceptingChildInlinedBytes = childInlinedBytes;
130
+ } else if (!didInlineIntoChild && childInlinedBytes < smallestChildInlinedBytes) smallestChildInlinedBytes = childInlinedBytes;
131
+ }
132
+ if (!hasChildren) smallestChildInlinedBytes = 0;
133
+ let hints = node.prefetchHints;
134
+ if (didInlineIntoChild) hints |= INLINED_INTO_CHILD;
135
+ let inlinedBytes = didInlineIntoChild ? acceptingChildInlinedBytes : smallestChildInlinedBytes;
136
+ const isBundleTerminal = !didInlineIntoChild;
137
+ if (!headInlineState.inlined && isBundleTerminal && node.name === PAGE_SEGMENT && inlinedBytes + HEAD_INLINE_SIZE < config.maxBundleSize) {
138
+ hints |= HEAD_INLINED_INTO_SELF;
139
+ inlinedBytes += HEAD_INLINE_SIZE;
140
+ headInlineState.inlined = true;
141
+ }
142
+ if (parentGzipSize !== null) {
143
+ if (inlinedBytes + parentGzipSize < config.maxBundleSize) {
144
+ hints |= PARENT_INLINED_INTO_SELF;
145
+ inlinedBytes += parentGzipSize;
146
+ }
147
+ }
148
+ node.prefetchHints = hints;
149
+ return inlinedBytes;
150
+ }
151
+ function stripMutableFields(node) {
152
+ const slots = node.slots === null ? null : Object.fromEntries(Object.entries(node.slots).map(([key, child]) => [key, stripMutableFields(child)]));
153
+ return {
154
+ name: node.name,
155
+ param: node.param,
156
+ prefetchHints: node.prefetchHints,
157
+ slots
158
+ };
159
+ }
160
+ function resolvePrefetchInliningConfig(config) {
161
+ if (config) return config;
162
+ return {
163
+ maxBundleSize: DEFAULT_MAX_INLINE_BUNDLE_SIZE,
164
+ maxSize: DEFAULT_SEGMENT_INLINE_THRESHOLD
165
+ };
166
+ }
167
+ async function createRouteTreePrefetchResponse(route, options = {}) {
168
+ const tree = await buildTree(route);
169
+ computePrefetchHints(tree, null, { inlined: false }, resolvePrefetchInliningConfig(options.prefetchInlining));
170
+ const headers = new Headers({
171
+ "Cache-Control": "no-store",
172
+ "Content-Type": VINEXT_RSC_CONTENT_TYPE,
173
+ [NEXT_DID_POSTPONE_HEADER]: "2",
174
+ Vary: VINEXT_RSC_VARY_HEADER
175
+ });
176
+ applyRscCompatibilityIdHeader(headers);
177
+ const deploymentId = options.deploymentId ?? getDeploymentId();
178
+ if (deploymentId) headers.set(NEXTJS_DEPLOYMENT_ID_HEADER, deploymentId);
179
+ const payload = {
180
+ tree: stripMutableFields(tree),
181
+ staleTime: -1
182
+ };
183
+ if (options.buildId) payload.buildId = options.buildId;
184
+ return new Response(`0:${JSON.stringify(payload)}\n`, { headers });
185
+ }
186
+ //#endregion
187
+ export { createRouteTreePrefetchResponse, isRouteTreePrefetchRequest };
@@ -4,8 +4,8 @@ import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "../utils/protocol-headers.
4
4
  import { badRequestResponse, notFoundResponse, notFoundStaticAssetResponse } from "./http-error-responses.js";
5
5
  import { isOpenRedirectShaped } from "./open-redirect.js";
6
6
  import { cloneRequestWithHeaders, filterInternalHeaders } from "./request-pipeline.js";
7
- import { getImageOptimizer, handleConfiguredImageOptimization, isImageOptimizationPath } from "./image-optimization.js";
8
7
  import { assetPrefixPathname, isNextStaticPath } from "../utils/asset-prefix.js";
8
+ import { getImageOptimizer, handleConfiguredImageOptimization, isImageOptimizationPath } from "./image-optimization.js";
9
9
  import { finalizeMissingStaticAssetResponse, resolveStaticAssetSignal } from "./worker-utils.js";
10
10
  import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
11
11
  import rscHandler, { __assetPrefix, __basePath, __imageAllowedWidths, __imageConfig } from "virtual:vinext-rsc-entry";
@@ -24,6 +24,7 @@ type ResolveInvalidRscCacheBustingRequestOptions = {
24
24
  };
25
25
  declare function getVinextRscCompatibilityId(): string | null;
26
26
  declare function applyRscCompatibilityIdHeader(headers: Headers, compatibilityId?: string | null | undefined): void;
27
+ declare function applyRscDeploymentIdHeader(headers: Headers): void;
27
28
  declare function isRscCompatibilityIdCompatible(responseCompatibilityId: string | null | undefined, clientCompatibilityId?: string | null | undefined): boolean;
28
29
  type RscCompatibilityNavigationDecision = {
29
30
  kind: "compatible";
@@ -61,4 +62,4 @@ declare function createServerActionRequestUrl(href: string): string;
61
62
  declare function createRscRedirectLocation(location: string, request: Request): Promise<string>;
62
63
  declare function resolveInvalidRscCacheBustingRequest(options: ResolveInvalidRscCacheBustingRequestOptions): Promise<Response | null>;
63
64
  //#endregion
64
- export { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, computeRscCacheBustingSearchParam, createRscRedirectLocation, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId, hasRscCacheBustingSearchParam, isRscCompatibilityIdCompatible, resolveHardNavigationTargetFromRscResponse, resolveInvalidRscCacheBustingRequest, resolveRscCompatibilityNavigationDecision, setRscCacheBustingSearchParam, stripRscCacheBustingSearchParam, stripRscSuffix };
65
+ export { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, computeRscCacheBustingSearchParam, createRscRedirectLocation, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId, hasRscCacheBustingSearchParam, isRscCompatibilityIdCompatible, resolveHardNavigationTargetFromRscResponse, resolveInvalidRscCacheBustingRequest, resolveRscCompatibilityNavigationDecision, setRscCacheBustingSearchParam, stripRscCacheBustingSearchParam, stripRscSuffix };
@@ -1,7 +1,7 @@
1
- import { NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "./headers.js";
1
+ import { NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_RSC_RENDER_MODE_HEADER } from "./headers.js";
2
2
  import { fnv1a64 } from "../utils/hash.js";
3
3
  import { parseAppRscRenderMode } from "./app-rsc-render-mode.js";
4
- import { applyDeploymentIdHeader } from "../utils/deployment-id.js";
4
+ import { applyDeploymentIdHeader, getDeploymentId } from "../utils/deployment-id.js";
5
5
  //#region src/server/app-rsc-cache-busting.ts
6
6
  /**
7
7
  * RSC cache-busting hashes cover the headers that make an RSC payload vary.
@@ -14,7 +14,6 @@ const VINEXT_RSC_COMPATIBILITY_ID_HEADER = "X-Vinext-RSC-Compatibility-Id";
14
14
  const VINEXT_RSC_CONTENT_TYPE = "text/x-component";
15
15
  const VINEXT_RSC_VARY_HEADER = [
16
16
  "RSC",
17
- "Accept",
18
17
  NEXT_ROUTER_STATE_TREE_HEADER,
19
18
  NEXT_ROUTER_PREFETCH_HEADER,
20
19
  NEXT_ROUTER_SEGMENT_PREFETCH_HEADER,
@@ -44,6 +43,11 @@ function applyRscCompatibilityIdHeader(headers, compatibilityId = getVinextRscCo
44
43
  if (normalized) headers.set(VINEXT_RSC_COMPATIBILITY_ID_HEADER, normalized);
45
44
  else headers.delete(VINEXT_RSC_COMPATIBILITY_ID_HEADER);
46
45
  }
46
+ function applyRscDeploymentIdHeader(headers) {
47
+ const deploymentId = getDeploymentId();
48
+ if (deploymentId) headers.set(NEXTJS_DEPLOYMENT_ID_HEADER, deploymentId);
49
+ else headers.delete(NEXTJS_DEPLOYMENT_ID_HEADER);
50
+ }
47
51
  function isRscCompatibilityIdCompatible(responseCompatibilityId, clientCompatibilityId = getVinextRscCompatibilityId()) {
48
52
  const normalizedResponseCompatibilityId = normalizeCompatibilityId(responseCompatibilityId);
49
53
  const normalizedClientCompatibilityId = normalizeCompatibilityId(clientCompatibilityId);
@@ -184,7 +188,7 @@ async function resolveInvalidRscCacheBustingRequest(options) {
184
188
  const url = new URL(options.request.url);
185
189
  const actualHash = url.searchParams.get(VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM);
186
190
  const expectedHash = await computeRscCacheBustingSearchParam(options.request.headers);
187
- if (actualHash === null && expectedHash === "") return null;
191
+ if (actualHash === null && expectedHash === "" && url.pathname.endsWith(".rsc")) return null;
188
192
  const acceptedHashes = new Set([expectedHash]);
189
193
  if (actualHash !== null && actualHash !== expectedHash) {
190
194
  acceptedHashes.add(computeLegacyRscCacheBustingSearchParam(options.request.headers));
@@ -203,4 +207,4 @@ async function resolveInvalidRscCacheBustingRequest(options) {
203
207
  });
204
208
  }
205
209
  //#endregion
206
- export { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, computeRscCacheBustingSearchParam, createRscRedirectLocation, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId, hasRscCacheBustingSearchParam, isRscCompatibilityIdCompatible, resolveHardNavigationTargetFromRscResponse, resolveInvalidRscCacheBustingRequest, resolveRscCompatibilityNavigationDecision, setRscCacheBustingSearchParam, stripRscCacheBustingSearchParam, stripRscSuffix };
210
+ export { VINEXT_RSC_CACHE_BUSTING_SEARCH_PARAM, VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityIdHeader, applyRscDeploymentIdHeader, computeRscCacheBustingSearchParam, createRscRedirectLocation, createRscRequestHeaders, createRscRequestUrl, createServerActionRequestUrl, getVinextRscCompatibilityId, hasRscCacheBustingSearchParam, isRscCompatibilityIdCompatible, resolveHardNavigationTargetFromRscResponse, resolveInvalidRscCacheBustingRequest, resolveRscCompatibilityNavigationDecision, setRscCacheBustingSearchParam, stripRscCacheBustingSearchParam, stripRscSuffix };
@@ -6,6 +6,7 @@ import { AppMiddlewareContext, ApplyAppMiddlewareResult } from "./app-middleware
6
6
  import { AppRscRenderMode } from "./app-rsc-render-mode.js";
7
7
  import { AppPagePprFallbackCacheShell } from "./app-ppr-fallback-shell.js";
8
8
  import { AppPrerenderRootParamNamesMap, AppPrerenderStaticParamsMap } from "./app-prerender-endpoints.js";
9
+ import { AppRouteTreePrefetchRoute, PrefetchInliningConfig } from "./app-route-tree-prefetch.js";
9
10
  import { ReactFormState } from "react-dom/client";
10
11
 
11
12
  //#region src/server/app-rsc-handler.d.ts
@@ -24,12 +25,15 @@ type AppRscHandlerRoute = {
24
25
  __loadPage?: unknown;
25
26
  __loadRouteHandler?: unknown;
26
27
  isDynamic: boolean;
28
+ layouts?: readonly unknown[];
29
+ layoutTreePositions?: readonly number[];
27
30
  params?: readonly string[];
28
31
  page?: unknown;
29
32
  pattern: string;
30
33
  rootParamNames?: readonly string[];
31
34
  routeHandler?: unknown;
32
35
  routeSegments: readonly string[];
36
+ slots?: AppRouteTreePrefetchRoute["slots"];
33
37
  };
34
38
  type AppRscRouteMatch<TRoute> = {
35
39
  params: AppPageParams;
@@ -63,6 +67,7 @@ type DispatchMatchedPageOptions<TRoute> = {
63
67
  staticParamsValidationParams?: AppPageParams;
64
68
  rootParams?: RootParams;
65
69
  request: Request;
70
+ renderedPathAndSearch?: string | null;
66
71
  route: TRoute;
67
72
  scriptNonce?: string;
68
73
  searchParams: URLSearchParams;
@@ -189,6 +194,7 @@ type CreateAppRscHandlerOptions<TRoute extends AppRscHandlerRoute> = {
189
194
  matchRoute: (pathname: string) => AppRscRouteMatch<TRoute> | null;
190
195
  runMiddleware?: (options: RunAppMiddlewareOptions) => Promise<ApplyAppMiddlewareResult>;
191
196
  publicFiles: ReadonlySet<string>;
197
+ prefetchInlining?: PrefetchInliningConfig;
192
198
  renderNotFound: (options: RenderNotFoundOptions<TRoute>) => Promise<Response | null>;
193
199
  renderPagesFallback?: (options: RenderPagesFallbackOptions) => Promise<Response | null>;
194
200
  rootParamNamesByPattern?: RootParamNamesMap;
@@ -1,7 +1,7 @@
1
1
  import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
2
2
  import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
3
3
  import { getRequestExecutionContext } from "../shims/request-context.js";
4
- import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "../utils/protocol-headers.js";
4
+ import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
5
5
  import { ACTION_REVALIDATED_HEADER } from "./headers.js";
6
6
  import { isExternalUrl, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
7
7
  import { notFoundResponse } from "./http-error-responses.js";
@@ -23,6 +23,7 @@ import { createServerActionNotFoundResponse, getServerActionNotFoundMessage } fr
23
23
  import { buildPageCacheTags } from "./implicit-tags.js";
24
24
  import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
25
25
  import { pickRootParams, setRootParams } from "../shims/root-params.js";
26
+ import { createRouteTreePrefetchResponse, isRouteTreePrefetchRequest } from "./app-route-tree-prefetch.js";
26
27
  import { flattenErrorCauses } from "../utils/error-cause.js";
27
28
  import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
28
29
  import { normalizeRscRequest } from "./app-rsc-request-normalization.js";
@@ -163,10 +164,10 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
163
164
  headers: { Location: location }
164
165
  });
165
166
  }
166
- const rscCacheBustingRedirect = await resolveInvalidRscCacheBustingRequest({
167
+ const rscCacheBustingRedirect = hadBasePath ? await resolveInvalidRscCacheBustingRequest({
167
168
  isRscRequest,
168
169
  request
169
- });
170
+ }) : null;
170
171
  if (rscCacheBustingRedirect) return rscCacheBustingRedirect;
171
172
  const normalizedUserlandRequest = requestWithoutRscSuffix(request);
172
173
  const userlandRequest = requestWithoutRscCacheBustingSearchParam(normalizedUserlandRequest);
@@ -200,6 +201,13 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
200
201
  const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareContext.headers);
201
202
  const postMiddlewareRequestContext = buildPostMwRequestContext(userlandRequest);
202
203
  let filesystemRouteEligible = hadBasePath || didMiddlewareRewrite;
204
+ const validateClaimedOutsideBasePathRsc = async () => {
205
+ if (hadBasePath || !filesystemRouteEligible) return null;
206
+ return resolveInvalidRscCacheBustingRequest({
207
+ isRscRequest,
208
+ request
209
+ });
210
+ };
203
211
  for (const rewrite of options.configRewrites.beforeFiles) {
204
212
  const beforeFilesRewrite = await applyRewrite({
205
213
  basePathState,
@@ -215,6 +223,51 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
215
223
  filesystemRouteEligible = true;
216
224
  }
217
225
  }
226
+ const claimedRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
227
+ if (claimedRscCacheBustingRedirect) return claimedRscCacheBustingRedirect;
228
+ const actionId = request.headers.get("x-rsc-action") ?? request.headers.get("next-action");
229
+ const isPostRequest = request.method.toUpperCase() === "POST";
230
+ const contentType = request.headers.get("content-type") || "";
231
+ const isProgressiveActionRequest = isPostRequest && !actionId && contentType.startsWith("multipart/form-data");
232
+ let resolvedLateRewritesForAction = false;
233
+ if (!filesystemRouteEligible && (actionId || isProgressiveActionRequest)) {
234
+ let actionMatch = null;
235
+ for (const rewrite of options.configRewrites.afterFiles) {
236
+ const rewritten = await applyRewrite({
237
+ basePathState,
238
+ clearRequestContext: options.clearRequestContext,
239
+ request: normalizedUserlandRequest,
240
+ requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
241
+ rewrites: [rewrite]
242
+ }, matchPathname(cleanPathname));
243
+ if (rewritten instanceof Response) return rewritten;
244
+ if (!rewritten) continue;
245
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
246
+ cleanPathname = pathnameForResolvedUrl(resolvedUrl);
247
+ filesystemRouteEligible = true;
248
+ actionMatch = options.matchRoute(cleanPathname);
249
+ if (actionMatch) break;
250
+ }
251
+ if (!actionMatch) for (const rewrite of options.configRewrites.fallback) {
252
+ const rewritten = await applyRewrite({
253
+ basePathState,
254
+ clearRequestContext: options.clearRequestContext,
255
+ request: normalizedUserlandRequest,
256
+ requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
257
+ rewrites: [rewrite]
258
+ }, matchPathname(cleanPathname));
259
+ if (rewritten instanceof Response) return rewritten;
260
+ if (!rewritten) continue;
261
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
262
+ cleanPathname = pathnameForResolvedUrl(resolvedUrl);
263
+ filesystemRouteEligible = true;
264
+ actionMatch = options.matchRoute(cleanPathname);
265
+ if (actionMatch) break;
266
+ }
267
+ resolvedLateRewritesForAction = filesystemRouteEligible;
268
+ }
269
+ const lateActionRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
270
+ if (lateActionRscCacheBustingRedirect) return lateActionRscCacheBustingRedirect;
218
271
  if (filesystemRouteEligible && isImageOptimizationPath(cleanPathname)) {
219
272
  const imageRedirect = resolveDevImageRedirect(url, [...options.imageConfig?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...options.imageConfig?.imageSizes ?? DEFAULT_IMAGE_SIZES], options.imageConfig?.qualities, { isDev: options.isDev });
220
273
  if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
@@ -255,9 +308,18 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
255
308
  });
256
309
  const preActionMatch = filesystemRouteEligible ? options.matchRoute(cleanPathname) : null;
257
310
  if (preActionMatch) setRootParams(pickRootParams(preActionMatch.params, preActionMatch.route.rootParamNames));
258
- const actionId = request.headers.get("x-rsc-action") ?? request.headers.get("next-action");
259
- const contentType = request.headers.get("content-type") || "";
260
- const isPostRequest = request.method.toUpperCase() === "POST";
311
+ if (pagesDataRequest && didMiddlewareRewritePathname && preActionMatch) {
312
+ const headers = new Headers();
313
+ mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);
314
+ headers.set("content-type", "application/json");
315
+ headers.set("x-nextjs-rewrite", resolvedUrl);
316
+ options.clearRequestContext();
317
+ return new Response("{}", { headers });
318
+ }
319
+ if (!filesystemRouteEligible && isPostRequest && actionId) {
320
+ options.clearRequestContext();
321
+ return notFoundResponse();
322
+ }
261
323
  let progressiveActionResult = null;
262
324
  if (filesystemRouteEligible && isPostRequest && contentType.startsWith("multipart/form-data") && !actionId) {
263
325
  if (options.handleProgressiveActionRequest) progressiveActionResult = await options.handleProgressiveActionRequest({
@@ -322,7 +384,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
322
384
  options.clearRequestContext();
323
385
  return staticPagesFallbackResponse;
324
386
  }
325
- if (!match || match.route.isDynamic) for (const rewrite of options.configRewrites.afterFiles) {
387
+ if (!resolvedLateRewritesForAction && (!match || match.route.isDynamic)) for (const rewrite of options.configRewrites.afterFiles) {
326
388
  const afterFilesRewrite = await applyRewrite({
327
389
  basePathState,
328
390
  clearRequestContext: options.clearRequestContext,
@@ -335,6 +397,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
335
397
  resolvedUrl = mergeRewriteQuery(resolvedUrl, afterFilesRewrite);
336
398
  cleanPathname = pathnameForResolvedUrl(resolvedUrl);
337
399
  filesystemRouteEligible = true;
400
+ const claimedRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
401
+ if (claimedRscCacheBustingRedirect) return claimedRscCacheBustingRedirect;
338
402
  match = options.matchRoute(cleanPathname);
339
403
  const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
340
404
  if (rewrittenStaticPagesResponse) {
@@ -353,7 +417,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
353
417
  options.clearRequestContext();
354
418
  return dynamicPagesFallbackResponse;
355
419
  }
356
- if (!match) for (const rewrite of options.configRewrites.fallback) {
420
+ if (!resolvedLateRewritesForAction && !match) for (const rewrite of options.configRewrites.fallback) {
357
421
  const fallbackRewrite = await applyRewrite({
358
422
  basePathState,
359
423
  clearRequestContext: options.clearRequestContext,
@@ -366,6 +430,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
366
430
  resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
367
431
  cleanPathname = pathnameForResolvedUrl(resolvedUrl);
368
432
  filesystemRouteEligible = true;
433
+ const claimedRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
434
+ if (claimedRscCacheBustingRedirect) return claimedRscCacheBustingRedirect;
369
435
  match = options.matchRoute(cleanPathname);
370
436
  const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
371
437
  if (rewrittenStaticPagesResponse) {
@@ -391,6 +457,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
391
457
  const response = buildNextDataNotFoundResponse();
392
458
  const headers = new Headers(response.headers);
393
459
  headers.set("x-nextjs-matched-path", matchPathname(canonicalPathname));
460
+ if (resolvedUrl !== originalResolvedUrl) headers.set("x-nextjs-rewrite", resolvedUrl);
394
461
  return new Response("{}", {
395
462
  status: 200,
396
463
  headers
@@ -418,11 +485,19 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
418
485
  }
419
486
  const { route, params } = match;
420
487
  if (options.ensureRouteLoaded) await options.ensureRouteLoaded(route);
488
+ const resolvedSearchParams = getResolvedSearchParams();
489
+ if (isRouteTreePrefetchRequest(request) && !route.routeHandler) {
490
+ const response = await createRouteTreePrefetchResponse(route, {
491
+ buildId: options.buildId,
492
+ prefetchInlining: options.prefetchInlining
493
+ });
494
+ options.clearRequestContext();
495
+ return applyMiddlewareContextToResponse(response, middlewareContext);
496
+ }
421
497
  const prerenderRouteParamsMatch = matchPrerenderRouteParamsPayload(readTrustedPrerenderRouteParams(request), route.pattern, params);
422
498
  const prerenderRouteParams = prerenderRouteParamsMatch?.params ?? null;
423
499
  const isPrerenderFallbackShell = prerenderRouteParamsMatch?.kind === "fallback-shell";
424
500
  const renderParams = prerenderRouteParams ?? params;
425
- const resolvedSearchParams = getResolvedSearchParams();
426
501
  let runtimeFallbackShells = [];
427
502
  if (options.createPprFallbackShells && request.method === "GET" && !isRscRequest && !isPrerenderFallbackShell && route.params) runtimeFallbackShells = options.createPprFallbackShells({
428
503
  params: route.params,
@@ -476,6 +551,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
476
551
  staticParamsValidationParams: prerenderRouteParams === null || isPrerenderFallbackShell ? void 0 : params,
477
552
  rootParams,
478
553
  request,
554
+ renderedPathAndSearch: resolvedUrl,
479
555
  route,
480
556
  scriptNonce,
481
557
  searchParams: resolvedSearchParams,
@@ -525,14 +601,16 @@ function createAppRscHandler(options) {
525
601
  const pagesDataInScope = !options.basePath || hasBasePath(pagesDataUrl.pathname, options.basePath);
526
602
  if (pagesDataInScope) pagesDataUrl.pathname = stripBasePath(pagesDataUrl.pathname, options.basePath);
527
603
  const pagesDataCandidate = pagesDataInScope ? cloneRequestWithUrl(rawRequest, pagesDataUrl.toString()) : null;
528
- const pagesDataNormalization = options.renderPagesFallback && pagesDataCandidate ? normalizePagesDataRequest(pagesDataCandidate, options.buildId) : null;
604
+ const pagesDataNormalization = options.renderPagesFallback && pagesDataCandidate ? normalizePagesDataRequest(pagesDataCandidate, options.buildId, "", typeof options.runMiddleware === "function" && options.trailingSlash) : null;
529
605
  if (pagesDataNormalization?.notFoundResponse) return pagesDataNormalization.notFoundResponse;
530
606
  const isPagesDataRequest = pagesDataNormalization?.isDataReq === true;
531
607
  const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(rawRequest);
608
+ const isTrustedSpeculativePrerender = process.env.VINEXT_PRERENDER === "1" && rawRequest.headers.get("x-vinext-prerender-secret") !== null && rawRequest.headers.get("x-vinext-prerender-speculative") === "1";
532
609
  const filteredHeaders = filterInternalHeaders(rawRequest.headers);
533
610
  if (mwCtx !== null) filteredHeaders.set(VINEXT_MW_CTX_HEADER, mwCtx);
534
611
  const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
535
612
  if (prerenderRouteParamsHeader !== null) filteredHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
613
+ if (isTrustedSpeculativePrerender) filteredHeaders.set(VINEXT_PRERENDER_SPECULATIVE_HEADER, "1");
536
614
  let appRequest = rawRequest;
537
615
  if (pagesDataNormalization?.isDataReq) {
538
616
  const appRequestUrl = new URL(pagesDataNormalization.request.url);
@@ -1,11 +1,9 @@
1
1
  //#region src/server/app-rsc-render-mode.d.ts
2
- type AppRscRenderMode = "navigation" | "prefetch-loading-shell" | "refresh-preserve-ui" | "action-rerender-preserve-ui";
2
+ type AppRscRenderMode = "navigation" | "prefetch-dynamic-shell" | "prefetch-loading-shell";
3
3
  declare const APP_RSC_RENDER_MODE_NAVIGATION = "navigation";
4
+ declare const APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL = "prefetch-dynamic-shell";
4
5
  declare const APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL = "prefetch-loading-shell";
5
- declare const APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI = "refresh-preserve-ui";
6
- declare const APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI = "action-rerender-preserve-ui";
7
- declare function shouldSuppressLoadingBoundaries(mode: AppRscRenderMode): boolean;
8
6
  declare function getRscRenderModeCacheVariant(mode: AppRscRenderMode): string | null;
9
7
  declare function parseAppRscRenderMode(value: string | null): AppRscRenderMode;
10
8
  //#endregion
11
- export { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI, APP_RSC_RENDER_MODE_NAVIGATION, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI, AppRscRenderMode, getRscRenderModeCacheVariant, parseAppRscRenderMode, shouldSuppressLoadingBoundaries };
9
+ export { APP_RSC_RENDER_MODE_NAVIGATION, APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, AppRscRenderMode, getRscRenderModeCacheVariant, parseAppRscRenderMode };