vinext 1.2.0 → 1.3.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 (283) hide show
  1. package/README.md +13 -10
  2. package/dist/build/client-build-config.d.ts +64 -3
  3. package/dist/build/client-build-config.js +131 -4
  4. package/dist/build/client-reference-groups.d.ts +163 -0
  5. package/dist/build/client-reference-groups.js +534 -0
  6. package/dist/build/module-dependency-cache.d.ts +31 -0
  7. package/dist/build/module-dependency-cache.js +51 -1
  8. package/dist/build/next-client-runtime-manifests.d.ts +10 -1
  9. package/dist/build/next-client-runtime-manifests.js +19 -4
  10. package/dist/build/nitro-public-files.d.ts +24 -0
  11. package/dist/build/nitro-public-files.js +60 -0
  12. package/dist/build/output-root-externals.d.ts +21 -0
  13. package/dist/build/output-root-externals.js +40 -0
  14. package/dist/build/pages-client-assets-module.js +1 -1
  15. package/dist/build/prerender-paths.js +6 -3
  16. package/dist/build/prerender.js +1 -1
  17. package/dist/build/server-actions-encryption-key.d.ts +23 -0
  18. package/dist/build/server-actions-encryption-key.js +101 -0
  19. package/dist/build/ssr-manifest.d.ts +3 -0
  20. package/dist/build/ssr-manifest.js +10 -1
  21. package/dist/check.js +5 -6
  22. package/dist/cli-dev-config.js +3 -3
  23. package/dist/cli.js +1 -1
  24. package/dist/client/client-rewrite-params.d.ts +9 -0
  25. package/dist/client/client-rewrite-params.js +20 -0
  26. package/dist/client/dev-error-overlay.js +2 -1
  27. package/dist/client/navigation-runtime.d.ts +25 -2
  28. package/dist/client/navigation-runtime.js +42 -11
  29. package/dist/client/vinext-next-data.d.ts +0 -1
  30. package/dist/config/config-matchers.d.ts +15 -40
  31. package/dist/config/config-matchers.js +195 -262
  32. package/dist/config/config-source.d.ts +34 -0
  33. package/dist/config/config-source.js +141 -0
  34. package/dist/config/header-params.d.ts +29 -0
  35. package/dist/config/header-params.js +106 -0
  36. package/dist/config/next-config.d.ts +7 -5
  37. package/dist/config/next-config.js +120 -7
  38. package/dist/entries/app-browser-entry.d.ts +14 -1
  39. package/dist/entries/app-browser-entry.js +26 -36
  40. package/dist/entries/app-rsc-entry.d.ts +2 -0
  41. package/dist/entries/app-rsc-entry.js +92 -57
  42. package/dist/entries/app-rsc-manifest.d.ts +10 -0
  43. package/dist/entries/app-rsc-manifest.js +20 -1
  44. package/dist/entries/app-ssr-entry.d.ts +4 -1
  45. package/dist/entries/app-ssr-entry.js +9 -2
  46. package/dist/entries/pages-client-entry.d.ts +1 -0
  47. package/dist/entries/pages-client-entry.js +6 -6
  48. package/dist/entries/pages-server-entry.js +17 -14
  49. package/dist/index.d.ts +11 -0
  50. package/dist/index.js +350 -175
  51. package/dist/init.d.ts +1 -1
  52. package/dist/init.js +103 -6
  53. package/dist/plugins/ast-utils.d.ts +53 -2
  54. package/dist/plugins/ast-utils.js +90 -2
  55. package/dist/plugins/cloudflare-dev-module-urls.d.ts +41 -0
  56. package/dist/plugins/cloudflare-dev-module-urls.js +271 -0
  57. package/dist/plugins/commonjs-esm-facade.js +2 -2
  58. package/dist/plugins/css-module-imports.js +13 -20
  59. package/dist/plugins/dynamic-preload-metadata.js +2 -3
  60. package/dist/plugins/extensionless-dynamic-import.js +2 -3
  61. package/dist/plugins/fonts.d.ts +1 -1
  62. package/dist/plugins/fonts.js +3 -3
  63. package/dist/plugins/ignore-dynamic-requests.js +2 -3
  64. package/dist/plugins/import-meta-url.js +3 -4
  65. package/dist/plugins/instrumentation-client.js +3 -2
  66. package/dist/plugins/middleware-export-validation.js +2 -3
  67. package/dist/plugins/og-harfbuzz.js +2 -3
  68. package/dist/plugins/optimize-imports.d.ts +25 -2
  69. package/dist/plugins/optimize-imports.js +109 -24
  70. package/dist/plugins/pages-node-externals.js +2 -3
  71. package/dist/plugins/remove-console.js +2 -18
  72. package/dist/plugins/require-condition-resolution.js +3 -3
  73. package/dist/plugins/require-context.js +2 -3
  74. package/dist/plugins/rsc-client-reference-loaders.d.ts +45 -1
  75. package/dist/plugins/rsc-client-reference-loaders.js +336 -18
  76. package/dist/plugins/strip-server-exports.js +3 -4
  77. package/dist/plugins/styled-jsx.js +2 -3
  78. package/dist/plugins/use-cache-callable.d.ts +26 -2
  79. package/dist/plugins/use-cache-callable.js +101 -36
  80. package/dist/plugins/worker-image-imports.d.ts +1 -0
  81. package/dist/plugins/worker-image-imports.js +31 -34
  82. package/dist/plugins/worker-use-server.js +38 -14
  83. package/dist/routing/app-route-graph.d.ts +1 -1
  84. package/dist/routing/browser-route-manifest.d.ts +43 -0
  85. package/dist/routing/browser-route-manifest.js +195 -0
  86. package/dist/routing/hashed-route-patterns.d.ts +4 -0
  87. package/dist/routing/hashed-route-patterns.js +22 -0
  88. package/dist/routing/optimistic-route-trie.d.ts +27 -0
  89. package/dist/routing/optimistic-route-trie.js +102 -0
  90. package/dist/routing/route-validation.d.ts +6 -1
  91. package/dist/routing/route-validation.js +26 -10
  92. package/dist/server/api-handler.js +1 -1
  93. package/dist/server/app-action-forwarding.d.ts +8 -0
  94. package/dist/server/app-action-forwarding.js +17 -3
  95. package/dist/server/app-browser-entry.js +149 -62
  96. package/dist/server/app-browser-error.d.ts +3 -1
  97. package/dist/server/app-browser-error.js +7 -2
  98. package/dist/server/app-browser-interception-context.d.ts +2 -2
  99. package/dist/server/app-browser-interception-context.js +1 -1
  100. package/dist/server/app-browser-mpa-navigation.d.ts +1 -0
  101. package/dist/server/app-browser-mpa-navigation.js +6 -5
  102. package/dist/server/app-browser-navigation-controller.d.ts +17 -6
  103. package/dist/server/app-browser-navigation-controller.js +88 -26
  104. package/dist/server/app-browser-prefetch-response.js +2 -2
  105. package/dist/server/app-browser-state.d.ts +2 -2
  106. package/dist/server/app-browser-state.js +1 -1
  107. package/dist/server/app-browser-supplemental-refresh.js +1 -1
  108. package/dist/server/app-browser-visible-commit.d.ts +4 -4
  109. package/dist/server/app-client-reference-preloader.d.ts +23 -0
  110. package/dist/server/app-client-reference-preloader.js +30 -7
  111. package/dist/server/app-fallback-renderer.js +2 -1
  112. package/dist/server/app-middleware.d.ts +6 -0
  113. package/dist/server/app-middleware.js +8 -10
  114. package/dist/server/app-optimistic-routing.d.ts +8 -10
  115. package/dist/server/app-optimistic-routing.js +4 -95
  116. package/dist/server/app-page-boundary-render.js +8 -1
  117. package/dist/server/app-page-cache-render.js +1 -0
  118. package/dist/server/app-page-dispatch.js +3 -1
  119. package/dist/server/app-page-render.js +4 -2
  120. package/dist/server/app-page-rsc-render-status.d.ts +1 -0
  121. package/dist/server/app-page-rsc-render-status.js +1 -0
  122. package/dist/server/app-page-search-params-observation.d.ts +1 -4
  123. package/dist/server/app-page-search-params-observation.js +8 -10
  124. package/dist/server/app-page-stream.d.ts +7 -0
  125. package/dist/server/app-page-stream.js +1 -0
  126. package/dist/server/app-pages-bridge.d.ts +2 -1
  127. package/dist/server/app-pages-bridge.js +12 -8
  128. package/dist/server/app-prerender-endpoints.js +1 -1
  129. package/dist/server/app-prerender-static-params.js +3 -2
  130. package/dist/server/app-render-abort-error.d.ts +19 -0
  131. package/dist/server/app-render-abort-error.js +31 -1
  132. package/dist/server/app-render-dependency.js +42 -2
  133. package/dist/server/app-request-stage-independent-entry.js +7 -7
  134. package/dist/server/app-response-stage-entry.js +5 -5
  135. package/dist/server/app-route-handler-dispatch.js +3 -1
  136. package/dist/server/app-route-handler-execution.d.ts +2 -0
  137. package/dist/server/app-route-handler-execution.js +9 -2
  138. package/dist/server/app-route-handler-middleware-context.d.ts +2 -1
  139. package/dist/server/app-route-handler-middleware-context.js +3 -3
  140. package/dist/server/app-route-handler-response.d.ts +2 -1
  141. package/dist/server/app-route-handler-response.js +2 -2
  142. package/dist/server/app-route-handler-runtime.d.ts +2 -0
  143. package/dist/server/app-route-handler-runtime.js +21 -4
  144. package/dist/server/app-route-module-loader.js +7 -6
  145. package/dist/server/app-route-tree.d.ts +20 -0
  146. package/dist/server/app-route-tree.js +18 -0
  147. package/dist/server/app-router-entry.js +7 -7
  148. package/dist/server/app-rsc-cache-busting.d.ts +16 -0
  149. package/dist/server/app-rsc-cache-busting.js +29 -12
  150. package/dist/server/app-rsc-combined-handler.js +8 -1
  151. package/dist/server/app-rsc-errors.d.ts +7 -0
  152. package/dist/server/app-rsc-errors.js +9 -2
  153. package/dist/server/app-rsc-handler.d.ts +4 -1
  154. package/dist/server/app-rsc-handler.js +151 -135
  155. package/dist/server/app-rsc-request-normalization.js +3 -3
  156. package/dist/server/app-rsc-response-finalizer.d.ts +5 -0
  157. package/dist/server/app-rsc-response-finalizer.js +4 -1
  158. package/dist/server/app-rsc-response-stage.js +5 -3
  159. package/dist/server/app-rsc-route-matching.d.ts +1 -0
  160. package/dist/server/app-rsc-route-matching.js +1 -1
  161. package/dist/server/app-server-action-execution.d.ts +23 -6
  162. package/dist/server/app-server-action-execution.js +51 -57
  163. package/dist/server/app-ssr-entry.d.ts +6 -0
  164. package/dist/server/app-ssr-entry.js +21 -11
  165. package/dist/server/app-ssr-stream.d.ts +7 -0
  166. package/dist/server/app-ssr-stream.js +13 -1
  167. package/dist/server/app-visited-response-cache.js +2 -2
  168. package/dist/server/config-headers.js +13 -4
  169. package/dist/server/defer-until-stream-consumed.d.ts +2 -1
  170. package/dist/server/defer-until-stream-consumed.js +3 -1
  171. package/dist/server/dev-server.js +1 -1
  172. package/dist/server/image-optimization.js +1 -0
  173. package/dist/server/isolate-shared-promise.d.ts +10 -0
  174. package/dist/server/isolate-shared-promise.js +33 -0
  175. package/dist/server/isr-cache.js +3 -2
  176. package/dist/server/metadata-route-response.js +2 -2
  177. package/dist/server/middleware-matcher-pattern.d.ts +0 -1
  178. package/dist/server/middleware-matcher-pattern.js +11 -140
  179. package/dist/server/middleware-matcher.js +5 -6
  180. package/dist/server/middleware-response-headers.d.ts +31 -0
  181. package/dist/server/middleware-response-headers.js +57 -1
  182. package/dist/server/middleware-runtime.js +30 -17
  183. package/dist/server/navigation-planner.d.ts +2 -2
  184. package/dist/server/navigation-planner.js +1 -1
  185. package/dist/server/nitro-public-files-plugin.d.ts +38 -0
  186. package/dist/server/nitro-public-files-plugin.js +106 -0
  187. package/dist/server/nitro-public-files.d.ts +21 -0
  188. package/dist/server/nitro-public-files.js +39 -0
  189. package/dist/server/open-redirect.d.ts +11 -4
  190. package/dist/server/open-redirect.js +11 -4
  191. package/dist/server/pages-api-route.js +2 -2
  192. package/dist/server/pages-asset-tags.d.ts +5 -0
  193. package/dist/server/pages-asset-tags.js +9 -2
  194. package/dist/server/pages-client-assets.d.ts +4 -1
  195. package/dist/server/pages-data-route.js +2 -1
  196. package/dist/server/pages-i18n.d.ts +18 -0
  197. package/dist/server/pages-i18n.js +18 -2
  198. package/dist/server/pages-node-compat.d.ts +5 -3
  199. package/dist/server/pages-node-compat.js +35 -16
  200. package/dist/server/pages-page-data.js +1 -1
  201. package/dist/server/pages-page-handler.js +1 -1
  202. package/dist/server/pages-page-response.js +1 -1
  203. package/dist/server/pages-request-pipeline.d.ts +6 -1
  204. package/dist/server/pages-request-pipeline.js +35 -39
  205. package/dist/server/pages-request-stage-entry.js +20 -10
  206. package/dist/server/pages-response-stage-entry.js +1 -1
  207. package/dist/server/pages-revalidate.js +3 -2
  208. package/dist/server/pages-router-entry.js +2 -2
  209. package/dist/server/prod-server.d.ts +2 -2
  210. package/dist/server/prod-server.js +74 -36
  211. package/dist/server/proxy-trust.d.ts +6 -0
  212. package/dist/server/proxy-trust.js +12 -6
  213. package/dist/server/request-pipeline.d.ts +5 -0
  214. package/dist/server/request-pipeline.js +12 -1
  215. package/dist/server/rsc-stream-hints.d.ts +1 -1
  216. package/dist/server/rsc-stream-hints.js +21 -3
  217. package/dist/server/server-reference-loader.js +10 -1
  218. package/dist/server/static-file-cache.js +15 -3
  219. package/dist/server/worker-image-optimization.js +19 -6
  220. package/dist/server/worker-utils.js +1 -1
  221. package/dist/shims/cache-handler.js +3 -2
  222. package/dist/shims/cache-request-state.d.ts +40 -3
  223. package/dist/shims/cache-request-state.js +70 -5
  224. package/dist/shims/cache-runtime.js +47 -19
  225. package/dist/shims/cache.d.ts +2 -2
  226. package/dist/shims/cache.js +17 -8
  227. package/dist/shims/cdn-purge-routes.d.ts +24 -0
  228. package/dist/shims/cdn-purge-routes.js +77 -0
  229. package/dist/shims/dynamic.js +17 -4
  230. package/dist/shims/form.js +8 -3
  231. package/dist/shims/head.js +1 -1
  232. package/dist/shims/headers.js +2 -2
  233. package/dist/shims/image-props.d.ts +93 -0
  234. package/dist/shims/image-props.js +323 -0
  235. package/dist/shims/image.d.ts +4 -18
  236. package/dist/shims/image.js +4 -319
  237. package/dist/shims/internal/headers-state.d.ts +7 -0
  238. package/dist/shims/internal/headers-state.js +14 -2
  239. package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +4 -1
  240. package/dist/shims/internal/hybrid-client-route-owner-direct.js +32 -15
  241. package/dist/shims/internal/hybrid-client-route-owner.js +9 -8
  242. package/dist/shims/link-prefetch.js +5 -4
  243. package/dist/shims/link.js +7 -5
  244. package/dist/shims/navigation.d.ts +1 -1
  245. package/dist/shims/navigation.js +21 -10
  246. package/dist/shims/og.js +35 -10
  247. package/dist/shims/request-context.d.ts +13 -0
  248. package/dist/shims/router.js +28 -52
  249. package/dist/shims/server.d.ts +42 -8
  250. package/dist/shims/server.js +99 -15
  251. package/dist/shims/thenable-params.d.ts +6 -1
  252. package/dist/shims/thenable-params.js +11 -2
  253. package/dist/shims/unified-request-context.d.ts +5 -0
  254. package/dist/shims/unified-request-context.js +2 -0
  255. package/dist/shims/url-utils.d.ts +7 -0
  256. package/dist/shims/url-utils.js +12 -3
  257. package/dist/utils/asset-prefix.d.ts +7 -0
  258. package/dist/utils/asset-prefix.js +10 -1
  259. package/dist/utils/client-build-manifest.js +12 -5
  260. package/dist/utils/client-runtime-metadata.d.ts +1 -0
  261. package/dist/utils/client-runtime-metadata.js +15 -2
  262. package/dist/utils/domain-locale.js +1 -1
  263. package/dist/utils/lazy-chunks.d.ts +4 -0
  264. package/dist/utils/manifest-paths.d.ts +14 -0
  265. package/dist/utils/manifest-paths.js +22 -1
  266. package/dist/utils/path-to-regexp.d.ts +21 -0
  267. package/dist/{server/middleware-path-to-regexp.js → utils/path-to-regexp.js} +14 -11
  268. package/dist/utils/plugin-react-version.d.ts +15 -0
  269. package/dist/utils/plugin-react-version.js +64 -0
  270. package/dist/utils/plugin-rsc-version.d.ts +2 -0
  271. package/dist/utils/plugin-rsc-version.js +28 -2
  272. package/dist/utils/public-routes.d.ts +2 -0
  273. package/dist/utils/public-routes.js +18 -7
  274. package/dist/utils/react-version.d.ts +7 -0
  275. package/dist/utils/react-version.js +39 -16
  276. package/package.json +6 -6
  277. package/dist/build/nitro-route-rules.d.ts +0 -47
  278. package/dist/build/nitro-route-rules.js +0 -79
  279. package/dist/plugins/cache-flight-codec.d.ts +0 -19
  280. package/dist/plugins/cache-flight-codec.js +0 -68
  281. package/dist/server/middleware-path-to-regexp.d.ts +0 -13
  282. package/dist/utils/regex-safety.d.ts +0 -17
  283. package/dist/utils/regex-safety.js +0 -789
