vinext 0.1.8 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/README.md +51 -30
  2. package/dist/build/inject-pregenerated-paths.d.ts +4 -0
  3. package/dist/build/inject-pregenerated-paths.js +18 -0
  4. package/dist/build/layout-classification.js +1 -1
  5. package/dist/build/nitro-route-rules.js +1 -1
  6. package/dist/build/pages-client-assets-module.d.ts +11 -0
  7. package/dist/build/pages-client-assets-module.js +27 -0
  8. package/dist/build/prerender.d.ts +2 -1
  9. package/dist/build/prerender.js +13 -6
  10. package/dist/build/report.d.ts +13 -2
  11. package/dist/build/report.js +99 -2
  12. package/dist/build/run-prerender.d.ts +7 -0
  13. package/dist/build/run-prerender.js +10 -1
  14. package/dist/build/standalone.js +2 -0
  15. package/dist/cache/cache-adapters-virtual.js +3 -3
  16. package/dist/check.js +40 -2
  17. package/dist/cli-args.d.ts +1 -2
  18. package/dist/cli-args.js +1 -1
  19. package/dist/cli-dev-config.d.ts +12 -0
  20. package/dist/cli-dev-config.js +23 -0
  21. package/dist/cli.js +111 -95
  22. package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
  23. package/dist/{server → client}/dev-error-overlay-store.js +1 -1
  24. package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
  25. package/dist/{server → client}/dev-error-overlay.js +2 -2
  26. package/dist/client/navigation-runtime.d.ts +2 -0
  27. package/dist/client/navigation-runtime.js +3 -1
  28. package/dist/client/window-next.d.ts +2 -1
  29. package/dist/cloudflare/index.d.ts +2 -2
  30. package/dist/cloudflare/index.js +2 -2
  31. package/dist/config/config-matchers.js +14 -10
  32. package/dist/config/next-config.d.ts +5 -3
  33. package/dist/config/next-config.js +44 -1
  34. package/dist/config/prerender.d.ts +34 -0
  35. package/dist/config/prerender.js +55 -0
  36. package/dist/entries/app-rsc-entry.d.ts +2 -1
  37. package/dist/entries/app-rsc-entry.js +40 -10
  38. package/dist/entries/app-rsc-manifest.js +2 -0
  39. package/dist/entries/pages-client-entry.d.ts +3 -0
  40. package/dist/entries/pages-client-entry.js +15 -1
  41. package/dist/entries/pages-server-entry.js +5 -2
  42. package/dist/image/image-adapters-virtual.d.ts +59 -0
  43. package/dist/image/image-adapters-virtual.js +59 -0
  44. package/dist/index.d.ts +33 -0
  45. package/dist/index.js +167 -100
  46. package/dist/init-cloudflare.d.ts +43 -0
  47. package/dist/init-cloudflare.js +839 -0
  48. package/dist/init-platform.d.ts +40 -0
  49. package/dist/init-platform.js +195 -0
  50. package/dist/init.d.ts +16 -38
  51. package/dist/init.js +209 -99
  52. package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
  53. package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
  54. package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
  55. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
  56. package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +1 -1
  57. package/dist/packages/cloudflare/src/deploy-config.js +150 -0
  58. package/dist/packages/cloudflare/src/deploy-help.js +55 -0
  59. package/dist/packages/cloudflare/src/deploy.js +276 -0
  60. package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
  61. package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +18 -15
  62. package/dist/plugins/ast-scope.d.ts +16 -0
  63. package/dist/plugins/ast-scope.js +62 -0
  64. package/dist/plugins/ast-utils.d.ts +27 -1
  65. package/dist/plugins/ast-utils.js +32 -1
  66. package/dist/plugins/css-module-imports.d.ts +14 -0
  67. package/dist/plugins/css-module-imports.js +59 -0
  68. package/dist/plugins/extensionless-dynamic-import.js +2 -2
  69. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  70. package/dist/plugins/ignore-dynamic-requests.js +530 -0
  71. package/dist/plugins/typeof-window.d.ts +1 -1
  72. package/dist/plugins/typeof-window.js +28 -56
  73. package/dist/routing/app-route-graph.d.ts +23 -2
  74. package/dist/routing/app-route-graph.js +126 -32
  75. package/dist/routing/file-matcher.d.ts +3 -0
  76. package/dist/routing/file-matcher.js +3 -0
  77. package/dist/routing/pages-router.js +2 -2
  78. package/dist/server/api-handler.js +9 -14
  79. package/dist/server/app-browser-action-result.d.ts +4 -1
  80. package/dist/server/app-browser-action-result.js +8 -1
  81. package/dist/server/app-browser-entry.js +161 -52
  82. package/dist/server/app-browser-interception-context.d.ts +1 -0
  83. package/dist/server/app-browser-interception-context.js +4 -2
  84. package/dist/server/app-browser-navigation-controller.d.ts +2 -0
  85. package/dist/server/app-browser-navigation-controller.js +60 -31
  86. package/dist/server/app-browser-server-action-client.d.ts +1 -1
  87. package/dist/server/app-browser-server-action-client.js +3 -4
  88. package/dist/server/app-browser-state.d.ts +11 -1
  89. package/dist/server/app-browser-state.js +25 -8
  90. package/dist/server/app-browser-visible-commit.d.ts +6 -1
  91. package/dist/server/app-browser-visible-commit.js +43 -25
  92. package/dist/server/app-elements-wire.d.ts +9 -2
  93. package/dist/server/app-elements-wire.js +8 -1
  94. package/dist/server/app-elements.d.ts +2 -2
  95. package/dist/server/app-elements.js +4 -3
  96. package/dist/server/app-fallback-renderer.d.ts +2 -1
  97. package/dist/server/app-fallback-renderer.js +10 -6
  98. package/dist/server/app-hydration-cache-publication.d.ts +11 -0
  99. package/dist/server/app-hydration-cache-publication.js +43 -0
  100. package/dist/server/app-middleware.d.ts +4 -3
  101. package/dist/server/app-middleware.js +8 -3
  102. package/dist/server/app-optimistic-routing.js +11 -4
  103. package/dist/server/app-page-cache-finalizer.js +2 -1
  104. package/dist/server/app-page-cache-render.d.ts +1 -0
  105. package/dist/server/app-page-cache-render.js +8 -4
  106. package/dist/server/app-page-cache.d.ts +1 -0
  107. package/dist/server/app-page-cache.js +5 -2
  108. package/dist/server/app-page-dispatch.js +1 -0
  109. package/dist/server/app-page-element-builder.d.ts +2 -1
  110. package/dist/server/app-page-element-builder.js +58 -4
  111. package/dist/server/app-page-probe.js +5 -0
  112. package/dist/server/app-page-render-identity.d.ts +1 -0
  113. package/dist/server/app-page-render-identity.js +1 -1
  114. package/dist/server/app-page-render.js +18 -0
  115. package/dist/server/app-page-request.d.ts +14 -0
  116. package/dist/server/app-page-request.js +69 -4
  117. package/dist/server/app-page-route-wiring.d.ts +8 -1
  118. package/dist/server/app-page-route-wiring.js +32 -18
  119. package/dist/server/app-page-segment-state.d.ts +2 -1
  120. package/dist/server/app-page-segment-state.js +3 -1
  121. package/dist/server/app-page-stream.d.ts +5 -0
  122. package/dist/server/app-page-stream.js +3 -1
  123. package/dist/server/app-route-handler-execution.js +5 -1
  124. package/dist/server/app-route-handler-response.js +1 -0
  125. package/dist/server/app-route-handler-runtime.js +1 -1
  126. package/dist/server/app-router-entry.js +9 -2
  127. package/dist/server/app-rsc-handler.d.ts +1 -0
  128. package/dist/server/app-rsc-handler.js +62 -31
  129. package/dist/server/app-rsc-request-normalization.d.ts +3 -2
  130. package/dist/server/app-rsc-request-normalization.js +6 -3
  131. package/dist/server/app-segment-config.d.ts +11 -0
  132. package/dist/server/app-segment-config.js +62 -6
  133. package/dist/server/app-server-action-execution.d.ts +1 -0
  134. package/dist/server/app-server-action-execution.js +58 -28
  135. package/dist/server/app-ssr-entry.d.ts +3 -0
  136. package/dist/server/app-ssr-entry.js +15 -7
  137. package/dist/server/app-ssr-stream.d.ts +7 -3
  138. package/dist/server/app-ssr-stream.js +10 -6
  139. package/dist/server/app-visited-response-cache.d.ts +6 -0
  140. package/dist/server/app-visited-response-cache.js +3 -1
  141. package/dist/server/client-trace-metadata.js +26 -0
  142. package/dist/server/default-global-not-found-module.d.ts +14 -0
  143. package/dist/server/default-global-not-found-module.js +14 -0
  144. package/dist/server/dev-route-files.js +4 -0
  145. package/dist/server/dev-server.js +19 -18
  146. package/dist/server/dev-stack-sourcemap.d.ts +1 -1
  147. package/dist/server/dev-stack-sourcemap.js +1 -1
  148. package/dist/server/fetch-handler.d.ts +2 -0
  149. package/dist/server/fetch-handler.js +18 -0
  150. package/dist/server/headers.d.ts +3 -15
  151. package/dist/server/headers.js +2 -15
  152. package/dist/server/image-optimization.d.ts +51 -1
  153. package/dist/server/image-optimization.js +52 -2
  154. package/dist/server/implicit-tags.js +1 -1
  155. package/dist/server/isr-cache.d.ts +1 -1
  156. package/dist/server/isr-cache.js +2 -2
  157. package/dist/server/metadata-routes.d.ts +3 -1
  158. package/dist/server/metadata-routes.js +12 -2
  159. package/dist/server/middleware-runtime.js +6 -1
  160. package/dist/server/navigation-planner.d.ts +1 -0
  161. package/dist/server/navigation-planner.js +14 -3
  162. package/dist/server/pages-api-route.js +2 -2
  163. package/dist/server/pages-asset-tags.d.ts +4 -6
  164. package/dist/server/pages-asset-tags.js +12 -12
  165. package/dist/server/pages-client-assets.d.ts +12 -0
  166. package/dist/server/pages-client-assets.js +10 -0
  167. package/dist/server/pages-node-compat.d.ts +8 -1
  168. package/dist/server/pages-node-compat.js +32 -4
  169. package/dist/server/pages-page-data.d.ts +24 -1
  170. package/dist/server/pages-page-data.js +45 -24
  171. package/dist/server/pages-page-handler.d.ts +2 -1
  172. package/dist/server/pages-page-handler.js +19 -12
  173. package/dist/server/pages-page-response.d.ts +7 -0
  174. package/dist/server/pages-page-response.js +4 -1
  175. package/dist/server/pages-request-pipeline.d.ts +2 -0
  176. package/dist/server/pages-request-pipeline.js +25 -1
  177. package/dist/server/pages-router-entry.d.ts +30 -0
  178. package/dist/server/pages-router-entry.js +108 -0
  179. package/dist/server/prerender-manifest.d.ts +3 -1
  180. package/dist/server/prerender-route-params.js +1 -1
  181. package/dist/server/prod-server.d.ts +1 -1
  182. package/dist/server/prod-server.js +33 -20
  183. package/dist/server/request-pipeline.js +1 -0
  184. package/dist/server/seed-cache.js +4 -4
  185. package/dist/shims/app-router-scroll-state.d.ts +1 -0
  186. package/dist/shims/app-router-scroll-state.js +1 -0
  187. package/dist/shims/app-router-scroll.js +2 -1
  188. package/dist/shims/cache.js +19 -15
  189. package/dist/shims/cdn-cache.js +1 -1
  190. package/dist/shims/dynamic-preload-chunks.js +2 -1
  191. package/dist/shims/form.d.ts +3 -1
  192. package/dist/shims/form.js +37 -43
  193. package/dist/shims/headers.d.ts +7 -1
  194. package/dist/shims/headers.js +17 -3
  195. package/dist/shims/image.js +75 -14
  196. package/dist/shims/internal/app-route-detection.d.ts +2 -17
  197. package/dist/shims/internal/app-route-detection.js +4 -17
  198. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
  199. package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
  200. package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -15
  201. package/dist/shims/internal/hybrid-client-route-owner.js +9 -60
  202. package/dist/shims/internal/pages-data-fetch-dedup.d.ts +9 -5
  203. package/dist/shims/internal/pages-data-fetch-dedup.js +73 -14
  204. package/dist/shims/internal/pages-data-target.d.ts +10 -9
  205. package/dist/shims/internal/pages-data-target.js +91 -12
  206. package/dist/shims/internal/pages-router-components.d.ts +7 -0
  207. package/dist/shims/internal/pages-router-components.js +13 -0
  208. package/dist/shims/layout-segment-context.d.ts +4 -1
  209. package/dist/shims/layout-segment-context.js +18 -4
  210. package/dist/shims/link.js +55 -26
  211. package/dist/shims/navigation.d.ts +5 -1
  212. package/dist/shims/navigation.js +45 -10
  213. package/dist/shims/navigation.react-server.js +1 -1
  214. package/dist/shims/root-params.d.ts +15 -1
  215. package/dist/shims/root-params.js +21 -1
  216. package/dist/shims/router.d.ts +5 -7
  217. package/dist/shims/router.js +362 -93
  218. package/dist/shims/server.js +3 -2
  219. package/dist/shims/slot.js +3 -6
  220. package/dist/utils/client-runtime-metadata.d.ts +2 -18
  221. package/dist/utils/client-runtime-metadata.js +31 -22
  222. package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
  223. package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
  224. package/dist/utils/domain-locale.d.ts +6 -3
  225. package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
  226. package/dist/{server → utils}/middleware-request-headers.js +2 -2
  227. package/dist/utils/project.d.ts +48 -2
  228. package/dist/utils/project.js +225 -4
  229. package/dist/utils/protocol-headers.d.ts +17 -0
  230. package/dist/utils/protocol-headers.js +17 -0
  231. package/dist/utils/react-version.d.ts +4 -0
  232. package/dist/utils/react-version.js +44 -0
  233. package/package.json +47 -2
  234. package/dist/deploy.d.ts +0 -197
  235. package/dist/deploy.js +0 -1040
  236. package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
  237. /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
