vinext 0.1.1 → 0.1.3

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 (266) hide show
  1. package/README.md +2 -5
  2. package/dist/build/client-build-config.d.ts +7 -1
  3. package/dist/build/client-build-config.js +9 -1
  4. package/dist/build/prerender.d.ts +9 -1
  5. package/dist/build/prerender.js +41 -12
  6. package/dist/build/run-prerender.d.ts +10 -2
  7. package/dist/build/run-prerender.js +15 -1
  8. package/dist/check.js +4 -3
  9. package/dist/client/app-nav-failure-handler.d.ts +8 -0
  10. package/dist/client/app-nav-failure-handler.js +44 -0
  11. package/dist/client/navigation-runtime.d.ts +3 -2
  12. package/dist/client/vinext-next-data.d.ts +18 -1
  13. package/dist/client/window-next.d.ts +8 -5
  14. package/dist/client/window-next.js +12 -1
  15. package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
  16. package/dist/config/config-matchers.d.ts +11 -4
  17. package/dist/config/config-matchers.js +88 -16
  18. package/dist/config/next-config.d.ts +59 -4
  19. package/dist/config/next-config.js +149 -48
  20. package/dist/deploy.d.ts +30 -11
  21. package/dist/deploy.js +189 -101
  22. package/dist/entries/app-browser-entry.d.ts +9 -3
  23. package/dist/entries/app-browser-entry.js +21 -3
  24. package/dist/entries/app-rsc-entry.d.ts +2 -0
  25. package/dist/entries/app-rsc-entry.js +71 -6
  26. package/dist/entries/app-rsc-manifest.js +2 -0
  27. package/dist/entries/app-ssr-entry.js +1 -1
  28. package/dist/entries/pages-client-entry.js +54 -9
  29. package/dist/entries/pages-server-entry.js +48 -11
  30. package/dist/index.d.ts +0 -2
  31. package/dist/index.js +285 -139
  32. package/dist/plugins/dynamic-preload-metadata.d.ts +13 -0
  33. package/dist/plugins/dynamic-preload-metadata.js +415 -0
  34. package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
  35. package/dist/plugins/extensionless-dynamic-import.js +152 -0
  36. package/dist/plugins/og-assets.js +2 -2
  37. package/dist/plugins/optimize-imports.d.ts +10 -5
  38. package/dist/plugins/optimize-imports.js +27 -21
  39. package/dist/plugins/postcss.js +7 -7
  40. package/dist/plugins/sass.d.ts +53 -24
  41. package/dist/plugins/sass.js +249 -1
  42. package/dist/plugins/typeof-window.d.ts +14 -0
  43. package/dist/plugins/typeof-window.js +150 -0
  44. package/dist/plugins/wasm-module-import.d.ts +15 -0
  45. package/dist/plugins/wasm-module-import.js +50 -0
  46. package/dist/routing/app-route-graph.d.ts +25 -2
  47. package/dist/routing/app-route-graph.js +91 -22
  48. package/dist/routing/file-matcher.d.ts +10 -1
  49. package/dist/routing/file-matcher.js +23 -2
  50. package/dist/routing/pages-router.js +3 -3
  51. package/dist/routing/utils.d.ts +35 -6
  52. package/dist/routing/utils.js +59 -7
  53. package/dist/server/api-handler.d.ts +6 -1
  54. package/dist/server/api-handler.js +21 -15
  55. package/dist/server/app-browser-action-result.d.ts +19 -6
  56. package/dist/server/app-browser-action-result.js +19 -10
  57. package/dist/server/app-browser-entry.js +269 -297
  58. package/dist/server/app-browser-error.d.ts +10 -3
  59. package/dist/server/app-browser-error.js +47 -6
  60. package/dist/server/app-browser-history-controller.d.ts +104 -0
  61. package/dist/server/app-browser-history-controller.js +210 -0
  62. package/dist/server/app-browser-hydration.d.ts +2 -0
  63. package/dist/server/app-browser-hydration.js +1 -0
  64. package/dist/server/app-browser-navigation-controller.d.ts +7 -4
  65. package/dist/server/app-browser-navigation-controller.js +33 -9
  66. package/dist/server/app-browser-rsc-redirect.d.ts +11 -2
  67. package/dist/server/app-browser-rsc-redirect.js +30 -8
  68. package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
  69. package/dist/server/app-browser-server-action-navigation.js +9 -0
  70. package/dist/server/app-browser-state.js +4 -7
  71. package/dist/server/app-browser-stream.js +86 -43
  72. package/dist/server/app-browser-visible-commit.js +1 -1
  73. package/dist/server/app-elements-wire.d.ts +6 -1
  74. package/dist/server/app-elements-wire.js +14 -4
  75. package/dist/server/app-elements.d.ts +2 -2
  76. package/dist/server/app-elements.js +2 -2
  77. package/dist/server/app-fallback-renderer.d.ts +3 -1
  78. package/dist/server/app-fallback-renderer.js +6 -2
  79. package/dist/server/app-middleware.js +1 -0
  80. package/dist/server/app-optimistic-routing.js +24 -3
  81. package/dist/server/app-page-boundary-render.d.ts +3 -1
  82. package/dist/server/app-page-boundary-render.js +31 -16
  83. package/dist/server/app-page-cache-render.d.ts +53 -0
  84. package/dist/server/app-page-cache-render.js +91 -0
  85. package/dist/server/app-page-cache.d.ts +16 -2
  86. package/dist/server/app-page-cache.js +71 -8
  87. package/dist/server/app-page-dispatch.d.ts +34 -0
  88. package/dist/server/app-page-dispatch.js +167 -97
  89. package/dist/server/app-page-element-builder.d.ts +23 -2
  90. package/dist/server/app-page-element-builder.js +42 -10
  91. package/dist/server/app-page-execution.d.ts +7 -2
  92. package/dist/server/app-page-execution.js +53 -18
  93. package/dist/server/app-page-probe.d.ts +1 -0
  94. package/dist/server/app-page-probe.js +4 -0
  95. package/dist/server/app-page-render-observation.d.ts +3 -1
  96. package/dist/server/app-page-render-observation.js +17 -1
  97. package/dist/server/app-page-render.d.ts +13 -2
  98. package/dist/server/app-page-render.js +48 -17
  99. package/dist/server/app-page-request.d.ts +3 -0
  100. package/dist/server/app-page-request.js +5 -3
  101. package/dist/server/app-page-response.js +1 -1
  102. package/dist/server/app-page-route-wiring.d.ts +5 -1
  103. package/dist/server/app-page-route-wiring.js +21 -11
  104. package/dist/server/app-page-stream.d.ts +16 -9
  105. package/dist/server/app-page-stream.js +12 -9
  106. package/dist/server/app-pages-bridge.d.ts +18 -0
  107. package/dist/server/app-pages-bridge.js +22 -5
  108. package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
  109. package/dist/server/app-ppr-fallback-shell-render.js +26 -0
  110. package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
  111. package/dist/server/app-ppr-fallback-shell.js +8 -1
  112. package/dist/server/app-route-handler-dispatch.js +9 -2
  113. package/dist/server/app-route-handler-policy.d.ts +1 -0
  114. package/dist/server/app-route-handler-response.js +11 -10
  115. package/dist/server/app-route-handler-runtime.js +12 -1
  116. package/dist/server/app-router-entry.js +5 -0
  117. package/dist/server/app-rsc-cache-busting.js +2 -0
  118. package/dist/server/app-rsc-handler.d.ts +25 -0
  119. package/dist/server/app-rsc-handler.js +153 -53
  120. package/dist/server/app-rsc-response-finalizer.js +1 -1
  121. package/dist/server/app-rsc-route-matching.d.ts +3 -0
  122. package/dist/server/app-rsc-route-matching.js +2 -0
  123. package/dist/server/app-segment-config.d.ts +9 -1
  124. package/dist/server/app-segment-config.js +12 -3
  125. package/dist/server/app-server-action-execution.d.ts +12 -0
  126. package/dist/server/app-server-action-execution.js +47 -15
  127. package/dist/server/app-ssr-entry.d.ts +2 -0
  128. package/dist/server/app-ssr-entry.js +81 -8
  129. package/dist/server/app-ssr-stream.js +9 -1
  130. package/dist/server/cache-control.js +4 -0
  131. package/dist/server/dev-lockfile.js +2 -1
  132. package/dist/server/dev-server.d.ts +2 -2
  133. package/dist/server/dev-server.js +287 -63
  134. package/dist/server/headers.d.ts +8 -1
  135. package/dist/server/headers.js +8 -1
  136. package/dist/server/hybrid-route-priority.d.ts +22 -0
  137. package/dist/server/hybrid-route-priority.js +33 -0
  138. package/dist/server/image-optimization.d.ts +18 -9
  139. package/dist/server/image-optimization.js +37 -23
  140. package/dist/server/implicit-tags.d.ts +2 -1
  141. package/dist/server/implicit-tags.js +4 -1
  142. package/dist/server/instrumentation-runtime.d.ts +6 -0
  143. package/dist/server/instrumentation-runtime.js +8 -0
  144. package/dist/server/isr-decision.d.ts +79 -0
  145. package/dist/server/isr-decision.js +70 -0
  146. package/dist/server/metadata-route-response.js +5 -3
  147. package/dist/server/middleware-runtime.d.ts +13 -0
  148. package/dist/server/middleware-runtime.js +11 -7
  149. package/dist/server/middleware.js +1 -0
  150. package/dist/server/navigation-planner.d.ts +186 -22
  151. package/dist/server/navigation-planner.js +302 -0
  152. package/dist/server/navigation-trace.d.ts +18 -1
  153. package/dist/server/navigation-trace.js +18 -1
  154. package/dist/server/normalize-path.d.ts +0 -8
  155. package/dist/server/normalize-path.js +3 -1
  156. package/dist/server/otel-tracer-extension.d.ts +45 -0
  157. package/dist/server/otel-tracer-extension.js +89 -0
  158. package/dist/server/pages-api-route.d.ts +20 -3
  159. package/dist/server/pages-api-route.js +19 -3
  160. package/dist/server/pages-asset-tags.d.ts +16 -4
  161. package/dist/server/pages-asset-tags.js +22 -12
  162. package/dist/server/pages-data-route.d.ts +8 -1
  163. package/dist/server/pages-data-route.js +16 -3
  164. package/dist/server/pages-get-initial-props.d.ts +54 -4
  165. package/dist/server/pages-get-initial-props.js +43 -1
  166. package/dist/server/pages-node-compat.d.ts +3 -11
  167. package/dist/server/pages-node-compat.js +175 -122
  168. package/dist/server/pages-page-data.d.ts +39 -2
  169. package/dist/server/pages-page-data.js +261 -46
  170. package/dist/server/pages-page-handler.d.ts +5 -2
  171. package/dist/server/pages-page-handler.js +78 -25
  172. package/dist/server/pages-page-response.d.ts +47 -2
  173. package/dist/server/pages-page-response.js +73 -9
  174. package/dist/server/pages-readiness.d.ts +1 -1
  175. package/dist/server/pages-request-pipeline.d.ts +16 -1
  176. package/dist/server/pages-request-pipeline.js +96 -38
  177. package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
  178. package/dist/server/pregenerated-concrete-paths.js +2 -19
  179. package/dist/server/prerender-manifest.d.ts +33 -0
  180. package/dist/server/prerender-manifest.js +54 -0
  181. package/dist/server/prerender-route-params.d.ts +1 -2
  182. package/dist/server/prod-server.d.ts +39 -1
  183. package/dist/server/prod-server.js +107 -37
  184. package/dist/server/request-pipeline.d.ts +3 -15
  185. package/dist/server/request-pipeline.js +58 -47
  186. package/dist/server/rsc-stream-hints.d.ts +5 -1
  187. package/dist/server/rsc-stream-hints.js +6 -1
  188. package/dist/server/seed-cache.js +10 -18
  189. package/dist/shims/app-router-scroll-state.d.ts +3 -1
  190. package/dist/shims/app-router-scroll-state.js +14 -2
  191. package/dist/shims/app-router-scroll.d.ts +3 -0
  192. package/dist/shims/app-router-scroll.js +28 -18
  193. package/dist/shims/cache-runtime.js +12 -4
  194. package/dist/shims/cache.d.ts +1 -0
  195. package/dist/shims/cache.js +1 -1
  196. package/dist/shims/cdn-cache.d.ts +5 -5
  197. package/dist/shims/dynamic-preload-chunks.d.ts +8 -0
  198. package/dist/shims/dynamic-preload-chunks.js +79 -0
  199. package/dist/shims/dynamic.d.ts +4 -0
  200. package/dist/shims/dynamic.js +4 -2
  201. package/dist/shims/error-boundary.d.ts +6 -4
  202. package/dist/shims/error-boundary.js +7 -0
  203. package/dist/shims/error.js +38 -11
  204. package/dist/shims/error.react-server.d.ts +9 -0
  205. package/dist/shims/error.react-server.js +6 -0
  206. package/dist/shims/fetch-cache.d.ts +11 -1
  207. package/dist/shims/fetch-cache.js +55 -20
  208. package/dist/shims/hash-scroll.js +6 -1
  209. package/dist/shims/head.js +6 -1
  210. package/dist/shims/headers.d.ts +16 -2
  211. package/dist/shims/headers.js +66 -5
  212. package/dist/shims/image-config.js +7 -1
  213. package/dist/shims/internal/als-registry.js +28 -1
  214. package/dist/shims/internal/app-route-detection.d.ts +6 -3
  215. package/dist/shims/internal/app-route-detection.js +18 -23
  216. package/dist/shims/internal/app-router-context.d.ts +5 -0
  217. package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
  218. package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
  219. package/dist/shims/internal/navigation-untracked.d.ts +35 -0
  220. package/dist/shims/internal/navigation-untracked.js +55 -0
  221. package/dist/shims/internal/pages-data-target.d.ts +7 -2
  222. package/dist/shims/internal/pages-data-target.js +17 -8
  223. package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
  224. package/dist/shims/internal/pages-router-accessor.js +13 -0
  225. package/dist/shims/internal/router-context.d.ts +2 -1
  226. package/dist/shims/internal/router-context.js +3 -1
  227. package/dist/shims/link.js +12 -5
  228. package/dist/shims/metadata.d.ts +6 -2
  229. package/dist/shims/metadata.js +32 -14
  230. package/dist/shims/navigation.d.ts +14 -17
  231. package/dist/shims/navigation.js +93 -46
  232. package/dist/shims/ppr-fallback-shell.d.ts +5 -1
  233. package/dist/shims/ppr-fallback-shell.js +28 -7
  234. package/dist/shims/router.d.ts +13 -2
  235. package/dist/shims/router.js +434 -116
  236. package/dist/shims/script-nonce-context.d.ts +1 -1
  237. package/dist/shims/script-nonce-context.js +11 -3
  238. package/dist/shims/server.d.ts +33 -2
  239. package/dist/shims/server.js +75 -18
  240. package/dist/shims/slot.js +1 -1
  241. package/dist/shims/unified-request-context.js +2 -0
  242. package/dist/typegen.js +1 -0
  243. package/dist/utils/built-asset-url.d.ts +4 -0
  244. package/dist/utils/built-asset-url.js +11 -0
  245. package/dist/utils/client-build-manifest.js +15 -5
  246. package/dist/utils/client-runtime-metadata.d.ts +45 -0
  247. package/dist/utils/client-runtime-metadata.js +63 -0
  248. package/dist/utils/commonjs-loader.d.ts +16 -0
  249. package/dist/utils/commonjs-loader.js +100 -0
  250. package/dist/utils/deployment-id.d.ts +8 -0
  251. package/dist/utils/deployment-id.js +22 -0
  252. package/dist/utils/hash.d.ts +17 -1
  253. package/dist/utils/hash.js +36 -1
  254. package/dist/utils/html-limited-bots.d.ts +18 -1
  255. package/dist/utils/html-limited-bots.js +23 -1
  256. package/dist/utils/lazy-chunks.d.ts +27 -1
  257. package/dist/utils/lazy-chunks.js +65 -1
  258. package/dist/utils/manifest-paths.d.ts +20 -2
  259. package/dist/utils/manifest-paths.js +38 -3
  260. package/dist/utils/parse-cookie.d.ts +13 -0
  261. package/dist/utils/parse-cookie.js +52 -0
  262. package/dist/utils/path.d.ts +8 -1
  263. package/dist/utils/path.js +13 -1
  264. package/package.json +2 -2
  265. package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
  266. package/dist/shims/internal/parse-cookie-header.js +0 -30