@@ -51,6 +51,7 @@ const isrCachePath = resolveEntryPath("../server/isr-cache.js", import.meta.url)
51
51
  const thenableParamsShimPath = resolveEntryPath("../shims/thenable-params.js", import.meta.url);
52
52
  const appPageElementBuilderPath = resolveEntryPath("../server/app-page-element-builder.js", import.meta.url);
53
53
  const instrumentationRuntimePath = resolveEntryPath("../server/instrumentation-runtime.js", import.meta.url);
54
+ const isolateSharedPromisePath = resolveEntryPath("../server/isolate-shared-promise.js", import.meta.url);
54
55
  const appRscErrorHandlerPath = resolveEntryPath("../server/app-rsc-error-handler.js", import.meta.url);
55
56
  const appRequestContextPath = resolveEntryPath("../server/app-request-context.js", import.meta.url);
56
57
  const appRequestStageContextPath = resolveEntryPath("../server/app-request-stage-context.js", import.meta.url);
@@ -116,19 +117,22 @@ function buildAppDecodedPathnamePatterns(routes, config) {
116
117
  };
117
118
  return routes.filter((route) => !route.isDynamic && !route.routePath && getAppRouteRenderEntryPath(route) !== null && isPrerenderedPage(route)).map((route) => route.pattern);
118
119
  }
119
- function buildAppRequestRouteMetadata(routes) {
120
+ function createForcesDynamicReader() {
120
121
  const readSource = createSegmentSourceReader();
121
- const forcesDynamic = (filePath) => {
122
+ return (filePath) => {
122
123
  const source = readSource(filePath);
123
124
  return source !== null && extractExportConstString(source, "dynamic") === "force-dynamic";
124
125
  };
126
+ }
127
+ /** Whether a direct request to the route renders a `dynamic = "force-dynamic"` tree. */
128
+ function directRequestForcesDynamic(route, forcesDynamic) {
129
+ return route.routePath ? forcesDynamic(route.routePath) : appPageSegmentConfigPaths(route).some(forcesDynamic);
130
+ }
131
+ function buildAppRequestRouteMetadata(routes) {
132
+ const forcesDynamic = createForcesDynamicReader();
125
133
  return routes.map((route) => ({
126
134
  canUseCanonicalLoadingShell: appRouteHasMainTreeLoadingBoundary(route),
127
- forceDynamic: route.routePath ? forcesDynamic(route.routePath) : [
128
- ...appPageSegmentConfigPaths(route),
129
- ...route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])),
130
- ...route.siblingIntercepts.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])
131
- ].some(forcesDynamic),
135
+ forceDynamic: directRequestForcesDynamic(route, forcesDynamic) || [...route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])), ...route.siblingIntercepts.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])].some(forcesDynamic),
132
136
  ids: route.ids ?? null,
133
137
  pattern: route.pattern,
134
138
  patternParts: route.patternParts,
@@ -179,6 +183,29 @@ function buildAppRequestRouteMetadata(routes) {
179
183
  }))
180
184
  }));
181
185
  }
186
+ /**
187
+ * Register the build-time route facts `revalidatePath()` uses to skip CDN
188
+ * purges for force-dynamic routes. A Pages Router can serve the same paths
189
+ * without those facts, so mixed apps always purge.
190
+ */
191
+ function generateCdnPurgeRoutesRegistration(routes, metadataRoutes, config) {
192
+ if (config?.hasPagesDir) return "";
193
+ const forcesDynamic = createForcesDynamicReader();
194
+ const purgeRoutes = {
195
+ metadataRoutes: (metadataRoutes ?? []).map((route) => ({
196
+ patternParts: route.patternParts ?? null,
197
+ routeSegments: route.routeSegments ?? [],
198
+ servedUrl: route.servedUrl
199
+ })),
200
+ routes: routes.map((route) => ({
201
+ forceDynamic: directRequestForcesDynamic(route, forcesDynamic),
202
+ patternParts: route.patternParts,
203
+ routeSegments: route.routeSegments
204
+ }))
205
+ };
206
+ return `import { registerCdnPurgeRoutes as __registerCdnPurgeRoutes } from "vinext/shims/cdn-purge-routes";
207
+ __registerCdnPurgeRoutes(${JSON.stringify(purgeRoutes)});`;
208
+ }
182
209
  /** Generate the module-free App request stage used by multi-stage Worker outputs. */
183
210
  function generateAppRequestRscEntry(appDir, routes, middlewarePath, metadataRoutes, _globalErrorPath, basePath, trailingSlash, config, instrumentationPath) {
184
211
  const bp = basePath ?? "";
@@ -204,13 +231,14 @@ import __pagesClientAssets from "virtual:vinext-pages-client-assets";
204
231
  ${middlewarePath ? `import { applyAppMiddleware as __applyAppMiddleware } from ${JSON.stringify(appMiddlewarePath)};` : ""}
205
232
  ${instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(toSlash(instrumentationPath))};
206
233
  import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(instrumentationRuntimePath)};
234
+ import { shareIsolatePromise as __shareIsolatePromise } from ${JSON.stringify(isolateSharedPromisePath)};
207
235
  let __applicationInitialization;
208
236
  async function __initializeApplication() {
209
237
  await __ensureInstrumentationRegistered(_instrumentation, ${JSON.stringify(toSlash(instrumentationPath))});
210
238
  ${middlewarePath ? `middlewareModule = await import(${JSON.stringify(toSlash(middlewarePath))});` : ""}
211
239
  }
212
- export function __ensureInstrumentation() {
213
- return __applicationInitialization ??= __initializeApplication();
240
+ export function __ensureInstrumentation(ctx) {
241
+ return __applicationInitialization ??= __shareIsolatePromise(__initializeApplication(), ctx);
214
242
  }` : "export function __ensureInstrumentation() {}"}
215
243
  ${middlewarePath ? instrumentationPath ? "let middlewareModule;" : `import * as middlewareModule from ${JSON.stringify(toSlash(middlewarePath))};` : ""}
216
244
  ${hasPagesDir ? `import { getDraftModeCookieHeader } from "next/headers";
@@ -219,8 +247,8 @@ import { renderPagesFallback as __renderPagesFallback } from ${JSON.stringify(ap
219
247
  import { buildRequestHeadersFromMiddlewareResponse as __buildRequestHeadersFromMiddlewareResponse } from ${JSON.stringify(middlewareRequestHeadersPath)};
220
248
  import { applyRouteHandlerMiddlewareContext as __applyRouteHandlerMiddlewareContext } from ${JSON.stringify(appRouteHandlerMiddlewareContextPath)};` : ""}
221
249
 
222
- ${hasPagesDir ? `export function __ensureHybridPagesApplication() {
223
- return __pagesRequestEntry.__ensureInstrumentation?.();
250
+ ${hasPagesDir ? `export function __ensureHybridPagesApplication(ctx) {
251
+ return __pagesRequestEntry.__ensureInstrumentation?.(ctx);
224
252
  }` : "export function __ensureHybridPagesApplication() {}"}
225
253
 
226
254
  const __basePath = ${JSON.stringify(bp)};
@@ -242,6 +270,7 @@ export const __clientBuildFiles = __pagesClientAssets.clientBuildFiles ?? [];
242
270
  const __routes = ${JSON.stringify(requestRoutes)};
243
271
  const __routeMatcher = __createAppRscRouteMatcher(__routes, ${JSON.stringify(buildAppDecodedPathnamePatterns(routes, config))});
244
272
  const __metadataRouteMatchers = ${JSON.stringify(metadataRouteMatchers)};
273
+ ${generateCdnPurgeRoutesRegistration(routes, metadataRoutes, config)}
245
274
 
246
275
  function matchRoute(pathname) { return __routeMatcher.matchRoute(pathname); }
247
276
  function matchRequestRoute(pathname) { return __routeMatcher.matchRequestRoute(pathname); }
@@ -295,7 +324,7 @@ const __requestHandler = createAppRscRequestHandler({
295
324
  devForwardedMiddlewareContextKey: ${JSON.stringify(config?.devForwardedMiddlewareContextKey ?? null)},
296
325
  dispatchMatchedPage() { throw new Error("App request stage attempted to render a page inline"); },
297
326
  dispatchMatchedRouteHandler() { throw new Error("App request stage attempted to render a route handler inline"); },
298
- ${instrumentationPath ? "ensureInstrumentation() { return __ensureInstrumentation(); }," : ""}
327
+ ${instrumentationPath ? "ensureInstrumentation(ctx) { return __ensureInstrumentation(ctx); }," : ""}
299
328
  i18nConfig: ${JSON.stringify(config?.i18n ?? null)},
300
329
  imageConfig: ${JSON.stringify(config?.imageConfig)},
301
330
  isMetadataRoute: __isMetadataPath,
@@ -368,6 +397,7 @@ const __requestHandler = createAppRscRequestHandler({
368
397
  },` : ""}
369
398
  rootParamNamesByPattern: {},
370
399
  setNavigationContext,
400
+ skipProxyUrlNormalize: ${JSON.stringify(config?.skipProxyUrlNormalize ?? false)},
371
401
  skipTrailingSlashRedirect: ${JSON.stringify(config?.skipTrailingSlashRedirect ?? false)},
372
402
  staticParamsMap: {},
373
403
  trailingSlash: __trailingSlash,
@@ -449,12 +479,12 @@ function generateRscEntry(appDir, routes, middlewarePath, metadataRoutes, global
449
479
  });
450
480
  const loadPrerenderPagesRoutesCode = hasPagesDir ? `
451
481
  let __hybridPagesApplication;
452
- export function __ensureHybridPagesApplication() {
453
- return __hybridPagesApplication ??= (async () => {
482
+ export function __ensureHybridPagesApplication(ctx) {
483
+ return __hybridPagesApplication ??= __shareIsolatePromise((async () => {
454
484
  const __pagesEntry = await import.meta.viteRsc.loadModule("ssr", "index");
455
- await __pagesEntry.__ensureInstrumentation?.();
485
+ await __pagesEntry.__ensureInstrumentation?.(ctx);
456
486
  return __pagesEntry;
457
- })();
487
+ })(), ctx);
458
488
  }
459
489
  async function __loadPrerenderPagesRoutes() {
460
490
  const __gspSsrEntry = await __ensureHybridPagesApplication();
@@ -475,8 +505,8 @@ ${metaRouteEntries.join(",\n")}
475
505
  rootLayouts = [${rootLayoutVars.join(", ")}];
476
506
  __fallbackRenderer = __createFallbackRenderer();
477
507
  }
478
- export function __ensureInstrumentation() {
479
- return __applicationInitialization ??= __initializeApplication();
508
+ export function __ensureInstrumentation(ctx) {
509
+ return __applicationInitialization ??= __shareIsolatePromise(__initializeApplication(), ctx);
480
510
  }` : "export function __ensureInstrumentation() {}";
481
511
  return `
482
512
  ${hasAppRouteHandlers ? `// Capture the canonical Request surface before any user module can extend it.
@@ -487,15 +517,22 @@ import __cacheabilityManifest from "virtual:vinext-cacheability-manifest";
487
517
  export { __cacheabilityManifest };
488
518
  import {
489
519
  renderToReadableStream as _renderToReadableStream,
490
- ${hasServerActions ? `decodeAction,
491
- decodeFormState,
492
- decodeReply,
493
- loadServerAction,
520
+ ${hasServerActions ? `loadServerAction,
494
521
  createTemporaryReferenceSet,` : ""}
495
522
  } from ${JSON.stringify(hasServerActions ? "@vitejs/plugin-rsc/rsc" : "@vitejs/plugin-rsc/react/rsc")};
496
- import { createClientManifest as _createClientManifest } from "@vitejs/plugin-rsc/core/rsc";
523
+ import {
524
+ createClientManifest as _createClientManifest,${hasServerActions ? `
525
+ createServerManifest as _createServerManifest,` : ""}
526
+ } from "@vitejs/plugin-rsc/core/rsc";
497
527
  import { prerender as _prerender } from "@vitejs/plugin-rsc/vendor/react-server-dom/static.edge";
498
- import { createRscPrerenderer, createRscRenderer } from ${JSON.stringify(rscStreamHintsPath)};
528
+ ${hasServerActions ? `// plugin-rsc's decoders fix an unscoped server manifest; React's own take the
529
+ // manifest, so actions can scope the server references they decode per route.
530
+ import {
531
+ decodeAction as _decodeAction,
532
+ decodeFormState as _decodeFormState,
533
+ decodeReply as _decodeReply,
534
+ } from "@vitejs/plugin-rsc/vendor/react-server-dom/server.edge";
535
+ ` : ""}import { createRscPrerenderer, createRscRenderer } from ${JSON.stringify(rscStreamHintsPath)};
499
536
 
500
537
  const renderToReadableStream = createRscRenderer(_renderToReadableStream);
501
538
  const prerenderToReadableStream = createRscPrerenderer(async (model, options) =>
@@ -505,6 +542,7 @@ import { createElement } from "react";
505
542
  import { getNavigationContext as _getNavigationContext } from "next/navigation";
506
543
  import { configureMemoryCacheHandler as __configureMemoryCacheHandler } from "vinext/shims/cache-handler";
507
544
  import { getRequestExecutionContext as __getRequestExecutionContext } from "vinext/shims/request-context";
545
+ import { shareIsolatePromise as __shareIsolatePromise } from ${JSON.stringify(isolateSharedPromisePath)};
508
546
  import { headersContextFromRequest, getDraftModeCookieHeader, getAndClearPendingCookies, consumeDynamicUsage, consumeInvalidDynamicUsageError, setHeadersAccessPhase } from "next/headers";
509
547
  import { mergeMetadata, resolveModuleMetadata, mergeViewport, resolveModuleViewport } from "vinext/metadata";
510
548
  ${config?.nodeOpenTelemetryLoader ? `import { register as __registerOpenTelemetryLoader } from "node:module";
@@ -878,6 +916,8 @@ function __createFallbackRenderer() {
878
916
  }
879
917
  ${instrumentationPath ? "let __fallbackRenderer;" : "const __fallbackRenderer = __createFallbackRenderer();"}
880
918
 
919
+ ${generateCdnPurgeRoutesRegistration(routes, metadataRoutes, config)}
920
+
881
921
  function matchRoute(url) {
882
922
  return __routeMatcher.matchRoute(url);
883
923
  }
@@ -1286,8 +1326,8 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1286
1326
  searchParams,
1287
1327
  });
1288
1328
  },
1289
- ${instrumentationPath ? `ensureInstrumentation() {
1290
- return __ensureInstrumentation();
1329
+ ${instrumentationPath ? `ensureInstrumentation(ctx) {
1330
+ return __ensureInstrumentation(ctx);
1291
1331
  },` : ""}
1292
1332
  ${hasServerActions ? `
1293
1333
  async handleProgressiveActionRequest({
@@ -1305,13 +1345,15 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1305
1345
  } = await __loadAppServerActionExecution();
1306
1346
  const {
1307
1347
  areServerActionsOwnedByRoute: __areServerActionsOwnedByRoute,
1348
+ createForwardedActionContext: __createForwardedActionContext,
1308
1349
  forwardServerActionIfNeeded: __forwardServerActionIfNeeded,
1309
1350
  } = await __loadAppActionForwarding();
1310
1351
  // A multipart form POST to a page is always a server-action attempt, so a
1311
1352
  // body that decodes to no action must surface as 404 action-not-found
1312
- // (#1340). Route handlers run after this dispatch and accept raw multipart
1313
- // POSTs, so only flag actual page routes. The __loadPage / __loadRouteHandler
1314
- // markers are static and available before lazy module hydration.
1353
+ // (#1340). Route handlers and Pages routes never reach this dispatch
1354
+ // (#3886) and unmatched routes fall through, so only flag page routes.
1355
+ // The __loadPage marker is static and available before lazy module
1356
+ // hydration.
1315
1357
  //
1316
1358
  // Only the progressive (multipart, no actionId) POST path consults
1317
1359
  // hasPageRoute, so skip the route match entirely for every other request
@@ -1321,11 +1363,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1321
1363
  contentType,
1322
1364
  actionId,
1323
1365
  );
1324
- const __hasPageRoute = Boolean(
1325
- __isProgressiveAction &&
1326
- routeMatch?.route.__loadPage &&
1327
- !routeMatch.route.__loadRouteHandler,
1328
- );
1366
+ const __hasPageRoute = Boolean(__isProgressiveAction && routeMatch?.route.__loadPage);
1329
1367
  return __handleProgressiveServerActionRequest({
1330
1368
  actionId,
1331
1369
  allowedOrigins: __allowedOrigins,
@@ -1335,8 +1373,9 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1335
1373
  __clearRequestContext();
1336
1374
  },
1337
1375
  contentType,
1338
- decodeAction,
1339
- decodeFormState,
1376
+ createServerManifest: _createServerManifest,
1377
+ decodeAction: _decodeAction,
1378
+ decodeFormState: _decodeFormState,
1340
1379
  getAndClearPendingCookies,
1341
1380
  getDraftModeCookieHeader,
1342
1381
  forwardAction(__progressiveActionId) {
@@ -1348,17 +1387,9 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1348
1387
  clearRequestContext: __clearRequestContext,
1349
1388
  currentRoutePattern: routeMatch?.route.pattern ?? null,
1350
1389
  dispatch(__forwardRequest) {
1351
- const __executionContext = __getRequestExecutionContext();
1352
1390
  return __appRscHandler(
1353
1391
  __forwardRequest,
1354
- __executionContext
1355
- ? {
1356
- actionForwarded: true,
1357
- cache: __executionContext.cache,
1358
- passThroughOnException: __executionContext.passThroughOnException?.bind(__executionContext),
1359
- waitUntil: __executionContext.waitUntil.bind(__executionContext),
1360
- }
1361
- : { actionForwarded: true },
1392
+ __createForwardedActionContext(__getRequestExecutionContext()),
1362
1393
  );
1363
1394
  },
1364
1395
  middlewareContext,
@@ -1398,8 +1429,11 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1398
1429
  sourceConfigHeaders,
1399
1430
  searchParams,
1400
1431
  }) {
1401
- const { forwardServerActionIfNeeded: __forwardServerActionIfNeeded } =
1402
- await __loadAppActionForwarding();
1432
+ const {
1433
+ areServerActionsOwnedByRoute: __areServerActionsOwnedByRoute,
1434
+ createForwardedActionContext: __createForwardedActionContext,
1435
+ forwardServerActionIfNeeded: __forwardServerActionIfNeeded,
1436
+ } = await __loadAppActionForwarding();
1403
1437
  const __currentActionMatch = routeMatch;
1404
1438
  const __forwardResponse = await __forwardServerActionIfNeeded({
1405
1439
  actionId,
@@ -1409,17 +1443,9 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1409
1443
  clearRequestContext: __clearRequestContext,
1410
1444
  currentRoutePattern: __currentActionMatch?.route.pattern ?? null,
1411
1445
  dispatch(__forwardRequest) {
1412
- const __executionContext = __getRequestExecutionContext();
1413
1446
  return __appRscHandler(
1414
1447
  __forwardRequest,
1415
- __executionContext
1416
- ? {
1417
- actionForwarded: true,
1418
- cache: __executionContext.cache,
1419
- passThroughOnException: __executionContext.passThroughOnException?.bind(__executionContext),
1420
- waitUntil: __executionContext.waitUntil.bind(__executionContext),
1421
- }
1422
- : { actionForwarded: true },
1448
+ __createForwardedActionContext(__getRequestExecutionContext()),
1423
1449
  );
1424
1450
  },
1425
1451
  middlewareContext,
@@ -1492,8 +1518,9 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1492
1518
  createRscOnErrorHandler(actionRequest, actionPathname, routePattern, overrides) {
1493
1519
  return createRscOnErrorHandler(actionRequest, actionPathname, routePattern, overrides);
1494
1520
  },
1521
+ createServerManifest: _createServerManifest,
1495
1522
  createTemporaryReferenceSet,
1496
- decodeReply,
1523
+ decodeReply: _decodeReply,
1497
1524
  dispatchRedirectRequest(redirectRequest) {
1498
1525
  return __appRscHandler(redirectRequest, undefined);
1499
1526
  },
@@ -1511,6 +1538,13 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1511
1538
  },
1512
1539
  isRscRequest,
1513
1540
  loadServerAction,
1541
+ validateActionReferences(__argumentActionIds) {
1542
+ return __areServerActionsOwnedByRoute(
1543
+ __VINEXT_ACTION_OWNERS(),
1544
+ __argumentActionIds,
1545
+ __actionMatch?.route.pattern ?? null,
1546
+ );
1547
+ },
1514
1548
  // Redirect targets are rendered as if the client had navigated to them,
1515
1549
  // so they must route on the raw pathname a real request would use.
1516
1550
  matchRoute(pathnameToMatch) {
@@ -1676,6 +1710,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1676
1710
  },` : ""}
1677
1711
  rootParamNamesByPattern: rootParamNamesMap,
1678
1712
  setNavigationContext,
1713
+ skipProxyUrlNormalize: ${JSON.stringify(config?.skipProxyUrlNormalize ?? false)},
1679
1714
  skipTrailingSlashRedirect: ${JSON.stringify(config?.skipTrailingSlashRedirect ?? false)},
1680
1715
  staticParamsMap: generateStaticParamsMap,
1681
1716
  trailingSlash: __trailingSlash,
@@ -49,5 +49,15 @@ type BuildAppRscManifestCodeOptions = {
49
49
  */
50
50
  globalNotFoundPath?: string | null;
51
51
  };
52
+ /**
53
+ * The root not-found, forbidden and unauthorized boundaries, which a route
54
+ * without its own boundary falls back to.
55
+ */
56
+ export declare function rootBoundaryFiles(routes: readonly AppRoute[]): string[];
57
+ /**
58
+ * The files a render without a matched route shows (a route-miss 404, or a
59
+ * forbidden or unauthorized boundary): the root layouts and root boundaries.
60
+ */
61
+ export declare function rootBoundaryRouteFiles(routes: readonly AppRoute[]): string[];
52
62
  export declare function buildAppRscManifestCode(options: BuildAppRscManifestCodeOptions): AppRscManifestCode;
53
63
  //#endregion
@@ -17,6 +17,25 @@ function rootRouteBoundaryPath(route, boundaryPaths, fallbackPath) {
17
17
  if (route.pattern === "/") return fallbackPath ?? null;
18
18
  return boundaryPaths?.[0] ?? fallbackPath ?? null;
19
19
  }
20
+ /**
21
+ * The root not-found, forbidden and unauthorized boundaries, which a route
22
+ * without its own boundary falls back to.
23
+ */
24
+ function rootBoundaryFiles(routes) {
25
+ const rootRoute = findRootBoundaryRoute(routes);
26
+ return [
27
+ rootRouteBoundaryPath(rootRoute, rootRoute?.notFoundPaths, rootRoute?.notFoundPath),
28
+ rootRouteBoundaryPath(rootRoute, rootRoute?.forbiddenPaths, rootRoute?.forbiddenPath),
29
+ rootRouteBoundaryPath(rootRoute, rootRoute?.unauthorizedPaths, rootRoute?.unauthorizedPath)
30
+ ].filter((file) => file !== null);
31
+ }
32
+ /**
33
+ * The files a render without a matched route shows (a route-miss 404, or a
34
+ * forbidden or unauthorized boundary): the root layouts and root boundaries.
35
+ */
36
+ function rootBoundaryRouteFiles(routes) {
37
+ return [...rootRouteLayoutPaths(findRootBoundaryRoute(routes)), ...rootBoundaryFiles(routes)];
38
+ }
20
39
  function createImportAllocator(deferEagerImports) {
21
40
  const imports = [];
22
41
  const importInitializers = [];
@@ -357,4 +376,4 @@ function buildAppRscManifestCode(options) {
357
376
  };
358
377
  }
359
378
  //#endregion
360
- export { buildAppRscManifestCode };
379
+ export { buildAppRscManifestCode, rootBoundaryFiles, rootBoundaryRouteFiles };
@@ -9,6 +9,9 @@
9
9
  * entry also re-exports selected Pages server entry hooks from
10
10
  * `virtual:vinext-server-entry` so the RSC bundle can access Pages Router
11
11
  * route metadata and fallback dispatchers via `import("./ssr/index.js")`.
12
+ *
13
+ * `nitroPublicFilesEntry` wraps the default export for Nitro, so a public file
14
+ * the router resolves is served by Nitro's static handler.
12
15
  */
13
- export declare function generateSsrEntry(hasPagesDir?: boolean): string;
16
+ export declare function generateSsrEntry(hasPagesDir?: boolean, nitroPublicFilesEntry?: string | null): string;
14
17
  //#endregion
@@ -10,12 +10,19 @@ import { resolveRuntimeEntryModule } from "./runtime-entry-module.js";
10
10
  * entry also re-exports selected Pages server entry hooks from
11
11
  * `virtual:vinext-server-entry` so the RSC bundle can access Pages Router
12
12
  * route metadata and fallback dispatchers via `import("./ssr/index.js")`.
13
+ *
14
+ * `nitroPublicFilesEntry` wraps the default export for Nitro, so a public file
15
+ * the router resolves is served by Nitro's static handler.
13
16
  */
14
- function generateSsrEntry(hasPagesDir = false) {
17
+ function generateSsrEntry(hasPagesDir = false, nitroPublicFilesEntry = null) {
15
18
  const entryPath = resolveRuntimeEntryModule("app-ssr-entry");
16
19
  return `
17
20
  export * from ${JSON.stringify(entryPath)};
18
- export { default } from ${JSON.stringify(entryPath)};
21
+ ${nitroPublicFilesEntry ? `
22
+ import ssrEntry from ${JSON.stringify(entryPath)};
23
+ import { withNitroPublicFiles } from ${JSON.stringify(nitroPublicFilesEntry)};
24
+ export default withNitroPublicFiles(ssrEntry);
25
+ ` : `export { default } from ${JSON.stringify(entryPath)};`}
19
26
  ${hasPagesDir ? `
20
27
  export {
21
28
  __ensureInstrumentation,
@@ -6,6 +6,7 @@ import { VinextLinkPrefetchRoute } from "../client/vinext-next-data.js";
6
6
  export declare function compileClientMiddlewareMatchers(matcher: StaticMiddlewareMatcher | undefined): unknown[] | undefined;
7
7
  export declare function generateClientEntry(pagesDir: string, nextConfig: ResolvedNextConfig, fileMatcher: ReturnType<typeof createValidFileMatcher>, options?: {
8
8
  appPrefetchRoutes?: readonly VinextLinkPrefetchRoute[];
9
+ appRouteHandlers?: readonly VinextLinkPrefetchRoute[];
9
10
  instrumentationClientPath?: string | null;
10
11
  middlewareMatcher?: StaticMiddlewareMatcher | undefined;
11
12
  reactPreamble?: boolean;
@@ -1,7 +1,7 @@
1
1
  import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import { findFileWithExts } from "../routing/file-matcher.js";
3
3
  import { patternToNextFormat } from "../routing/route-validation.js";
4
- import { apiRouter, pagesRouter } from "../routing/pages-router.js";
4
+ import { pagesRouter } from "../routing/pages-router.js";
5
5
  import { resolveClientRuntimeModule } from "./runtime-entry-module.js";
6
6
  import { compileMiddlewareMatcherPattern } from "../server/middleware-matcher-pattern.js";
7
7
  import { hasExportedName } from "../build/report.js";
@@ -56,15 +56,12 @@ async function hasGetServerSidePropsExport(filePath) {
56
56
  }
57
57
  async function generateClientEntry(pagesDir, nextConfig, fileMatcher, options = {}) {
58
58
  const pageRoutes = await pagesRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);
59
- const apiRoutes = await apiRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);
60
59
  const appFilePath = findFileWithExts(pagesDir, "_app", fileMatcher);
61
60
  const errorFilePath = findFileWithExts(pagesDir, "_error", fileMatcher);
62
61
  const hasApp = appFilePath !== null;
63
62
  const appPrefetchRoutes = options.appPrefetchRoutes ?? [];
64
- const pagesPrefetchRoutes = [...pageRoutes.map(toPagesLinkPrefetchRoute), ...apiRoutes.map((route) => ({
65
- ...toPagesLinkPrefetchRoute(route),
66
- documentOnly: true
67
- }))];
63
+ const appRouteHandlers = options.appRouteHandlers ?? [];
64
+ const pagesPrefetchRoutes = pageRoutes.map(toPagesLinkPrefetchRoute);
68
65
  const pagesSsgPatterns = (await Promise.all(pageRoutes.map(async (route) => await hasGetStaticPropsExport(route.filePath) ? patternToNextFormat(route.pattern) : null))).filter((pattern) => pattern !== null);
69
66
  const pagesSspPatterns = (await Promise.all(pageRoutes.map(async (route) => await hasGetServerSidePropsExport(route.filePath) ? patternToNextFormat(route.pattern) : null))).filter((pattern) => pattern !== null);
70
67
  const instrumentationClientPath = options.instrumentationClientPath ?? null;
@@ -137,6 +134,9 @@ window.__VINEXT_APP_LOADER__ = appLoader;
137
134
  // when the user lands on an App Router page (see app-browser-entry.ts) — the
138
135
  // two writes do not race because only one entry executes per page load.
139
136
  window.__VINEXT_LINK_PREFETCH_ROUTES__ = ${JSON.stringify(appPrefetchRoutes)};
137
+ // App route handlers with hashed static segments, for the same ownership
138
+ // decisions (see hashed-route-patterns.ts).
139
+ window.__VINEXT_APP_ROUTE_HANDLERS__ = ${JSON.stringify(appRouteHandlers)};
140
140
  // Pages route manifest, exposed so the App Router runtime can decide when
141
141
  // a soft-navigated URL is actually owned by Pages (and must hard-navigate
142
142
  // instead of issuing an RSC request). Set here AND in app-browser-entry.ts
@@ -28,6 +28,7 @@ const _pagesRouteDataKindPath = resolveEntryPath("../server/pages-route-data-kin
28
28
  const _isrCachePath = resolveEntryPath("../server/isr-cache.js", import.meta.url);
29
29
  const _revalidationRequestPath = resolveEntryPath("../server/revalidation-request.js", import.meta.url);
30
30
  const _instrumentationRuntimePath = resolveEntryPath("../server/instrumentation-runtime.js", import.meta.url);
31
+ const _isolateSharedPromisePath = resolveEntryPath("../server/isolate-shared-promise.js", import.meta.url);
31
32
  async function getPagesDataKind(filePath) {
32
33
  const source = await readFile(filePath, "utf8");
33
34
  if (hasExportedName(source, "getStaticProps")) return "static";
@@ -85,18 +86,19 @@ async function generatePagesRequestEntry(pagesDir, nextConfig, fileMatcher, midd
85
86
  }
86
87
  });
87
88
  const instrumentationImportCode = instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(instrumentationPath)};
88
- import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(_instrumentationRuntimePath)};` : "";
89
+ import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(_instrumentationRuntimePath)};
90
+ import { shareIsolatePromise as __shareIsolatePromise } from ${JSON.stringify(_isolateSharedPromisePath)};` : "";
89
91
  const instrumentationInitCode = instrumentationPath ? `let __applicationInitialization;
90
92
  async function __initializeApplication() {
91
93
  await __ensureInstrumentationRegistered(_instrumentation, ${JSON.stringify(instrumentationPath)});
92
94
  ${middlewarePath ? `middlewareModule = await import(${JSON.stringify(middlewarePath)});` : ""}
93
95
  }
94
- export function __ensureInstrumentation() {
95
- return __applicationInitialization ??= __initializeApplication();
96
+ export function __ensureInstrumentation(ctx) {
97
+ return __applicationInitialization ??= __shareIsolatePromise(__initializeApplication(), ctx);
96
98
  }` : "export function __ensureInstrumentation() {}";
97
99
  const middlewareImportCode = middlewarePath ? instrumentationPath ? "let middlewareModule;" : `import * as middlewareModule from ${JSON.stringify(middlewarePath)};` : "";
98
100
  const middlewareExportCode = middlewarePath ? `export async function runMiddleware(request, ctx, options) {
99
- ${instrumentationPath ? "await __ensureInstrumentation();" : ""}
101
+ ${instrumentationPath ? "await __ensureInstrumentation(ctx);" : ""}
100
102
  return __runGeneratedMiddleware({
101
103
  basePath: vinextConfig.basePath,
102
104
  ctx,
@@ -110,8 +112,8 @@ export function __ensureInstrumentation() {
110
112
  skipTrailingSlashRedirect: vinextConfig.skipTrailingSlashRedirect,
111
113
  trailingSlash: vinextConfig.trailingSlash,
112
114
  });
113
- }` : `export async function runMiddleware() {
114
- ${instrumentationPath ? "await __ensureInstrumentation();" : ""}
115
+ }` : `export async function runMiddleware(request, ctx) {
116
+ ${instrumentationPath ? "await __ensureInstrumentation(ctx);" : ""}
115
117
  return { continue: true };
116
118
  }`;
117
119
  return `
@@ -260,7 +262,8 @@ async function generateServerEntry(pagesDir, nextConfig, fileMatcher, middleware
260
262
  }
261
263
  });
262
264
  const instrumentationImportCode = instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(instrumentationPath)};
263
- import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(_instrumentationRuntimePath)};` : "";
265
+ import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(_instrumentationRuntimePath)};
266
+ import { shareIsolatePromise as __shareIsolatePromise } from ${JSON.stringify(_isolateSharedPromisePath)};` : "";
264
267
  const specialModuleInitializers = instrumentationPath ? [
265
268
  appFilePath ? `({ default: AppComponent } = await import(${JSON.stringify(appFilePath)}));` : "",
266
269
  docFilePath ? `({ default: DocumentComponent } = await import(${JSON.stringify(docFilePath)}));` : "",
@@ -278,8 +281,8 @@ async function __initializeApplication() {
278
281
  _errorPageRoute.module = ErrorPageModule;
279
282
  _renderPage = __createRenderPage();
280
283
  }
281
- export function __ensureInstrumentation() {
282
- return __applicationInitialization ??= __initializeApplication();
284
+ export function __ensureInstrumentation(ctx) {
285
+ return __applicationInitialization ??= __shareIsolatePromise(__initializeApplication(), ctx);
283
286
  }` : "export function __ensureInstrumentation() {}";
284
287
  const openTelemetryLoaderCode = options.nodeOpenTelemetryLoader ? `import { register as __registerOpenTelemetryLoader } from "node:module";
285
288
  const __openTelemetryLoaderKey = Symbol.for("vinext.openTelemetryLoader");
@@ -291,7 +294,7 @@ if (process.env.VINEXT_PRERENDER !== "1" && !globalThis[__openTelemetryLoaderKey
291
294
  const middlewareRuntimeImportCode = includeMiddlewareRuntime ? `import { runGeneratedMiddleware as __runGeneratedMiddleware } from ${JSON.stringify(_middlewareRuntimePath)};` : "";
292
295
  const middlewareExportCode = includeMiddlewareRuntime ? middlewarePath ? `
293
296
  export async function runMiddleware(request, ctx, options) {
294
- ${instrumentationPath ? "await __ensureInstrumentation();" : ""}
297
+ ${instrumentationPath ? "await __ensureInstrumentation(ctx);" : ""}
295
298
  return __runGeneratedMiddleware({
296
299
  basePath: vinextConfig.basePath,
297
300
  ctx,
@@ -307,8 +310,8 @@ export async function runMiddleware(request, ctx, options) {
307
310
  });
308
311
  }
309
312
  ` : `
310
- export async function runMiddleware(request) {
311
- ${instrumentationPath ? "await __ensureInstrumentation();" : ""}
313
+ export async function runMiddleware(request, ctx) {
314
+ ${instrumentationPath ? "await __ensureInstrumentation(ctx);" : ""}
312
315
  return { continue: true };
313
316
  }
314
317
  ` : "";
@@ -568,7 +571,7 @@ function __createRenderPage() {
568
571
  ${instrumentationPath ? "let _renderPage;" : "const _renderPage = __createRenderPage();"}
569
572
 
570
573
  export async function renderPage(request, url, manifest, ctx, middlewareHeaders, options, initialResponseHeaders) {
571
- ${instrumentationPath ? "await __ensureInstrumentation();" : ""}
574
+ ${instrumentationPath ? "await __ensureInstrumentation(ctx);" : ""}
572
575
  __registerConfiguredCacheAdapters();
573
576
  if (ctx) return _runWithExecutionContext(ctx, () => _renderPage(request, url, manifest, middlewareHeaders, options, initialResponseHeaders));
574
577
  return _renderPage(request, url, manifest, middlewareHeaders, options, initialResponseHeaders);
@@ -577,7 +580,7 @@ export async function renderPage(request, url, manifest, ctx, middlewareHeaders,
577
580
 
578
581
 
579
582
  export async function handleApiRoute(request, url, ctx, trustedRevalidateOrigin, edgeRuntime = "worker", initialResponseHeaders) {
580
- ${instrumentationPath ? "await __ensureInstrumentation();" : ""}
583
+ ${instrumentationPath ? "await __ensureInstrumentation(ctx);" : ""}
581
584
  __registerConfiguredCacheAdapters();
582
585
  const match = matchRoute(url, apiRoutes);
583
586
  return __handlePagesApiRoute({
package/dist/index.d.ts CHANGED
@@ -24,6 +24,17 @@ export type VinextOptions = {
24
24
  * @default false
25
25
  */
26
26
  disableAppRouter?: boolean;
27
+ /**
28
+ * Turn off Next.js-like client chunking in App Router production builds.
29
+ * By default, client components that the same routes use load through one
30
+ * shared chunk, as they do from Next.js' per-route client entries. Set this
31
+ * to load each client component from its own chunk instead, for example to
32
+ * control chunking entirely through your own chunk groups. vinext already
33
+ * turns this chunking off when the client build has chunk groups other than
34
+ * its own (`codeSplitting.groups`, `advancedChunks` or `manualChunks`).
35
+ * @default false
36
+ */
37
+ disableNextLikeChunking?: boolean;
27
38
  /**
28
39
  * Override the output directory for the RSC server bundle.
29
40
  * Absolute paths are used as-is; relative paths are resolved from the