@@ -1,8 +1,9 @@
1
- import { stripBasePath } from "../../utils/base-path.js";
1
+ import { removeTrailingSlash, stripBasePath } from "../../utils/base-path.js";
2
+ import { isUnknownRecord } from "../../utils/record.js";
2
3
  import { getLocalePathPrefix } from "../../utils/domain-locale.js";
3
4
  import { buildPagesDataHref, matchPagesPattern } from "./pages-data-url.js";
4
5
  import { NEXT_DEPLOYMENT_ID_HEADER, getDeploymentId } from "../../utils/deployment-id.js";
5
- import { dedupedPagesDataFetch } from "./pages-data-fetch-dedup.js";
6
+ import { fetchCachedPagesData, fetchStaticPagesData } from "./pages-data-fetch-dedup.js";
6
7
  //#region src/shims/internal/pages-data-target.ts
7
8
  /**
8
9
  * Shared decision helper for the Pages Router `/_next/data/<id>/<page>.json`
@@ -13,6 +14,75 @@ import { dedupedPagesDataFetch } from "./pages-data-fetch-dedup.js";
13
14
  * module init time — link.tsx and router.ts must remain free of circular
14
15
  * imports and SSR-side router-init side effects.
15
16
  */
17
+ function hasVinextMiddleware(nextData) {
18
+ if (!isUnknownRecord(nextData)) return false;
19
+ const vinext = nextData.__vinext;
20
+ return isUnknownRecord(vinext) && vinext.hasMiddleware === true;
21
+ }
22
+ function isClientMiddlewareMatcherObject(value) {
23
+ if (!isUnknownRecord(value)) return false;
24
+ if (typeof value.source !== "string") return false;
25
+ if (value.locale !== void 0 && value.locale !== false) return false;
26
+ if (value.has !== void 0 && !Array.isArray(value.has)) return false;
27
+ if (value.missing !== void 0 && !Array.isArray(value.missing)) return false;
28
+ return true;
29
+ }
30
+ function stripLocaleForMiddlewareMatcher(pathname) {
31
+ const locales = window.__VINEXT_LOCALES__;
32
+ if (!locales || locales.length === 0 || pathname === "/") return pathname;
33
+ const firstSegment = pathname.split("/")[1];
34
+ if (!firstSegment || !locales.includes(firstSegment)) return pathname;
35
+ return "/" + pathname.split("/").slice(2).join("/");
36
+ }
37
+ function clientMiddlewareSourceMatches(pathname, source) {
38
+ if (!/[\\():*+?]/.test(source)) return removeTrailingSlash(pathname) === removeTrailingSlash(source);
39
+ if (source.includes("(") || source.includes("\\")) return true;
40
+ const sourceParts = source.split("/").filter(Boolean);
41
+ const pathParts = pathname.split("/").filter(Boolean);
42
+ let pathIndex = 0;
43
+ for (const sourcePart of sourceParts) {
44
+ if (sourcePart.startsWith(":")) {
45
+ if (sourcePart.endsWith("*")) return true;
46
+ if (sourcePart.endsWith("+")) return pathIndex < pathParts.length;
47
+ if (pathIndex >= pathParts.length) return false;
48
+ pathIndex++;
49
+ continue;
50
+ }
51
+ if (pathParts[pathIndex] !== sourcePart) return false;
52
+ pathIndex++;
53
+ }
54
+ return pathIndex === pathParts.length;
55
+ }
56
+ function clientMiddlewareMatcherMatches(pathname, matcher) {
57
+ if (matcher === void 0) return true;
58
+ if (typeof matcher === "string") return clientMiddlewareSourceMatches(stripLocaleForMiddlewareMatcher(pathname), matcher);
59
+ if (!Array.isArray(matcher)) return true;
60
+ for (const item of matcher) {
61
+ if (typeof item === "string") {
62
+ if (clientMiddlewareSourceMatches(stripLocaleForMiddlewareMatcher(pathname), item)) return true;
63
+ continue;
64
+ }
65
+ if (!isClientMiddlewareMatcherObject(item)) return true;
66
+ if (clientMiddlewareSourceMatches(item.locale === false ? pathname : stripLocaleForMiddlewareMatcher(pathname), item.source)) return true;
67
+ }
68
+ return false;
69
+ }
70
+ function getPagesMiddlewareDataHref(browserUrl, basePath) {
71
+ const nextData = window.__NEXT_DATA__;
72
+ if (!nextData || !hasVinextMiddleware(nextData)) return null;
73
+ const buildId = nextData.buildId;
74
+ if (typeof buildId !== "string" || buildId.length === 0) return null;
75
+ let parsed;
76
+ try {
77
+ parsed = new URL(browserUrl, window.location.href);
78
+ } catch {
79
+ return null;
80
+ }
81
+ if (parsed.origin !== window.location.origin) return null;
82
+ const pathname = stripBasePath(parsed.pathname, basePath);
83
+ if (!clientMiddlewareMatcherMatches(pathname, window.__VINEXT_MIDDLEWARE_MATCHER__)) return null;
84
+ return buildPagesDataHref(basePath, buildId, pathname, parsed.search);
85
+ }
16
86
  /**
17
87
  * Decide whether the JSON data-endpoint navigation path is usable for this
18
88
  * browser URL. We require:
@@ -56,11 +126,16 @@ function resolvePagesDataNavigationTarget(browserUrl, basePath) {
56
126
  if (!match) return null;
57
127
  const loader = loaders[match.pattern];
58
128
  if (!loader) return null;
129
+ const ssgPatterns = window.__VINEXT_PAGES_SSG_PATTERNS__;
130
+ const sspPatterns = window.__VINEXT_PAGES_SSP_PATTERNS__;
131
+ const dataKind = ssgPatterns?.includes(match.pattern) ? "static" : sspPatterns?.includes(match.pattern) ? "server" : ssgPatterns === void 0 || sspPatterns === void 0 ? "server" : "none";
59
132
  return {
60
133
  dataHref: buildPagesDataHref(basePath, buildId, pagePath, parsed.search),
61
134
  pattern: match.pattern,
62
135
  params: match.params,
63
136
  loader,
137
+ dataKind,
138
+ middlewareDataHref: getPagesMiddlewareDataHref(browserUrl, basePath) ?? void 0,
64
139
  buildId,
65
140
  pagePath,
66
141
  search: parsed.search,
@@ -68,14 +143,12 @@ function resolvePagesDataNavigationTarget(browserUrl, basePath) {
68
143
  };
69
144
  }
70
145
  /**
71
- * Prefetch the data JSON and kick off the code-split loader so the chunk is
72
- * warm by the time the user clicks.
146
+ * Kick off the code-split loader and, for SSG pages, prefetch the data JSON so
147
+ * the chunk and payload are warm by the time the user clicks.
73
148
  *
74
- * Used by both `Router.prefetch()` and `<Link>` hover/viewport prefetch. The
75
- * JSON request uses `fetch()` rather than `<link rel="prefetch">` so it can
76
- * carry Next.js's `x-deployment-id` skew-protection header. The in-flight
77
- * request is shared with a racing navigation; after it settles, the browser's
78
- * normal HTTP cache remains responsible for reuse.
149
+ * Used by both `Router.prefetch()` and `<Link>` hover/viewport prefetch.
150
+ * Matches Next.js Pages Router prefetch: non-SSG routes only warm the page
151
+ * chunk, while `getStaticProps` routes also fetch `/_next/data`.
79
152
  *
80
153
  * loader's returned Promise is intentionally discarded — `import()` caches the
81
154
  * result, so a subsequent navigation re-invocation hits the cache without
@@ -84,15 +157,21 @@ function resolvePagesDataNavigationTarget(browserUrl, basePath) {
84
157
  */
85
158
  function prefetchPagesData(target) {
86
159
  if (typeof document === "undefined") return;
160
+ target.loader().catch(() => {});
161
+ if (target.dataKind !== "static" && !target.middlewareDataHref) return;
87
162
  const headers = {
88
163
  Accept: "application/json",
89
164
  purpose: "prefetch",
90
165
  "x-nextjs-data": "1"
91
166
  };
167
+ if (target.middlewareDataHref) headers["x-middleware-prefetch"] = "1";
92
168
  const deploymentId = getDeploymentId();
93
169
  if (deploymentId) headers[NEXT_DEPLOYMENT_ID_HEADER] = deploymentId;
94
- dedupedPagesDataFetch(target.dataHref, { headers }).catch(() => {});
95
- target.loader().catch(() => {});
170
+ if (target.dataKind === "static") {
171
+ fetchStaticPagesData(target.middlewareDataHref ?? target.dataHref, { headers }).catch(() => {});
172
+ return;
173
+ }
174
+ if (target.middlewareDataHref) fetchCachedPagesData(target.middlewareDataHref, { headers }).catch(() => {});
96
175
  }
97
176
  //#endregion
98
- export { prefetchPagesData, resolvePagesDataNavigationTarget };
177
+ export { getPagesMiddlewareDataHref, prefetchPagesData, resolvePagesDataNavigationTarget };
@@ -0,0 +1,7 @@
1
+ //#region src/shims/internal/pages-router-components.d.ts
2
+ type PagesRouterComponentsMap = Record<string, {
3
+ __appRouter: true;
4
+ } | Record<string, unknown>>;
5
+ declare function getPagesRouterComponentsMap(): PagesRouterComponentsMap;
6
+ //#endregion
7
+ export { PagesRouterComponentsMap, getPagesRouterComponentsMap };
@@ -0,0 +1,13 @@
1
+ //#region src/shims/internal/pages-router-components.ts
2
+ const COMPONENTS_KEY = Symbol.for("vinext.pagesRouter.components");
3
+ function getPagesRouterComponentsMap() {
4
+ const globalState = globalThis;
5
+ let components = globalState[COMPONENTS_KEY];
6
+ if (!components) {
7
+ components = {};
8
+ globalState[COMPONENTS_KEY] = components;
9
+ }
10
+ return components;
11
+ }
12
+ //#endregion
13
+ export { getPagesRouterComponentsMap };
@@ -2,6 +2,7 @@ import { SegmentMap } from "./navigation-context-state.js";
2
2
  import { ReactNode } from "react";
3
3
 
4
4
  //#region src/shims/layout-segment-context.d.ts
5
+ declare function mergeLayoutSegmentMap(previous: SegmentMap | null, next: SegmentMap): SegmentMap;
5
6
  /**
6
7
  * Wraps children with the layout segment context.
7
8
  *
@@ -14,11 +15,13 @@ import { ReactNode } from "react";
14
15
  * to read the segments for a specific parallel route.
15
16
  */
16
17
  declare function LayoutSegmentProvider({
18
+ providerId,
17
19
  segmentMap,
18
20
  children
19
21
  }: {
22
+ providerId?: string;
20
23
  segmentMap: SegmentMap;
21
24
  children: ReactNode;
22
25
  }): string | number | bigint | boolean | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").FunctionComponentElement<import("react").ProviderProps<SegmentMap>> | null | undefined;
23
26
  //#endregion
24
- export { LayoutSegmentProvider };
27
+ export { LayoutSegmentProvider, mergeLayoutSegmentMap };
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { getLayoutSegmentContext } from "./navigation-context-state.js";
3
3
  import "./navigation-server.js";
4
- import { createElement } from "react";
4
+ import { createElement, useEffect, useRef } from "react";
5
5
  //#region src/shims/layout-segment-context.tsx
6
6
  /**
7
7
  * Layout segment context provider.
@@ -19,6 +19,14 @@ import { createElement } from "react";
19
19
  * The context is shared with navigation.ts via getLayoutSegmentContext()
20
20
  * to avoid creating separate contexts in different modules.
21
21
  */
22
+ const committedSegmentMapsByProviderId = /* @__PURE__ */ new Map();
23
+ function mergeLayoutSegmentMap(previous, next) {
24
+ if (!previous) return next;
25
+ return {
26
+ ...previous,
27
+ ...next
28
+ };
29
+ }
22
30
  /**
23
31
  * Wraps children with the layout segment context.
24
32
  *
@@ -30,10 +38,16 @@ import { createElement } from "react";
30
38
  * Components inside the provider call useSelectedLayoutSegments(parallelRoutesKey)
31
39
  * to read the segments for a specific parallel route.
32
40
  */
33
- function LayoutSegmentProvider({ segmentMap, children }) {
41
+ function LayoutSegmentProvider({ providerId, segmentMap, children }) {
42
+ const previousSegmentMap = useRef(null);
34
43
  const ctx = getLayoutSegmentContext();
44
+ const mergedSegmentMap = mergeLayoutSegmentMap(previousSegmentMap.current ?? (providerId ? committedSegmentMapsByProviderId.get(providerId) ?? null : null), segmentMap);
45
+ useEffect(() => {
46
+ previousSegmentMap.current = mergedSegmentMap;
47
+ if (providerId) committedSegmentMapsByProviderId.set(providerId, mergedSegmentMap);
48
+ }, [mergedSegmentMap, providerId]);
35
49
  if (!ctx) return children;
36
- return createElement(ctx.Provider, { value: segmentMap }, children);
50
+ return createElement(ctx.Provider, { value: mergedSegmentMap }, children);
37
51
  }
38
52
  //#endregion
39
- export { LayoutSegmentProvider };
53
+ export { LayoutSegmentProvider, mergeLayoutSegmentMap };
@@ -1,24 +1,18 @@
1
1
  "use client";
2
2
  import { stripBasePath } from "../utils/base-path.js";
3
3
  import { createRouteTrieCache, matchRouteWithTrie } from "../routing/route-matching.js";
4
- import { VINEXT_MOUNTED_SLOTS_HEADER } from "../server/headers.js";
5
4
  import { isDangerousScheme, reportBlockedDangerousNavigation } from "./url-safety.js";
6
- import { AppElementsWire } from "../server/app-elements-wire.js";
7
- import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-render-mode.js";
8
- import "../server/app-elements.js";
9
5
  import { addLocalePrefix, getDomainLocaleUrl } from "../utils/domain-locale.js";
10
- import { prefetchPagesData, resolvePagesDataNavigationTarget } from "./internal/pages-data-target.js";
11
- import { appendSearchParamsToUrl, urlQueryToSearchParams } from "../utils/query.js";
12
- import { resolveHybridClientRouteOwner } from "./internal/hybrid-client-route-owner.js";
6
+ import { getPagesMiddlewareDataHref, prefetchPagesData, resolvePagesDataNavigationTarget } from "./internal/pages-data-target.js";
13
7
  import { markAppRouteDetectedOnPrefetch } from "./internal/app-route-detection.js";
14
8
  import { isAbsoluteOrProtocolRelativeUrl, normalizePathTrailingSlash, toBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
9
+ import { appendSearchParamsToUrl, urlQueryToSearchParams } from "../utils/query.js";
15
10
  import { interpolateDynamicRouteHref } from "./internal/interpolate-as.js";
16
11
  import { getCurrentBrowserLocale } from "./client-locale.js";
17
12
  import { getCurrentRoutePathnameForWarning } from "./internal/route-pattern-for-warning.js";
18
- import { createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam, stripRscSuffix } from "../server/app-rsc-cache-busting.js";
13
+ import { isBotUserAgent } from "../utils/html-limited-bots.js";
19
14
  import { getNavigationRuntime, hasAppNavigationRuntime, registerNavigationRuntimeFunctions } from "../client/navigation-runtime.js";
20
15
  import { navigatePagesRouterLinkWithFallback, resolvePagesRouterQueryOnlyHref } from "../client/pages-router-link-navigation.js";
21
- import { getMountedSlotsHeader, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, navigateClientSide, prefetchRscResponse } from "./navigation.js";
22
16
  import { getI18nContext } from "./i18n-context.js";
23
17
  import { canLinkIntentPrefetch, canLinkPrefetch, getLinkPrefetchHref } from "./link-prefetch.js";
24
18
  import { clearLinkForCurrentNavigation, notifyLinkNavigationStart, setLinkForCurrentNavigation } from "./internal/link-status-registry.js";
@@ -190,12 +184,13 @@ function resolveAutoAppRoutePrefetch(href) {
190
184
  *
191
185
  * For App Router (RSC): fetches the .rsc payload in the background and
192
186
  * stores it in an in-memory cache for instant use during navigation.
193
- * For Pages Router: injects a <link rel="prefetch"> for the page module.
187
+ * For Pages Router: warms the page chunk, prefetches data only for SSG pages,
188
+ * and falls back to a document prefetch hint when no page loader matches.
194
189
  *
195
190
  * Uses `requestIdleCallback` (or `setTimeout` fallback) to avoid blocking
196
191
  * the main thread during initial page load.
197
192
  */
198
- function prefetchUrl(href, mode, priority = "low") {
193
+ function prefetchUrl(href, mode, priority = "low", pagesRouteHref) {
199
194
  if (typeof window === "undefined") return;
200
195
  const prefetchHref = getLinkPrefetchHref({
201
196
  href,
@@ -204,6 +199,11 @@ function prefetchUrl(href, mode, priority = "low") {
204
199
  });
205
200
  if (prefetchHref == null) return;
206
201
  const fullHref = toBrowserNavigationHref(prefetchHref, window.location.href, __basePath);
202
+ const fullRouteHref = toBrowserNavigationHref(pagesRouteHref === void 0 ? prefetchHref : getLinkPrefetchHref({
203
+ href: pagesRouteHref,
204
+ basePath: __basePath,
205
+ currentOrigin: window.location.origin
206
+ }) ?? prefetchHref, window.location.href, __basePath);
207
207
  const target = new URL(fullHref, window.location.href);
208
208
  if (target.origin === window.location.origin && target.pathname === window.location.pathname && target.search === window.location.search) return;
209
209
  (priority === "high" ? (fn) => {
@@ -211,6 +211,18 @@ function prefetchUrl(href, mode, priority = "low") {
211
211
  } : window.requestIdleCallback ?? ((fn) => setTimeout(fn, 100)))(() => {
212
212
  (async () => {
213
213
  if (hasAppNavigationRuntime()) {
214
+ if (isBotUserAgent(window.navigator?.userAgent ?? "")) return;
215
+ const [navigation, { AppElementsWire }, rscCacheBusting, { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL }, headersModule, { resolveHybridClientRouteOwner }] = await Promise.all([
216
+ import("./navigation.js"),
217
+ import("../server/app-elements.js"),
218
+ import("../server/app-rsc-cache-busting.js"),
219
+ import("../server/app-rsc-render-mode.js"),
220
+ import("../server/headers.js"),
221
+ import("./internal/hybrid-client-route-owner.js")
222
+ ]);
223
+ const { getPrefetchInterceptionContext, getPrefetchCache, getPrefetchedUrls, getMountedSlotsHeader, hasPrefetchCacheEntryForNavigation, prefetchRscResponse, PREFETCH_CACHE_TTL } = navigation;
224
+ const { createRscRequestHeaders, createRscRequestUrl } = rscCacheBusting;
225
+ const { NEXT_ROUTER_PREFETCH_HEADER, VINEXT_MOUNTED_SLOTS_HEADER } = headersModule;
214
226
  const hybridOwner = resolveHybridClientRouteOwner(prefetchHref, __basePath);
215
227
  if (hybridOwner === "pages" || hybridOwner === "document") return;
216
228
  const autoPrefetch = mode === "auto" ? resolveAutoAppRoutePrefetch(prefetchHref) : {
@@ -228,6 +240,7 @@ function prefetchUrl(href, mode, priority = "low") {
228
240
  renderMode: isOptimisticRouteShellPrefetch ? APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL : void 0
229
241
  });
230
242
  if (mountedSlotsHeader) headers.set(VINEXT_MOUNTED_SLOTS_HEADER, mountedSlotsHeader);
243
+ if (isOptimisticRouteShellPrefetch) headers.set(NEXT_ROUTER_PREFETCH_HEADER, "1");
231
244
  const rscUrl = await createRscRequestUrl(fullHref, headers);
232
245
  const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
233
246
  const prefetched = getPrefetchedUrls();
@@ -266,13 +279,19 @@ function prefetchUrl(href, mode, priority = "low") {
266
279
  purpose: "prefetch"
267
280
  }), interceptionContext, mountedSlotsHeader, void 0, {
268
281
  cacheForNavigation: autoPrefetch.cacheForNavigation,
282
+ fallbackTtlMs: PREFETCH_CACHE_TTL,
269
283
  optimisticRouteShell: isOptimisticRouteShellPrefetch
270
284
  });
271
285
  } else if (HAS_PAGES_ROUTER && window.__NEXT_DATA__) {
272
- const dataTarget = resolvePagesDataNavigationTarget(fullHref, __basePath);
273
- if (dataTarget) prefetchPagesData(dataTarget);
274
- else {
275
- markAppRouteDetectedOnPrefetch(fullHref, __basePath);
286
+ const dataTarget = resolvePagesDataNavigationTarget(fullRouteHref, __basePath);
287
+ if (dataTarget) {
288
+ const middlewareDataHref = fullRouteHref === fullHref ? dataTarget.middlewareDataHref : getPagesMiddlewareDataHref(fullHref, __basePath) ?? void 0;
289
+ prefetchPagesData({
290
+ ...dataTarget,
291
+ middlewareDataHref
292
+ });
293
+ } else {
294
+ await markAppRouteDetectedOnPrefetch(fullHref, __basePath);
276
295
  const link = document.createElement("link");
277
296
  link.rel = "prefetch";
278
297
  link.href = fullHref;
@@ -285,8 +304,10 @@ function prefetchUrl(href, mode, priority = "low") {
285
304
  });
286
305
  });
287
306
  }
288
- function promotePrefetchEntriesForNavigation(href) {
307
+ async function promotePrefetchEntriesForNavigation(href) {
289
308
  if (typeof window === "undefined") return;
309
+ if (!hasAppNavigationRuntime()) return;
310
+ const [{ getPrefetchCache }, { stripRscCacheBustingSearchParam, stripRscSuffix }] = await Promise.all([import("./navigation.js"), import("../server/app-rsc-cache-busting.js")]);
290
311
  let target;
291
312
  try {
292
313
  target = new URL(toBrowserNavigationHref(href, window.location.href, __basePath), window.location.href);
@@ -318,7 +339,7 @@ function setVisibleLinkPrefetch(instance, isVisible) {
318
339
  if (isVisible) {
319
340
  visibleLinkPrefetches.add(instance);
320
341
  if (instance.routerMode === "pages" && instance.viewportPrefetched) return;
321
- prefetchUrl(instance.href, instance.mode, "low");
342
+ prefetchUrl(instance.href, instance.mode, "low", instance.pagesRouteHref);
322
343
  instance.viewportPrefetched = true;
323
344
  } else visibleLinkPrefetches.delete(instance);
324
345
  }
@@ -327,7 +348,7 @@ function registerVisibleLinkPing() {
327
348
  registerNavigationRuntimeFunctions({ pingVisibleLinks: pingVisibleLinkPrefetches });
328
349
  }
329
350
  function pingVisibleLinkPrefetches() {
330
- for (const instance of visibleLinkPrefetches) if (instance.isVisible && instance.routerMode === "app") prefetchUrl(instance.href, instance.mode, "low");
351
+ for (const instance of visibleLinkPrefetches) if (instance.isVisible && instance.routerMode === "app") prefetchUrl(instance.href, instance.mode, "low", instance.pagesRouteHref);
331
352
  }
332
353
  function getSharedObserver() {
333
354
  if (typeof window === "undefined" || typeof IntersectionObserver === "undefined") return null;
@@ -426,6 +447,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
426
447
  const resolvedHref = typeof rawResolvedHref === "string" ? warnAndNormalizeRepeatedSlashesInHref(rawResolvedHref) : rawResolvedHref;
427
448
  const isDangerous = typeof resolvedHref === "string" && isDangerousScheme(resolvedHref);
428
449
  const normalizedHref = normalizePathTrailingSlash(applyLocaleToHref(isDangerous ? "/" : resolvedHref, locale), __trailingSlash);
450
+ const normalizedRouteHref = HAS_PAGES_ROUTER && typeof as === "string" && typeof routeHrefRaw === "string" && as !== routeHrefRaw ? normalizePathTrailingSlash(applyLocaleToHref(isDangerous ? "/" : routeHrefRaw, locale), __trailingSlash) : normalizedHref;
429
451
  const fullHref = normalizePathTrailingSlash(withBasePath(normalizedHref, __basePath), __trailingSlash);
430
452
  const [pending, setPending] = useState(false);
431
453
  const mountedRef = useRef(true);
@@ -470,6 +492,11 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
470
492
  href: hrefToPrefetch,
471
493
  isVisible: false,
472
494
  mode: prefetchMode,
495
+ pagesRouteHref: normalizedRouteHref === normalizedHref ? void 0 : getLinkPrefetchHref({
496
+ href: normalizedRouteHref,
497
+ basePath: __basePath,
498
+ currentOrigin: window.location.origin
499
+ }) ?? void 0,
473
500
  routerMode: getLinkPrefetchRouterMode(),
474
501
  viewportPrefetched: false
475
502
  };
@@ -483,7 +510,8 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
483
510
  }, [
484
511
  shouldViewportPrefetch,
485
512
  prefetchMode,
486
- normalizedHref
513
+ normalizedHref,
514
+ normalizedRouteHref
487
515
  ]);
488
516
  const prefetchOnIntent = useCallback(() => {
489
517
  if (!canLinkIntentPrefetch({
@@ -498,12 +526,13 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
498
526
  if (instance) instance.mode = "full";
499
527
  promotePrefetchEntriesForNavigation(normalizedHref);
500
528
  }
501
- prefetchUrl(normalizedHref, intentMode, "high");
529
+ prefetchUrl(normalizedHref, intentMode, "high", normalizedRouteHref === normalizedHref ? void 0 : normalizedRouteHref);
502
530
  }, [
503
531
  prefetchProp,
504
532
  isDangerous,
505
533
  prefetchMode,
506
534
  normalizedHref,
535
+ normalizedRouteHref,
507
536
  unstable_dynamicOnHover
508
537
  ]);
509
538
  const handleMouseEnter = useCallback((e) => {
@@ -553,12 +582,14 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
553
582
  onNavigate(navEvent);
554
583
  if (navEvent.defaultPrevented) return;
555
584
  } catch {}
556
- if (HAS_PAGES_ROUTER && hasAppNavigationRuntime && ["pages", "document"].includes(resolveHybridClientRouteOwner(navigateHref, __basePath) ?? "")) {
585
+ const hybridOwner = HAS_PAGES_ROUTER && hasAppNavigationRuntime ? (await import("./internal/hybrid-client-route-owner.js")).resolveHybridClientRouteOwner(navigateHref, __basePath) : null;
586
+ if (HAS_PAGES_ROUTER && hasAppNavigationRuntime && ["pages", "document"].includes(hybridOwner ?? "")) {
557
587
  if (replace) window.location.replace(absoluteFullHref);
558
588
  else window.location.assign(absoluteFullHref);
559
589
  return;
560
590
  }
561
591
  if (hasAppNavigationRuntime) {
592
+ const { navigateClientSide } = await import("./navigation.js");
562
593
  const setter = setPendingRef.current;
563
594
  if (setter) setLinkForCurrentNavigation(setter);
564
595
  setPending(true);
@@ -573,7 +604,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
573
604
  const Router = window.next?.appDir === true ? void 0 : window.next?.router;
574
605
  await navigatePagesRouterLinkWithFallback({
575
606
  router: Router && "reload" in Router ? Router : void 0,
576
- loadRouter: async () => (await import("next/router.js")).default,
607
+ loadRouter: async () => (await import("next/router")).default,
577
608
  navigation: {
578
609
  href: pagesHrefForLink,
579
610
  as: pagesAsForLink,
@@ -651,7 +682,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
651
682
  onClick: (event) => {
652
683
  if (childOnClick) childOnClick(event);
653
684
  if (event.defaultPrevented) return;
654
- handleClick(event, { skipLinkOnClick: true });
685
+ return handleClick(event, { skipLinkOnClick: true });
655
686
  },
656
687
  onMouseEnter: (event) => {
657
688
  if (childOnMouseEnter) childOnMouseEnter(event);
@@ -673,9 +704,7 @@ const Link = forwardRef(function Link({ href, as, replace = false, prefetch: pre
673
704
  children: /* @__PURE__ */ jsx("a", {
674
705
  ref: setRefs,
675
706
  href: fullHref,
676
- onClick: (event) => {
677
- handleClick(event);
678
- },
707
+ onClick: handleClick,
679
708
  onMouseEnter: handleMouseEnter,
680
709
  onTouchStart: handleTouchStart,
681
710
  ...anchorProps,
@@ -12,6 +12,7 @@ import * as React$1 from "react";
12
12
  declare const __basePath: string;
13
13
  /** Maximum number of entries in the RSC prefetch cache. */
14
14
  declare const MAX_PREFETCH_CACHE_SIZE = 50;
15
+ declare const DYNAMIC_NAVIGATION_CACHE_TTL: number;
15
16
  declare const PREFETCH_CACHE_TTL: number;
16
17
  /** A buffered RSC response stored as an ArrayBuffer for replay. */
17
18
  type CachedRscResponse = {
@@ -57,6 +58,8 @@ declare function hasPrefetchCacheEntryForNavigation(rscUrl: string, interception
57
58
  notifyInvalidation?: boolean;
58
59
  }): boolean;
59
60
  declare function invalidatePrefetchCache(): void;
61
+ declare function seedPrefetchResponseSnapshot(rscUrl: string, snapshot: CachedRscResponse, interceptionContext?: string | null, mountedSlotsHeader?: string | null, fallbackTtlMs?: number): void;
62
+ declare function deletePrefetchResponseSnapshot(rscUrl: string, snapshot: CachedRscResponse, interceptionContext?: string | null): void;
60
63
  /**
61
64
  * Store a prefetched RSC response in the cache by snapshotting it to an
62
65
  * ArrayBuffer. The snapshot completes asynchronously; during that window
@@ -105,6 +108,7 @@ declare function restoreRscResponse(cached: CachedRscResponse, copy?: boolean):
105
108
  */
106
109
  declare function prefetchRscResponse(rscUrl: string, fetchPromise: Promise<Response>, interceptionContext?: string | null, mountedSlotsHeader?: string | null, options?: PrefetchOptions, behavior?: {
107
110
  cacheForNavigation?: boolean;
111
+ fallbackTtlMs?: number;
108
112
  optimisticRouteShell?: boolean;
109
113
  }): void;
110
114
  /**
@@ -283,4 +287,4 @@ declare function useSelectedLayoutSegments(parallelRoutesKey?: string): string[]
283
287
  */
284
288
  declare function useServerInsertedHTML(callback: () => unknown): void;
285
289
  //#endregion
286
- export { BailoutToCSRError, CachedRscResponse, ClientNavigationRenderSnapshot, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, type NavigationContext, type NavigationStateAccessors, PREFETCH_CACHE_TTL, PrefetchCacheEntry, PrefetchOptions, ReadonlyURLSearchParams, RedirectType, type SegmentMap, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, permanentRedirect, prefetchRscResponse, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
290
+ export { BailoutToCSRError, CachedRscResponse, ClientNavigationRenderSnapshot, DYNAMIC_NAVIGATION_CACHE_TTL, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, type NavigationContext, type NavigationStateAccessors, PREFETCH_CACHE_TTL, PrefetchCacheEntry, PrefetchOptions, ReadonlyURLSearchParams, RedirectType, type SegmentMap, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, deletePrefetchResponseSnapshot, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, permanentRedirect, prefetchRscResponse, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
@@ -5,11 +5,11 @@ import { AppElementsWire } from "../server/app-elements-wire.js";
5
5
  import "../server/app-elements.js";
6
6
  import { markPprFallbackShellDynamicBoundary } from "./ppr-fallback-shell.js";
7
7
  import { AppRouterContext } from "./internal/app-router-context.js";
8
- import { resolveHybridClientRouteOwner } from "./internal/hybrid-client-route-owner.js";
9
8
  import { isAbsoluteOrProtocolRelativeUrl, toBrowserNavigationHref, toSameOriginAppPath, withBasePath } from "./url-utils.js";
10
9
  import { retryScrollTo, scrollToHashTarget } from "./hash-scroll.js";
11
10
  import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearClientHydrationContext, clearServerInsertedHTML, flushServerInsertedHTML, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getLayoutSegmentContext, getNavigationContext, registerServerInsertedHTMLCallback, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
12
11
  import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, decodeRedirectError, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
12
+ import { isBotUserAgent } from "../utils/html-limited-bots.js";
13
13
  import { clearAppNavigationFailureTarget, stageAppNavigationFailureTarget } from "../client/app-nav-failure-handler.js";
14
14
  import { beginAppRouterScrollIntent, clearAppRouterScrollIntent, consumeAppRouterScrollIntent, getPendingAppRouterScrollIntent } from "./app-router-scroll-state.js";
15
15
  import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, createRscRequestHeaders, createRscRequestUrl, stripRscCacheBustingSearchParam } from "../server/app-rsc-cache-busting.js";
@@ -22,6 +22,7 @@ import { hasPendingAppRouterPageRedirect } from "../server/app-browser-mpa-navig
22
22
  import { navigationPlanner } from "../server/navigation-planner.js";
23
23
  import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
24
24
  import { getPagesNavigationContext } from "./internal/pages-router-accessor.js";
25
+ import { resolveHybridClientRouteOwner } from "./internal/hybrid-client-route-owner.js";
25
26
  import { UnrecognizedActionError, unstable_isUnrecognizedActionError } from "./unrecognized-action-error.js";
26
27
  import * as React$1 from "react";
27
28
  //#region src/shims/navigation.ts
@@ -41,7 +42,7 @@ function useChildSegments(parallelRoutesKey = "children") {
41
42
  const ctx = getLayoutSegmentContext();
42
43
  if (!ctx) return [];
43
44
  try {
44
- return React$1.useContext(ctx)[parallelRoutesKey] ?? [];
45
+ return (React$1.useContext(ctx)[parallelRoutesKey] ?? []).filter((segment) => !segment.startsWith("__PAGE__"));
45
46
  } catch {
46
47
  return [];
47
48
  }
@@ -69,14 +70,15 @@ const MAX_PREFETCH_CACHE_SIZE = 50;
69
70
  * has not set `experimental.staleTimes`, Next.js' 300s default applies
70
71
  * (see `resolveStaleTimes` in `config/next-config.ts`).
71
72
  */
72
- function resolvePrefetchCacheTtl() {
73
- const raw = process.env.__NEXT_CLIENT_ROUTER_STATIC_STALETIME;
74
- if (raw === void 0 || raw === "") return 3e4;
73
+ function resolveClientRouterStaleTime(raw, fallbackMs) {
74
+ if (raw === void 0 || raw === "") return fallbackMs;
75
75
  const seconds = Number(raw);
76
- if (!Number.isFinite(seconds) || seconds < 0) return 3e4;
76
+ if (!Number.isFinite(seconds) || seconds < 0) return fallbackMs;
77
77
  return seconds * 1e3;
78
78
  }
79
- const PREFETCH_CACHE_TTL = resolvePrefetchCacheTtl();
79
+ const DYNAMIC_NAVIGATION_CACHE_TTL = resolveClientRouterStaleTime(process.env.__NEXT_CLIENT_ROUTER_DYNAMIC_STALETIME, 3e4);
80
+ const PREFETCH_CACHE_TTL = resolveClientRouterStaleTime(process.env.__NEXT_CLIENT_ROUTER_STATIC_STALETIME, 3e4);
81
+ const MIN_PREFETCH_STALE_TIME_MS = 3e4;
80
82
  function getCurrentInterceptionContext() {
81
83
  if (isServer) return null;
82
84
  return stripBasePath(window.location.pathname, __basePath);
@@ -135,6 +137,12 @@ function resolveCachedRscResponseExpiresAt(timestamp, cached, fallbackTtlMs) {
135
137
  if (isCacheExpiresAt(cached.expiresAt)) return cached.expiresAt;
136
138
  return timestamp + resolveCachedRscResponseTtlMs(cached, fallbackTtlMs);
137
139
  }
140
+ function resolvePrefetchedRscResponseExpiresAt(timestamp, cached, fallbackTtlMs) {
141
+ if (isCacheExpiresAt(cached.expiresAt)) return cached.expiresAt;
142
+ const seconds = cached.dynamicStaleTimeSeconds;
143
+ if (!isDynamicStaleTimeSeconds(seconds)) return timestamp + Math.max(fallbackTtlMs, MIN_PREFETCH_STALE_TIME_MS);
144
+ return timestamp + Math.max(seconds * 1e3, MIN_PREFETCH_STALE_TIME_MS);
145
+ }
138
146
  function resolvePrefetchCacheEntryExpiresAt(entry) {
139
147
  if (entry.expiresAt !== void 0) return entry.expiresAt;
140
148
  if (entry.snapshot) return resolveCachedRscResponseExpiresAt(entry.timestamp, entry.snapshot, PREFETCH_CACHE_TTL);
@@ -282,6 +290,32 @@ function invalidatePrefetchCache() {
282
290
  prefetched.clear();
283
291
  if (!isServer) getNavigationRuntime()?.functions.pingVisibleLinks?.();
284
292
  }
293
+ function seedPrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = null, mountedSlotsHeader = null, fallbackTtlMs = DYNAMIC_NAVIGATION_CACHE_TTL) {
294
+ const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
295
+ const cache = getPrefetchCache();
296
+ const existing = cache.get(cacheKey);
297
+ if (existing) deletePrefetchCacheEntry(cache, getPrefetchedUrls(), cacheKey, existing, false);
298
+ evictPrefetchCacheIfNeeded();
299
+ const timestamp = Date.now();
300
+ const entry = {
301
+ cacheForNavigation: true,
302
+ expiresAt: resolveCachedRscResponseExpiresAt(timestamp, snapshot, fallbackTtlMs),
303
+ mountedSlotsHeader,
304
+ outcome: "cache-seeded",
305
+ snapshot,
306
+ timestamp
307
+ };
308
+ cache.set(cacheKey, entry);
309
+ getPrefetchedUrls().add(cacheKey);
310
+ schedulePrefetchInvalidation(cacheKey, entry);
311
+ }
312
+ function deletePrefetchResponseSnapshot(rscUrl, snapshot, interceptionContext = null) {
313
+ const cacheKey = AppElementsWire.encodeCacheKey(rscUrl, interceptionContext);
314
+ const cache = getPrefetchCache();
315
+ const entry = cache.get(cacheKey);
316
+ if (entry?.snapshot !== snapshot) return;
317
+ deletePrefetchCacheEntry(cache, getPrefetchedUrls(), cacheKey, entry, false);
318
+ }
285
319
  /**
286
320
  * Store a prefetched RSC response in the cache by snapshotting it to an
287
321
  * ArrayBuffer. The snapshot completes asynchronously; during that window
@@ -390,7 +424,7 @@ function prefetchRscResponse(rscUrl, fetchPromise, interceptionContext = null, m
390
424
  entry.pending = fetchPromise.then(async (response) => {
391
425
  if (response.ok) {
392
426
  entry.snapshot = await snapshotRscResponse(response);
393
- entry.expiresAt = resolveCachedRscResponseExpiresAt(entry.timestamp, entry.snapshot, PREFETCH_CACHE_TTL);
427
+ entry.expiresAt = resolvePrefetchedRscResponseExpiresAt(entry.timestamp, entry.snapshot, behavior.fallbackTtlMs ?? PREFETCH_CACHE_TTL);
394
428
  } else deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, false);
395
429
  }).catch(() => {
396
430
  deletePrefetchCacheEntry(cache, prefetched, cacheKey, entry, false);
@@ -772,7 +806,7 @@ function commitClientNavigationState(navId, options) {
772
806
  if (isServer) return;
773
807
  const state = getClientNavigationState();
774
808
  if (!state) return;
775
- if ((navId !== void 0 || options?.releaseSnapshot === true) && state.navigationSnapshotActiveCount > 0) state.navigationSnapshotActiveCount -= 1;
809
+ if ((options?.releaseSnapshot ?? navId !== void 0) && state.navigationSnapshotActiveCount > 0) state.navigationSnapshotActiveCount -= 1;
776
810
  const urlChanged = syncCommittedUrlStateFromLocation();
777
811
  let paramsChanged = false;
778
812
  if (state.pendingClientParams !== null && state.pendingClientParamsJson !== null) {
@@ -1033,6 +1067,7 @@ const _appRouter = {
1033
1067
  prefetch(href, options) {
1034
1068
  assertSafeNavigationUrl(href);
1035
1069
  if (isServer) return;
1070
+ if (isBotUserAgent(window.navigator?.userAgent ?? "")) return;
1036
1071
  try {
1037
1072
  new URL(withBasePath(href, __basePath), window.location.href);
1038
1073
  } catch {
@@ -1203,4 +1238,4 @@ if (!isServer) {
1203
1238
  }
1204
1239
  }
1205
1240
  //#endregion
1206
- export { BailoutToCSRError, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, PREFETCH_CACHE_TTL, ReadonlyURLSearchParams, RedirectType, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, permanentRedirect, prefetchRscResponse, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
1241
+ export { BailoutToCSRError, DYNAMIC_NAVIGATION_CACHE_TTL, DynamicServerError, GLOBAL_ACCESSORS_KEY, HTTP_ERROR_FALLBACK_ERROR_CODE, MAX_PREFETCH_CACHE_SIZE, PREFETCH_CACHE_TTL, ReadonlyURLSearchParams, RedirectType, ServerInsertedHTMLContext, UnrecognizedActionError, __basePath, _registerStateAccessors, activateNavigationSnapshot, appRouterInstance, applyAppRouterScrollFallback, clearPendingPathname, clearServerInsertedHTML, commitClientNavigationState, consumePrefetchResponse, consumePrefetchResponseForNavigation, createCachedRscResponseSnapshot, createClientNavigationRenderSnapshot, createSnapshotPathAndSearch, decodeRedirectError, deletePrefetchResponseSnapshot, flushServerInsertedHTML, forbidden, getAccessFallbackHTTPStatus, getBfcacheIdMapContext, getBfcacheSegmentIdContext, getClientNavigationRenderContext, getClientNavigationState, getClientParams, getCurrentInterceptionContext, getCurrentNextUrl, getLayoutSegmentContext, getMountedSlotsHeader, getNavigationContext, getPrefetchCache, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, invalidatePrefetchCache, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, navigateClientSide, notFound, permanentRedirect, prefetchRscResponse, pushHistoryStateWithoutNotify, redirect, renderServerInsertedHTML, replaceClientParamsWithoutNotify, replaceHistoryStateWithoutNotify, resolveCachedRscResponseExpiresAt, resolveCachedRscResponseTtlMs, resolvePrefetchCacheEntryMountedSlotsHeader, restoreRscResponse, saveScrollPosition, seedPrefetchResponseSnapshot, setClientParams, setMountedSlotsHeader, setNavigationContext, setPendingPathname, snapshotRscResponse, storePrefetchResponse, unauthorized, unstable_isUnrecognizedActionError, unstable_rethrow, useClientNavigationRenderSnapshot, useParams, usePathname, useRouter, useSearchParams, useSelectedLayoutSegment, useSelectedLayoutSegments, useServerInsertedHTML };
@@ -1,8 +1,8 @@
1
1
  import { GLOBAL_ACCESSORS_KEY, ServerInsertedHTMLContext, _registerStateAccessors, clearServerInsertedHTML, flushServerInsertedHTML, getLayoutSegmentContext, getNavigationContext, renderServerInsertedHTML, setNavigationContext } from "./navigation-context-state.js";
2
2
  import { BailoutToCSRError, DynamicServerError, HTTP_ERROR_FALLBACK_ERROR_CODE, RedirectType, forbidden, getAccessFallbackHTTPStatus, isBailoutToCSRError, isDynamicServerError, isHTTPAccessFallbackError, isNextRouterError, isRedirectError, notFound, permanentRedirect, redirect, unauthorized, unstable_rethrow } from "./navigation-errors.js";
3
3
  import "./navigation-server.js";
4
- import { throwClientHookError } from "./client-hook-error.js";
5
4
  import { ReadonlyURLSearchParams } from "./readonly-url-search-params.js";
5
+ import { throwClientHookError } from "./client-hook-error.js";
6
6
  //#region src/shims/navigation.react-server.ts
7
7
  function usePathname() {
8
8
  throwClientHookError("usePathname()");