@@ -1,11 +1,32 @@
1
- import { hasBasePath } from "../utils/base-path.js";
1
+ import { addBasePathToPathname, hasBasePath } from "../utils/base-path.js";
2
2
  import { applyMiddlewareRequestHeaders, isExternalUrl, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
3
- import { applyConfigHeadersToHeaderRecord, normalizeTrailingSlash } from "./request-pipeline.js";
3
+ import { applyConfigHeadersToHeaderRecord, cloneRequestWithUrl, normalizeTrailingSlash } from "./request-pipeline.js";
4
4
  import { mergeRewriteQuery } from "../utils/query.js";
5
5
  import { normalizeDefaultLocalePathname, stripI18nLocaleForApiRoute } from "./pages-i18n.js";
6
6
  import { mergeHeaders } from "./worker-utils.js";
7
7
  //#region src/server/pages-request-pipeline.ts
8
8
  /**
9
+ * Wrap an adapter's `runMiddleware` callback so middleware receives the original
10
+ * (pre-basePath-stripping) URL. Adapters strip the basePath before handing the
11
+ * request to `runPagesRequest`, but Next.js passes the un-stripped URL to the
12
+ * middleware adapter so `request.nextUrl.basePath` reflects whether the URL
13
+ * actually had the basePath prefix. Requests outside the basePath
14
+ * (`hadBasePath === false`) are passed through untouched so middleware sees
15
+ * `nextUrl.basePath === ""` and can redirect them into the basePath
16
+ * (see the middleware-base-path e2e test / #1830).
17
+ *
18
+ * Shared by the Node prod server (prod-server.ts) and the generated Pages
19
+ * Router worker entry (deploy.ts) to keep the two adapters in sync.
20
+ */
21
+ function wrapMiddlewareWithBasePath(runMiddleware, basePath, hadBasePath) {
22
+ if (!hadBasePath || !basePath) return runMiddleware;
23
+ return (request, ctx, opts) => {
24
+ const mwUrl = new URL(request.url);
25
+ mwUrl.pathname = addBasePathToPathname(mwUrl.pathname, basePath);
26
+ return runMiddleware(new Request(mwUrl, request), ctx, opts);
27
+ };
28
+ }
29
+ /**
9
30
  * Run the Pages Router request pipeline.
10
31
  *
11
32
  * ASSUMPTION: request already has internal headers filtered and basePath stripped.
@@ -47,7 +68,8 @@ async function runPagesRequest(request, deps) {
47
68
  };
48
69
  }
49
70
  }
50
- let resolvedUrl = pathname + search;
71
+ const originalResolvedUrl = pathname + search;
72
+ let resolvedUrl = originalResolvedUrl;
51
73
  const middlewareHeaders = {};
52
74
  let middlewareStatus;
53
75
  if (typeof deps.runMiddleware === "function") {
@@ -93,7 +115,12 @@ async function runPagesRequest(request, deps) {
93
115
  }
94
116
  const { postMwReqCtx, request: postMwReq } = applyMiddlewareRequestHeaders(middlewareHeaders, request, { preserveCredentialHeaders: isExternalUrl(resolvedUrl) });
95
117
  request = postMwReq;
96
- let resolvedPathname = resolvedUrl.split("?")[0];
118
+ const pathnameForResolvedUrl = (value) => value.split("#", 1)[0].split("?", 1)[0];
119
+ const rewriteRequestContext = () => ({
120
+ ...postMwReqCtx,
121
+ query: new URL(resolvedUrl, url).searchParams
122
+ });
123
+ let resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
97
124
  const matchResolvedPathname = (p) => i18nConfig ? normalizeDefaultLocalePathname(p, i18nConfig, { hostname: requestHostname }) : p;
98
125
  if (configHeaders.length) applyConfigHeadersToHeaderRecord(middlewareHeaders, {
99
126
  configHeaders,
@@ -109,15 +136,15 @@ async function runPagesRequest(request, deps) {
109
136
  if (await deps.serveStaticFile(pathname, middlewareHeaders)) return { type: "handled" };
110
137
  }
111
138
  let configRewriteFired = false;
112
- if (configRewrites.beforeFiles?.length) {
113
- const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname), configRewrites.beforeFiles, postMwReqCtx, basePathState);
139
+ for (const rewrite of configRewrites.beforeFiles ?? []) {
140
+ const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
114
141
  if (rewritten) {
115
142
  if (isExternalUrl(rewritten)) return {
116
143
  type: "response",
117
144
  response: await proxyExternal(request, rewritten)
118
145
  };
119
146
  resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
120
- resolvedPathname = resolvedUrl.split("?")[0];
147
+ resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
121
148
  configRewriteFired = true;
122
149
  }
123
150
  }
@@ -130,34 +157,61 @@ async function runPagesRequest(request, deps) {
130
157
  };
131
158
  const apiLookupUrl = stripI18nLocaleForApiRoute(resolvedUrl, i18nConfig);
132
159
  const apiLookupPathname = apiLookupUrl.split("?")[0];
133
- if (apiLookupPathname.startsWith("/api/") || apiLookupPathname === "/api") if (typeof deps.handleApi === "function") return {
134
- type: "response",
135
- defaultContentType: "application/octet-stream",
136
- response: mergeHeaders(await deps.handleApi(request, apiLookupUrl, deps.ctx ?? null), middlewareHeaders, middlewareStatus)
137
- };
138
- else return {
160
+ if (apiLookupPathname.startsWith("/api/") || apiLookupPathname === "/api") if (typeof deps.handleApi === "function") {
161
+ let apiRequest = request;
162
+ if (basePath && hadBasePath) {
163
+ const apiRequestUrl = new URL(request.url);
164
+ apiRequestUrl.pathname = addBasePathToPathname(apiRequestUrl.pathname, basePath);
165
+ apiRequest = cloneRequestWithUrl(request, apiRequestUrl.toString());
166
+ }
167
+ return {
168
+ type: "response",
169
+ defaultContentType: "application/octet-stream",
170
+ response: mergeHeaders(await deps.handleApi(apiRequest, apiLookupUrl, deps.ctx ?? null), middlewareHeaders, middlewareStatus)
171
+ };
172
+ } else return {
139
173
  type: "api",
140
174
  apiUrl: apiLookupUrl,
141
175
  stagedHeaders: middlewareHeaders,
142
176
  requestHeaders: request.headers,
143
177
  middlewareStatus
144
178
  };
145
- const pageMatch = deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null;
179
+ let pageMatch = deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null;
146
180
  let resolvedPathnameChanged = false;
147
- if ((!pageMatch || pageMatch.route.isDynamic) && configRewrites.afterFiles?.length) {
148
- const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname), configRewrites.afterFiles, postMwReqCtx, basePathState);
181
+ if (!pageMatch || pageMatch.route.isDynamic) for (const rewrite of configRewrites.afterFiles ?? []) {
182
+ const rewritten = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
149
183
  if (rewritten) {
150
184
  if (isExternalUrl(rewritten)) return {
151
185
  type: "response",
152
186
  response: await proxyExternal(request, rewritten)
153
187
  };
154
188
  resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
155
- resolvedPathname = resolvedUrl.split("?")[0];
189
+ resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
156
190
  resolvedPathnameChanged = true;
191
+ pageMatch = deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null;
192
+ if (pageMatch) break;
157
193
  }
158
194
  }
195
+ const refreshDataRewriteHeader = () => {
196
+ if ((isDataReq || isDataRequest) && resolvedUrl !== originalResolvedUrl && !isExternalUrl(resolvedUrl)) middlewareHeaders["x-nextjs-rewrite"] = resolvedUrl;
197
+ else delete middlewareHeaders["x-nextjs-rewrite"];
198
+ };
199
+ refreshDataRewriteHeader();
159
200
  if (typeof deps.renderPage === "function") {
160
- const renderPageMatch = resolvedPathnameChanged ? deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null : pageMatch;
201
+ let renderPageMatch = pageMatch;
202
+ if ((isDataReq || isDataRequest) && !renderPageMatch && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
203
+ const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
204
+ if (!fallbackRewrite) continue;
205
+ if (isExternalUrl(fallbackRewrite)) return {
206
+ type: "response",
207
+ response: await proxyExternal(request, fallbackRewrite)
208
+ };
209
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
210
+ resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
211
+ renderPageMatch = deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null;
212
+ refreshDataRewriteHeader();
213
+ if (renderPageMatch) break;
214
+ }
161
215
  const shouldDeferErrorPageOnMiss = !isDataReq && !isDataRequest && !!deps.matchPageRoute && !renderPageMatch;
162
216
  const initialRenderOptions = shouldDeferErrorPageOnMiss ? { renderErrorPageOnMiss: false } : isDataReq ? { isDataReq: true } : void 0;
163
217
  const stagedHeaders = new Headers();
@@ -165,16 +219,18 @@ async function runPagesRequest(request, deps) {
165
219
  else stagedHeaders.set(k, v);
166
220
  let response = await deps.renderPage(request, resolvedUrl, initialRenderOptions, stagedHeaders);
167
221
  let matchedFallbackRewrite = false;
168
- if (response.status === 404 && shouldDeferErrorPageOnMiss && configRewrites.fallback?.length) {
169
- const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), configRewrites.fallback, postMwReqCtx, basePathState);
170
- if (fallbackRewrite) {
171
- if (isExternalUrl(fallbackRewrite)) return {
172
- type: "response",
173
- response: await proxyExternal(request, fallbackRewrite)
174
- };
175
- response = await deps.renderPage(request, mergeRewriteQuery(resolvedUrl, fallbackRewrite), void 0, stagedHeaders);
176
- matchedFallbackRewrite = true;
177
- }
222
+ if (response.status === 404 && shouldDeferErrorPageOnMiss && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
223
+ const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
224
+ if (!fallbackRewrite) continue;
225
+ if (isExternalUrl(fallbackRewrite)) return {
226
+ type: "response",
227
+ response: await proxyExternal(request, fallbackRewrite)
228
+ };
229
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
230
+ resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
231
+ response = await deps.renderPage(request, resolvedUrl, void 0, stagedHeaders);
232
+ matchedFallbackRewrite = true;
233
+ if (response.status !== 404) break;
178
234
  }
179
235
  if (response.status === 404 && shouldDeferErrorPageOnMiss && !matchedFallbackRewrite) response = await deps.renderPage(request, resolvedUrl, void 0, stagedHeaders);
180
236
  const merged = mergeHeaders(response, middlewareHeaders, middlewareStatus);
@@ -185,16 +241,18 @@ async function runPagesRequest(request, deps) {
185
241
  defaultContentType: "text/html"
186
242
  };
187
243
  }
188
- if (!(resolvedPathnameChanged ? deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null : pageMatch) && configRewrites.fallback?.length) {
189
- const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), configRewrites.fallback, postMwReqCtx, basePathState);
190
- if (fallbackRewrite) {
191
- if (isExternalUrl(fallbackRewrite)) return {
192
- type: "response",
193
- response: await proxyExternal(request, fallbackRewrite)
194
- };
195
- resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
196
- }
244
+ if (!(resolvedPathnameChanged ? deps.matchPageRoute ? deps.matchPageRoute(resolvedPathname, request) : null : pageMatch) && configRewrites.fallback?.length) for (const rewrite of configRewrites.fallback) {
245
+ const fallbackRewrite = matchRewrite(matchResolvedPathname(resolvedPathname), [rewrite], rewriteRequestContext(), basePathState);
246
+ if (!fallbackRewrite) continue;
247
+ if (isExternalUrl(fallbackRewrite)) return {
248
+ type: "response",
249
+ response: await proxyExternal(request, fallbackRewrite)
250
+ };
251
+ resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
252
+ resolvedPathname = pathnameForResolvedUrl(resolvedUrl);
253
+ if (deps.matchPageRoute?.(resolvedPathname, request)) break;
197
254
  }
255
+ refreshDataRewriteHeader();
198
256
  return {
199
257
  type: "render",
200
258
  resolvedUrl,
@@ -206,4 +264,4 @@ async function runPagesRequest(request, deps) {
206
264
  };
207
265
  }
208
266
  //#endregion
209
- export { runPagesRequest };
267
+ export { runPagesRequest, wrapMiddlewareWithBasePath };
@@ -4,28 +4,12 @@ declare global {
4
4
  }
5
5
  declare function normalizePregeneratedPathname(pathname: string): string;
6
6
  declare function clearPregeneratedConcretePaths(): void;
7
- /**
8
- * Records a concrete URL path for a route pattern. The pathname is normalized
9
- * here so this is the single source of truth: every caller — the Worker global
10
- * table and the Node `seed-cache.ts` path — stores the canonical form that
11
- * matches the runtime `cleanPathname` lookup without having to pre-normalize.
12
- */
13
7
  declare function addPregeneratedConcretePath(routePattern: string, pathname: string): void;
14
- /**
15
- * Returns the live backing `Set` for a route pattern (not a copy) to keep
16
- * lookups allocation-free on the serving hot path. The `ReadonlySet` type
17
- * forbids mutation at compile time. Callers must treat the result as
18
- * point-in-time and must NOT retain it across a re-seed: each
19
- * `initPregeneratedPathsFromGlobals` call runs `clearPregeneratedConcretePaths`,
20
- * which empties the map, leaving any previously-returned reference stale. Read
21
- * it, use it, drop it — never cache the reference.
22
- */
23
8
  declare function getRenderedConcreteUrlPathsForRoute(routePattern: string): ReadonlySet<string> | undefined;
24
9
  /**
25
10
  * Populate the registry from `globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS`.
26
11
  * No-op when the global is not set (Node path — seed-cache handles it later).
27
- * `addPregeneratedConcretePath` normalizes each pathname so it matches the
28
- * runtime `cleanPathname`.
12
+ * Pathnames are normalised so they match the runtime `cleanPathname`.
29
13
  */
30
14
  declare function initPregeneratedPathsFromGlobals(): void;
31
15
  //#endregion
@@ -16,38 +16,21 @@ const concreteUrlPathsByRoute = /* @__PURE__ */ new Map();
16
16
  function clearPregeneratedConcretePaths() {
17
17
  concreteUrlPathsByRoute.clear();
18
18
  }
19
- /**
20
- * Records a concrete URL path for a route pattern. The pathname is normalized
21
- * here so this is the single source of truth: every caller — the Worker global
22
- * table and the Node `seed-cache.ts` path — stores the canonical form that
23
- * matches the runtime `cleanPathname` lookup without having to pre-normalize.
24
- */
25
19
  function addPregeneratedConcretePath(routePattern, pathname) {
26
- const normalized = normalizePregeneratedPathname(pathname);
27
20
  let paths = concreteUrlPathsByRoute.get(routePattern);
28
21
  if (!paths) {
29
22
  paths = /* @__PURE__ */ new Set();
30
23
  concreteUrlPathsByRoute.set(routePattern, paths);
31
24
  }
32
- paths.add(normalized);
25
+ paths.add(normalizePregeneratedPathname(pathname));
33
26
  }
34
- /**
35
- * Returns the live backing `Set` for a route pattern (not a copy) to keep
36
- * lookups allocation-free on the serving hot path. The `ReadonlySet` type
37
- * forbids mutation at compile time. Callers must treat the result as
38
- * point-in-time and must NOT retain it across a re-seed: each
39
- * `initPregeneratedPathsFromGlobals` call runs `clearPregeneratedConcretePaths`,
40
- * which empties the map, leaving any previously-returned reference stale. Read
41
- * it, use it, drop it — never cache the reference.
42
- */
43
27
  function getRenderedConcreteUrlPathsForRoute(routePattern) {
44
28
  return concreteUrlPathsByRoute.get(routePattern);
45
29
  }
46
30
  /**
47
31
  * Populate the registry from `globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS`.
48
32
  * No-op when the global is not set (Node path — seed-cache handles it later).
49
- * `addPregeneratedConcretePath` normalizes each pathname so it matches the
50
- * runtime `cleanPathname`.
33
+ * Pathnames are normalised so they match the runtime `cleanPathname`.
51
34
  */
52
35
  function initPregeneratedPathsFromGlobals() {
53
36
  const raw = globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS;
@@ -0,0 +1,33 @@
1
+ //#region src/server/prerender-manifest.d.ts
2
+ type PrerenderManifestRoute = {
3
+ route: string;
4
+ status?: string;
5
+ revalidate?: number | false;
6
+ expire?: number;
7
+ path?: string;
8
+ router?: string;
9
+ fallback?: boolean;
10
+ };
11
+ type PrerenderManifest = {
12
+ buildId?: string;
13
+ trailingSlash?: boolean;
14
+ routes?: PrerenderManifestRoute[];
15
+ };
16
+ declare function readPrerenderManifest(manifestPath: string): PrerenderManifest | null;
17
+ declare function getRenderedAppRoutes(routes: PrerenderManifestRoute[]): PrerenderManifestRoute[];
18
+ /**
19
+ * Returns true when `pathname` contains bracket-delimited route params,
20
+ * indicating it is a fallback-shell placeholder (e.g. `/en/blog/[slug]`)
21
+ * rather than a concrete rendered URL.
22
+ */
23
+ declare function isFallbackShellArtifactPath(pathname: string, route?: PrerenderManifestRoute): boolean;
24
+ /**
25
+ * Build the pregenerated concrete-path payload table from a prerender manifest.
26
+ *
27
+ * Filters out fallback-shell placeholder paths and groups remaining concrete
28
+ * paths by route pattern. Returns an empty array when the manifest has no
29
+ * rendered App routes or all routes are fallback-shell artifacts.
30
+ */
31
+ declare function buildPregeneratedConcretePathTable(manifest: PrerenderManifest): Array<[string, string[]]>;
32
+ //#endregion
33
+ export { buildPregeneratedConcretePathTable, getRenderedAppRoutes, isFallbackShellArtifactPath, readPrerenderManifest };
@@ -0,0 +1,54 @@
1
+ import fs from "node:fs";
2
+ //#region src/server/prerender-manifest.ts
3
+ function readPrerenderManifest(manifestPath) {
4
+ if (!fs.existsSync(manifestPath)) return null;
5
+ try {
6
+ return JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
7
+ } catch (error) {
8
+ console.warn(`[vinext] Failed to read prerender manifest at ${manifestPath}:`, error);
9
+ return null;
10
+ }
11
+ }
12
+ function getRenderedAppRoutes(routes) {
13
+ return routes.filter((r) => r.status === "rendered" && r.router === "app");
14
+ }
15
+ function groupRoutesByPattern(routes) {
16
+ const byPattern = /* @__PURE__ */ new Map();
17
+ for (const r of routes) {
18
+ const pathname = r.path ?? r.route;
19
+ const existing = byPattern.get(r.route);
20
+ if (existing) existing.push(pathname);
21
+ else byPattern.set(r.route, [pathname]);
22
+ }
23
+ return byPattern;
24
+ }
25
+ /**
26
+ * Returns true when `pathname` contains bracket-delimited route params,
27
+ * indicating it is a fallback-shell placeholder (e.g. `/en/blog/[slug]`)
28
+ * rather than a concrete rendered URL.
29
+ */
30
+ function isFallbackShellArtifactPath(pathname, route) {
31
+ if (route?.fallback === true) return true;
32
+ if (route?.fallback === void 0) {
33
+ if (process.env.NODE_ENV !== "production") console.warn("[vinext] Legacy manifest detected: missing `fallback` flag for route. Using bracket heuristic for fallback-shell detection. A concrete URL containing literal brackets may be misclassified as a fallback shell.");
34
+ return pathname.includes("[") || pathname.includes("]");
35
+ }
36
+ return false;
37
+ }
38
+ /**
39
+ * Build the pregenerated concrete-path payload table from a prerender manifest.
40
+ *
41
+ * Filters out fallback-shell placeholder paths and groups remaining concrete
42
+ * paths by route pattern. Returns an empty array when the manifest has no
43
+ * rendered App routes or all routes are fallback-shell artifacts.
44
+ */
45
+ function buildPregeneratedConcretePathTable(manifest) {
46
+ const routes = manifest?.routes;
47
+ if (!routes?.length) return [];
48
+ const concreteRoutes = getRenderedAppRoutes(routes).filter((r) => {
49
+ return !isFallbackShellArtifactPath(r.path ?? r.route, r);
50
+ });
51
+ return Array.from(groupRoutesByPattern(concreteRoutes).entries());
52
+ }
53
+ //#endregion
54
+ export { buildPregeneratedConcretePathTable, getRenderedAppRoutes, isFallbackShellArtifactPath, readPrerenderManifest };
@@ -5,7 +5,6 @@ type PrerenderRouteParamsPayload = {
5
5
  params: PrerenderRouteParams;
6
6
  routePattern: string;
7
7
  };
8
- /** @public exported for #1716 serving consumers; not yet referenced in-repo */
9
8
  type PrerenderRouteParamsRouteMatch = {
10
9
  kind: "exact";
11
10
  params: PrerenderRouteParams;
@@ -21,4 +20,4 @@ declare function prerenderRouteParamsPayloadMatchesRoute(payload: PrerenderRoute
21
20
  declare function matchPrerenderRouteParamsPayload(payload: PrerenderRouteParamsPayload | null, routePattern: string, params: PrerenderRouteParams): PrerenderRouteParamsRouteMatch | null;
22
21
  declare function encodePrerenderRouteParams(pattern: string, params: PrerenderRouteParams, fallbackParamNames?: readonly string[]): PrerenderRouteParamsPayload | null;
23
22
  //#endregion
24
- export { PrerenderRouteParams, PrerenderRouteParamsPayload, PrerenderRouteParamsRouteMatch, encodePrerenderRouteParams, matchPrerenderRouteParamsPayload, prerenderRouteParamsPayloadMatchesRoute, readTrustedPrerenderRouteParams, readTrustedPrerenderRouteParamsFromHeaders, serializePrerenderRouteParamsHeader };
23
+ export { PrerenderRouteParams, PrerenderRouteParamsPayload, encodePrerenderRouteParams, matchPrerenderRouteParamsPayload, prerenderRouteParamsPayloadMatchesRoute, readTrustedPrerenderRouteParams, readTrustedPrerenderRouteParamsFromHeaders, serializePrerenderRouteParamsHeader };
@@ -3,6 +3,44 @@ import { resolveRequestHost, trustProxy, trustedHosts } from "./proxy-trust.js";
3
3
  import { IncomingMessage, ServerResponse } from "node:http";
4
4
 
5
5
  //#region src/server/prod-server.d.ts
6
+ /**
7
+ * Import a built server entry module (App Router RSC entry or Pages Router
8
+ * server entry) by absolute file path.
9
+ *
10
+ * The first import of a given path uses the plain file:// URL with NO query
11
+ * string. This is load-bearing: code-split builds emit lazy chunks that
12
+ * import the entry back by bare specifier (default Vite builds on both
13
+ * supported majors — Rollup on Vite 7 and Rolldown on Vite 8 — hoist modules
14
+ * shared between the entry's static graph and lazy route chunks into the
15
+ * entry chunk, which the chunks then import as e.g. "../../index.js").
16
+ * Node keys its ESM cache on the full URL including the query string, so if
17
+ * the server imported the entry as `index.js?t=<mtime>`, a chunk's bare
18
+ * back-import would evaluate the entire server bundle a second time and
19
+ * module-level singletons (db pools, service registries) would silently
20
+ * diverge between the two copies. See
21
+ * https://github.com/cloudflare/vinext/issues/1923.
22
+ *
23
+ * A `?t=<mtime>` query string is appended only when the same path is
24
+ * imported again after a rebuild (different mtime) — e.g. test suites that
25
+ * rebuild a fixture to the same output path within one process — where the
26
+ * bare URL's cache entry would return the stale previous build. Note this
27
+ * rebuild branch trades the single-instance guarantee back: chunks that
28
+ * import the entry by bare path still resolve to the FIRST build's cache
29
+ * entry, so freshness and single-instance only hold together on the first
30
+ * import of a path. Production processes import each entry path exactly
31
+ * once and always get both.
32
+ *
33
+ * The entry is imported via its canonical real path: the bundler
34
+ * canonicalizes module ids with fs.realpathSync.native, so chunks evaluate
35
+ * under realpath-based URLs and their relative imports resolve to realpath
36
+ * URLs too. Importing the entry through a symlinked path (macOS /var/...
37
+ * tmpdirs, symlinked deploy directories) would otherwise create a second
38
+ * instance keyed on the symlinked URL.
39
+ *
40
+ * Exported for direct unit testing of the URL choice.
41
+ */
42
+ declare function resolveServerEntryImportUrl(entryPath: string): string;
43
+ declare function importServerEntryModule(entryPath: string): Promise<any>;
6
44
  type ProdServerOptions = {
7
45
  /** Port to listen on */port?: number; /** Host to bind to */
8
46
  host?: string; /** Path to the build output directory */
@@ -105,4 +143,4 @@ declare function resolveAppRouterPrerenderSeeder(entryModule: unknown): AppRoute
105
143
  */
106
144
  declare function resolveAppRouterAssetPath(pathname: string, assetPathPrefix: string, assetPrefix: string): string | null;
107
145
  //#endregion
108
- export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, ProdServerOptions, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic };
146
+ export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, ProdServerOptions, importServerEntryModule, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, resolveServerEntryImportUrl, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic };