vinext 1.0.0-beta.10 → 1.0.0-beta.11

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 (166) hide show
  1. package/README.md +12 -12
  2. package/THIRD_PARTY_LICENSES.md +25 -0
  3. package/dist/_virtual/_rolldown/runtime.js +25 -0
  4. package/dist/build/prerender-paths.d.ts +4 -0
  5. package/dist/build/prerender-paths.js +64 -32
  6. package/dist/build/prerender.d.ts +1 -1
  7. package/dist/build/prerender.js +1 -1
  8. package/dist/cache/cache-adapters-virtual.d.ts +3 -3
  9. package/dist/cache/cache-adapters-virtual.js +14 -7
  10. package/dist/check.js +74 -18
  11. package/dist/client/dev-error-overlay.js +1 -1
  12. package/dist/config/next-config.d.ts +4 -0
  13. package/dist/config/next-config.js +151 -6
  14. package/dist/config/prerender.d.ts +2 -2
  15. package/dist/config/prerender.js +2 -2
  16. package/dist/config/server-external-packages.d.ts +13 -1
  17. package/dist/config/server-external-packages.js +37 -3
  18. package/dist/deps/.pnpm/ignore@5.3.2/deps/ignore/index.js +189 -0
  19. package/dist/deps/.pnpm/ua-parser-js@1.0.35/deps/ua-parser-js/src/ua-parser.js +1057 -0
  20. package/dist/entries/app-rsc-entry.d.ts +2 -0
  21. package/dist/entries/app-rsc-entry.js +104 -25
  22. package/dist/entries/app-rsc-manifest.d.ts +2 -0
  23. package/dist/entries/app-rsc-manifest.js +9 -3
  24. package/dist/entries/app-ssr-entry.js +8 -1
  25. package/dist/entries/pages-server-entry.d.ts +1 -0
  26. package/dist/entries/pages-server-entry.js +67 -20
  27. package/dist/index.js +124 -25
  28. package/dist/plugins/instrumentation-client.d.ts +2 -1
  29. package/dist/plugins/instrumentation-client.js +45 -9
  30. package/dist/plugins/optimize-imports.d.ts +2 -1
  31. package/dist/plugins/optimize-imports.js +3 -1
  32. package/dist/server/api-handler.js +7 -5
  33. package/dist/server/app-browser-entry.js +4 -4
  34. package/dist/server/app-browser-error.js +1 -1
  35. package/dist/server/app-browser-navigation-controller.js +1 -1
  36. package/dist/server/app-browser-state.js +1 -1
  37. package/dist/server/app-browser-visible-commit.js +1 -1
  38. package/dist/server/app-fallback-renderer.d.ts +2 -1
  39. package/dist/server/app-fallback-renderer.js +6 -6
  40. package/dist/server/app-fetch-tracing.d.ts +15 -0
  41. package/dist/server/app-fetch-tracing.js +38 -0
  42. package/dist/server/app-metadata-tracing.d.ts +12 -0
  43. package/dist/server/app-metadata-tracing.js +17 -0
  44. package/dist/server/app-page-boundary-render.d.ts +2 -1
  45. package/dist/server/app-page-boundary-render.js +8 -3
  46. package/dist/server/app-page-cache-finalizer.d.ts +2 -0
  47. package/dist/server/app-page-cache-finalizer.js +6 -2
  48. package/dist/server/app-page-cache-render.d.ts +2 -0
  49. package/dist/server/app-page-cache-render.js +16 -2
  50. package/dist/server/app-page-dispatch.d.ts +3 -1
  51. package/dist/server/app-page-dispatch.js +44 -15
  52. package/dist/server/app-page-element-builder.js +87 -55
  53. package/dist/server/app-page-head.d.ts +4 -0
  54. package/dist/server/app-page-head.js +22 -9
  55. package/dist/server/app-page-http-access-fallback-metadata.d.ts +2 -0
  56. package/dist/server/app-page-http-access-fallback-metadata.js +9 -2
  57. package/dist/server/app-page-render.d.ts +20 -3
  58. package/dist/server/app-page-render.js +81 -7
  59. package/dist/server/app-page-route-wiring.js +16 -10
  60. package/dist/server/app-page-stream.d.ts +12 -0
  61. package/dist/server/app-page-stream.js +32 -5
  62. package/dist/server/app-page-tracing.d.ts +33 -0
  63. package/dist/server/app-page-tracing.js +49 -0
  64. package/dist/server/app-request-stage-independent-entry.js +19 -3
  65. package/dist/server/app-response-header-provenance.js +2 -1
  66. package/dist/server/app-response-stage-entry.js +24 -4
  67. package/dist/server/app-route-handler-cache.js +46 -34
  68. package/dist/server/app-route-handler-dispatch.js +17 -8
  69. package/dist/server/app-route-handler-execution.d.ts +6 -2
  70. package/dist/server/app-route-handler-execution.js +62 -12
  71. package/dist/server/app-router-entry.d.ts +2 -0
  72. package/dist/server/app-router-entry.js +25 -5
  73. package/dist/server/app-rsc-error-handler.d.ts +11 -4
  74. package/dist/server/app-rsc-error-handler.js +15 -6
  75. package/dist/server/app-rsc-errors.d.ts +6 -2
  76. package/dist/server/app-rsc-errors.js +5 -5
  77. package/dist/server/app-rsc-handler.d.ts +1 -0
  78. package/dist/server/app-rsc-handler.js +35 -11
  79. package/dist/server/app-rsc-response-stage.js +11 -5
  80. package/dist/server/app-server-action-execution.d.ts +6 -2
  81. package/dist/server/app-server-action-execution.js +36 -21
  82. package/dist/server/app-ssr-entry.d.ts +4 -0
  83. package/dist/server/app-ssr-entry.js +16 -7
  84. package/dist/server/app-worker-stages.d.ts +1 -0
  85. package/dist/server/app-worker-stages.js +1 -1
  86. package/dist/server/cacheability-request.js +8 -1
  87. package/dist/server/client-trace-metadata.d.ts +5 -1
  88. package/dist/server/client-trace-metadata.js +27 -15
  89. package/dist/server/cloudflare-workers-tracing.d.ts +1 -0
  90. package/dist/server/cloudflare-workers-tracing.js +8 -0
  91. package/dist/server/defer-until-stream-consumed.d.ts +1 -1
  92. package/dist/server/defer-until-stream-consumed.js +2 -1
  93. package/dist/server/dev-server.js +96 -52
  94. package/dist/server/framework-tracer.d.ts +46 -0
  95. package/dist/server/framework-tracer.js +125 -0
  96. package/dist/server/fully-buffered-response.d.ts +11 -0
  97. package/dist/server/fully-buffered-response.js +19 -0
  98. package/dist/server/headers.d.ts +6 -0
  99. package/dist/server/headers.js +11 -2
  100. package/dist/server/instrumentation-runtime.d.ts +16 -19
  101. package/dist/server/instrumentation-runtime.js +26 -8
  102. package/dist/server/instrumentation.d.ts +14 -12
  103. package/dist/server/instrumentation.js +8 -8
  104. package/dist/server/isr-cache.d.ts +3 -1
  105. package/dist/server/isr-cache.js +4 -3
  106. package/dist/server/metadata-route-response.js +2 -1
  107. package/dist/server/middleware-runtime.js +27 -1
  108. package/dist/server/opentelemetry-api.d.ts +59 -0
  109. package/dist/server/opentelemetry-api.js +53 -0
  110. package/dist/server/opentelemetry-tracing.d.ts +5 -0
  111. package/dist/server/opentelemetry-tracing.js +83 -0
  112. package/dist/server/otel-tracer-extension.d.ts +5 -6
  113. package/dist/server/otel-tracer-extension.js +37 -36
  114. package/dist/server/pages-api-route.js +6 -6
  115. package/dist/server/pages-execution-tracing.d.ts +40 -0
  116. package/dist/server/pages-execution-tracing.js +80 -0
  117. package/dist/server/pages-page-data.js +9 -8
  118. package/dist/server/pages-page-handler.d.ts +2 -0
  119. package/dist/server/pages-page-handler.js +42 -19
  120. package/dist/server/pages-page-response.d.ts +4 -0
  121. package/dist/server/pages-page-response.js +42 -27
  122. package/dist/server/pages-request-pipeline.js +7 -1
  123. package/dist/server/pages-request-stage-entry.js +18 -1
  124. package/dist/server/pages-response-stage-entry.js +3 -1
  125. package/dist/server/pages-router-entry.js +9 -2
  126. package/dist/server/pregenerated-concrete-paths.d.ts +1 -0
  127. package/dist/server/pregenerated-concrete-paths.js +10 -6
  128. package/dist/server/prerender-manifest.d.ts +1 -0
  129. package/dist/server/prerender-manifest.js +6 -3
  130. package/dist/server/prerender-work-unit-setup.js +4 -4
  131. package/dist/server/prod-server.d.ts +2 -1
  132. package/dist/server/prod-server.js +81 -5
  133. package/dist/server/request-tracing.d.ts +22 -0
  134. package/dist/server/request-tracing.js +180 -0
  135. package/dist/server/response-stage-cacheability.d.ts +1 -0
  136. package/dist/server/response-stage-cacheability.js +2 -1
  137. package/dist/server/response-stage-policy.js +2 -1
  138. package/dist/server/response-start-tracing.d.ts +14 -0
  139. package/dist/server/response-start-tracing.js +80 -0
  140. package/dist/server/seed-cache.js +3 -2
  141. package/dist/server/tracer.d.ts +5 -0
  142. package/dist/server/tracer.js +13 -0
  143. package/dist/server/workers-tracing.d.ts +17 -0
  144. package/dist/server/workers-tracing.js +27 -0
  145. package/dist/shims/cache-runtime.js +5 -4
  146. package/dist/shims/cache.js +1 -1
  147. package/dist/shims/cacheability-classification.d.ts +4 -0
  148. package/dist/shims/cacheability-classification.js +7 -1
  149. package/dist/shims/cdn-cache.d.ts +3 -0
  150. package/dist/shims/cdn-cache.js +7 -0
  151. package/dist/shims/error-boundary.js +1 -1
  152. package/dist/shims/error.js +1 -1
  153. package/dist/shims/fetch-cache.d.ts +1 -0
  154. package/dist/shims/fetch-cache.js +37 -14
  155. package/dist/shims/navigation.js +2 -2
  156. package/dist/shims/navigation.react-server.js +1 -1
  157. package/dist/shims/server.d.ts +3 -34
  158. package/dist/shims/server.js +1 -19
  159. package/dist/shims/unified-request-context.d.ts +3 -16
  160. package/dist/shims/unified-request-context.js +2 -23
  161. package/dist/shims/user-agent.d.ts +31 -0
  162. package/dist/shims/user-agent.js +16 -0
  163. package/dist/utils/navigation-signal.d.ts +1 -0
  164. package/dist/utils/navigation-signal.js +16 -1
  165. package/next-package.json +4 -0
  166. package/package.json +15 -2
package/README.md CHANGED
@@ -4,9 +4,7 @@ Run Next.js applications on Vite, with Cloudflare Workers as the primary deploym
4
4
 
5
5
  **Website:** [vinext.dev](https://vinext.dev)
6
6
 
7
- **Documentation:**
8
-
9
- - [Caching](docs/caching.md)
7
+ **Documentation:** [vinext.dev/docs](https://vinext.dev/docs)
10
8
 
11
9
  > **Read the announcement:** [How we rebuilt Next.js with AI in one week](https://blog.cloudflare.com/vinext/)
12
10
 
@@ -122,7 +120,7 @@ Your existing `pages/`, `app/`, `next.config.js`, and `public/` directories work
122
120
 
123
121
  Options: `-p / --port <port>`, `-H / --hostname <host>`, `--turbopack` (accepted, no-op).
124
122
 
125
- `@vinext/cloudflare deploy` options: `--preview`, `--env <name>`, `--name <name>`, `--skip-build`, `--dry-run`, `--experimental-tpr`.
123
+ `@vinext/cloudflare deploy` options: `--preview`, `--env <name>`, `--name <name>`, `--skip-build`, `--dry-run`, `--experimental-traffic-aware-warm-cache`.
126
124
 
127
125
  `vinext init` prompts for a deployment target, defaulting to Cloudflare. Agents must ask the
128
126
  user which target they want, then pass `--platform=cloudflare` or `--platform=node`.
@@ -335,20 +333,22 @@ For TypeScript types, generate them with `wrangler types` and the `env` import w
335
333
 
336
334
  > **Note:** You do not need `getPlatformProxy()`, a custom worker entry with `fetch(request, env)`, or any other workaround. `cloudflare:workers` is the recommended way to access bindings in vinext.
337
335
 
338
- #### Traffic-aware Pre-Rendering (experimental)
336
+ #### Traffic-aware pre-warming (experimental)
339
337
 
340
- TPR queries Cloudflare zone analytics at deploy time to find which pages actually get traffic, pre-renders only those, and uploads them to KV cache. The result is SSG-level latency for popular pages without pre-rendering your entire site.
338
+ Traffic-aware warming queries Cloudflare zone analytics at deploy time to select the routes that actually get traffic. Those routes then go through vinext's standard staged CDN pre-warming flow, including route resolution, cacheability checks, and promotion.
341
339
 
342
340
  ```bash
343
- npx @vinext/cloudflare deploy --experimental-tpr # Pre-render pages covering 90% of traffic
344
- vp exec vinext-cloudflare deploy --experimental-tpr # Same, with Vite+
345
- npx @vinext/cloudflare deploy --experimental-tpr --tpr-coverage 95 # More aggressive coverage
346
- npx @vinext/cloudflare deploy --experimental-tpr --tpr-limit 500 # Cap at 500 pages
347
- npx @vinext/cloudflare deploy --experimental-tpr --tpr-window 48 # Use 48h of analytics
341
+ npx @vinext/cloudflare deploy --experimental-traffic-aware-warm-cache # Pre-warm routes covering 90% of traffic
342
+ vp exec vinext-cloudflare deploy --experimental-traffic-aware-warm-cache # Same, with Vite+
343
+ npx @vinext/cloudflare deploy --experimental-traffic-aware-warm-cache --traffic-aware-coverage 95 # More aggressive coverage
344
+ npx @vinext/cloudflare deploy --experimental-traffic-aware-warm-cache --traffic-aware-limit 500 # Cap at 500 routes
345
+ npx @vinext/cloudflare deploy --experimental-traffic-aware-warm-cache --traffic-aware-window 48 # Use 48h of analytics
348
346
  ```
349
347
 
350
348
  Requires a custom domain (zone analytics are unavailable on `*.workers.dev`) and `CLOUDFLARE_API_TOKEN` with Zone.Analytics read permission.
351
349
 
350
+ The previous `--experimental-tpr` and `--tpr-*` names remain supported as aliases.
351
+
352
352
  #### Custom Vite configuration
353
353
 
354
354
  If you need to customize the Vite config, create a `vite.config.ts`. vinext will merge its config with yours. For Cloudflare Workers deployment with the App Router, configure `@cloudflare/vite-plugin` so the RSC environment runs in workerd:
@@ -598,7 +598,7 @@ Every `next/*` import is shimmed to a Vite-compatible implementation.
598
598
  | Standalone output (`output: 'standalone'`) | ✅ | Generates `dist/standalone` with `server.js`, build artifacts, and runtime deps |
599
599
  | `connection()` | ✅ | Forces dynamic rendering |
600
600
  | `"use cache"` directive | ✅ | File-level and function-level. `cacheLife()` profiles, `cacheTag()`, stale-while-revalidate |
601
- | `instrumentation.ts` | ✅ | `register()` and `onRequestError()` callbacks |
601
+ | `instrumentation.ts` | ✅ | `register()`, `onRequestError()`, and [framework tracing](docs/tracing.mdx) |
602
602
  | Route segment config | 🟡 | `revalidate`, `dynamic`, `dynamicParams`. `runtime` and `preferredRegion` are ignored |
603
603
 
604
604
  ### Configuration
@@ -0,0 +1,25 @@
1
+ # Third-party licenses
2
+
3
+ ## ua-parser-js
4
+
5
+ MIT License
6
+
7
+ Copyright (c) 2012-2021 Faisal Salman <f@faisalman.com>
8
+
9
+ Permission is hereby granted, free of charge, to any person obtaining a copy
10
+ of this software and associated documentation files (the "Software"), to deal
11
+ in the Software without restriction, including without limitation the rights
12
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the Software is
14
+ furnished to do so, subject to the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included in all
17
+ copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
+ SOFTWARE.
@@ -0,0 +1,25 @@
1
+ import "node:module";
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
+ key = keys[i];
13
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
21
+ value: mod,
22
+ enumerable: true
23
+ }) : target, mod));
24
+ //#endregion
25
+ export { __commonJSMin, __toESM };
@@ -53,6 +53,10 @@ export declare const DEFAULT_REMOTE_PATH_DISCOVERY_RETRY_DELAY_MS = 1000;
53
53
  export declare const DEFAULT_REMOTE_PATH_DISCOVERY_PHASE_TIMEOUT_MS = 120000;
54
54
  type PrerenderPathDiscoveryOptions = {
55
55
  root: string;
56
+ /** Additional concrete public paths to resolve through the route graph. */
57
+ candidatePaths?: readonly string[];
58
+ /** Resolve only candidate paths instead of enumerating dynamic route hooks. */
59
+ candidatePathsOnly?: boolean;
56
60
  /** Fully resolved Next.js config. Loaded from disk when omitted. */
57
61
  nextConfig?: ResolvedNextConfig;
58
62
  appDir?: string | null;
@@ -270,6 +270,7 @@ async function collectPagesPaths(options) {
270
270
  }
271
271
  continue;
272
272
  }
273
+ if (!options.enumerateDynamicPaths) continue;
273
274
  if (type === "ssr") continue;
274
275
  if (!options.baseUrl) continue;
275
276
  try {
@@ -319,16 +320,31 @@ async function excludePagesApiWarmPaths(options) {
319
320
  return matchRoute(pagesPathname, apiRoutes) === null;
320
321
  });
321
322
  }
322
- async function resolvePagesWarmRoutePatterns(options) {
323
+ async function resolvePagesWarmRouteMetadata(options) {
323
324
  const pageRoutes = await pagesRouter(options.pagesDir, options.pageExtensions);
324
- return Object.fromEntries(options.paths.flatMap((pathname) => {
325
+ const classifications = /* @__PURE__ */ new Map();
326
+ const dataPaths = [];
327
+ const routePatterns = {};
328
+ for (const pathname of options.paths) {
325
329
  const pagesPathname = options.i18n ? extractLocaleFromUrl(pathname, options.i18n).url : pathname;
326
330
  const match = matchRoute(pagesPathname, pageRoutes);
327
- return match ? [[pathname, {
331
+ if (!match) continue;
332
+ routePatterns[pathname] = {
328
333
  kind: "pages-page",
329
334
  pattern: match.route.pattern
330
- }]] : [];
331
- }));
335
+ };
336
+ let classification = classifications.get(match.route.filePath);
337
+ if (!classification) {
338
+ classification = classifyPagesRoute(match.route.filePath);
339
+ classifications.set(match.route.filePath, classification);
340
+ }
341
+ const { hasServerSideProps, hasStaticProps } = classification;
342
+ if (hasServerSideProps || hasStaticProps) dataPaths.push(pathname);
343
+ }
344
+ return {
345
+ dataPaths,
346
+ routePatterns
347
+ };
332
348
  }
333
349
  function localizePagesPath(pathname, locale, i18n) {
334
350
  if (!i18n || !locale || locale === i18n.defaultLocale) return pathname;
@@ -364,8 +380,6 @@ async function collectAppPaths(options) {
364
380
  const routes = await appRouter(options.appDir, options.pageExtensions);
365
381
  const paths = [];
366
382
  const seen = /* @__PURE__ */ new Set();
367
- const loadingShellPaths = [];
368
- const seenLoadingShellPaths = /* @__PURE__ */ new Set();
369
383
  const routeHandlerPaths = [];
370
384
  const seenRouteHandlerPaths = /* @__PURE__ */ new Set();
371
385
  const fallbackRoutePatterns = [];
@@ -418,20 +432,19 @@ async function collectAppPaths(options) {
418
432
  const { type } = classifyAppRoute(renderEntryPath, route.routePath, route.isDynamic);
419
433
  if (type === "api") continue;
420
434
  }
421
- const hasMainTreeLoadingBoundary = appRouteHasMainTreeLoadingBoundary(route);
422
435
  const addDiscoveredPath = (pathname) => {
423
436
  if (isRouteHandler) {
424
437
  addPath(routeHandlerPaths, seenRouteHandlerPaths, pathname);
425
438
  return;
426
439
  }
427
440
  addPath(paths, seen, pathname);
428
- if (hasMainTreeLoadingBoundary) addPath(loadingShellPaths, seenLoadingShellPaths, pathname);
429
441
  };
430
442
  if (!route.isDynamic) {
431
443
  addDiscoveredPath(route.pattern);
432
444
  addPath(nonDynamicPaths, seenNonDynamicPaths, route.pattern);
433
445
  continue;
434
446
  }
447
+ if (!options.enumerateDynamicPaths) continue;
435
448
  requireNonEmptyStaticParams = options.cacheComponents && !isRouteHandler;
436
449
  try {
437
450
  const generateStaticParams = staticParamsMap[route.pattern];
@@ -502,7 +515,6 @@ async function collectAppPaths(options) {
502
515
  }
503
516
  return {
504
517
  fallbackRoutePatterns,
505
- loadingShellPaths,
506
518
  nonDynamicPaths,
507
519
  paths,
508
520
  routeHandlerPaths
@@ -725,12 +737,8 @@ async function discoverPrerenderPathManifest(options) {
725
737
  const seenPagesPaths = /* @__PURE__ */ new Set();
726
738
  const discoveredPagesDataPaths = [];
727
739
  const seenPagesDataPaths = /* @__PURE__ */ new Set();
728
- const discoveredAppPaths = [];
729
- const seenAppPaths = /* @__PURE__ */ new Set();
730
740
  const discoveredRouteHandlerPaths = [];
731
741
  const seenRouteHandlerPaths = /* @__PURE__ */ new Set();
732
- const discoveredLoadingShellPaths = [];
733
- const seenLoadingShellPaths = /* @__PURE__ */ new Set();
734
742
  const discoveredNonDynamicPathSet = /* @__PURE__ */ new Set();
735
743
  const fallbackRoutePatterns = [];
736
744
  await withPrerenderEndpoints(async () => {
@@ -767,15 +775,12 @@ async function discoverPrerenderPathManifest(options) {
767
775
  appDir,
768
776
  baseUrl,
769
777
  cacheComponents: config.cacheComponents,
778
+ enumerateDynamicPaths: options.candidatePathsOnly !== true,
770
779
  pageExtensions: config.pageExtensions,
771
780
  retryOptions: pathDiscoveryRetryOptions,
772
781
  secretHeaders
773
782
  });
774
- for (const pathname of appPathResult.paths) {
775
- addPath(paths, seen, pathname);
776
- addPath(discoveredAppPaths, seenAppPaths, pathname);
777
- }
778
- for (const pathname of appPathResult.loadingShellPaths) addPath(discoveredLoadingShellPaths, seenLoadingShellPaths, pathname);
783
+ for (const pathname of appPathResult.paths) addPath(paths, seen, pathname);
779
784
  for (const pathname of appPathResult.routeHandlerPaths) addPath(discoveredRouteHandlerPaths, seenRouteHandlerPaths, pathname);
780
785
  for (const pathname of appPathResult.nonDynamicPaths) discoveredNonDynamicPathSet.add(pathname);
781
786
  fallbackRoutePatterns.push(...appPathResult.fallbackRoutePatterns);
@@ -783,6 +788,7 @@ async function discoverPrerenderPathManifest(options) {
783
788
  if (pagesDir) {
784
789
  const pagesPathResult = await collectPagesPaths({
785
790
  baseUrl,
791
+ enumerateDynamicPaths: options.candidatePathsOnly !== true,
786
792
  i18n: config.i18n,
787
793
  pagesDir,
788
794
  pageExtensions: config.pageExtensions,
@@ -801,6 +807,16 @@ async function discoverPrerenderPathManifest(options) {
801
807
  if (prodServer) await new Promise((resolve) => prodServer.server.close(() => resolve()));
802
808
  }
803
809
  });
810
+ for (const publicPathname of options.candidatePaths ?? []) {
811
+ let pathname = normalizePathTrailingSlash(new URL(publicPathname, "http://vinext.local").pathname, false);
812
+ if (config.basePath) {
813
+ if (pathname === config.basePath) pathname = "/";
814
+ else if (pathname.startsWith(`${config.basePath}/`)) pathname = pathname.slice(config.basePath.length);
815
+ else continue;
816
+ }
817
+ addPath(paths, seen, pathname);
818
+ if (pagesDir) addPath(discoveredPagesPaths, seenPagesPaths, pathname);
819
+ }
804
820
  const hasStagedRequestRouting = options.requestRouting === "uncached-stage";
805
821
  const middlewarePath = hasStagedRequestRouting ? findMiddlewareConventionFile(root, appDir, pagesDir, config.pageExtensions) : null;
806
822
  const configuredMatcher = middlewarePath ? extractMiddlewareMatcherConfig(middlewarePath) : void 0;
@@ -816,9 +832,20 @@ async function discoverPrerenderPathManifest(options) {
816
832
  pageExtensions: config.pageExtensions,
817
833
  paths: configuredPagesWarmPaths
818
834
  }) : configuredPagesWarmPaths;
819
- const discoveredPagesDataPathSet = new Set(discoveredPagesDataPaths);
820
835
  const configuredCandidatePaths = paths.filter((pathname) => !excludedWarmPathSet.has(pathname));
821
836
  const configuredRouteHandlerPaths = discoveredRouteHandlerPaths.filter((pathname) => !excludedWarmPathSet.has(pathname));
837
+ const pagesWarmMetadata = pagesDir ? await resolvePagesWarmRouteMetadata({
838
+ i18n: config.i18n,
839
+ pagesDir,
840
+ pageExtensions: config.pageExtensions,
841
+ paths: resolvedPagesWarmPaths
842
+ }) : {
843
+ dataPaths: [],
844
+ routePatterns: {}
845
+ };
846
+ for (const pathname of pagesWarmMetadata.dataPaths) addPath(discoveredPagesDataPaths, seenPagesDataPaths, pathname);
847
+ const discoveredPagesDataPathSet = new Set(discoveredPagesDataPaths);
848
+ const pagesOnlyWarmPaths = resolvedPagesWarmPaths.filter((pathname) => pagesWarmMetadata.routePatterns[pathname] !== void 0);
822
849
  const appOwnedWarmPaths = appDir ? await resolveAppWarmPaths({
823
850
  appDir,
824
851
  i18n: config.i18n,
@@ -828,19 +855,24 @@ async function discoverPrerenderPathManifest(options) {
828
855
  }) : {
829
856
  appPaths: [],
830
857
  appRoutePaths: [],
831
- htmlPaths: discoveredAppPaths,
832
- loadingShellPaths: discoveredLoadingShellPaths,
833
- pagesPaths: resolvedPagesWarmPaths,
834
- routePatterns: pagesDir ? await resolvePagesWarmRoutePatterns({
835
- i18n: config.i18n,
836
- pagesDir,
837
- pageExtensions: config.pageExtensions,
838
- paths: resolvedPagesWarmPaths
839
- }) : {},
840
- rscPaths: discoveredAppPaths
858
+ htmlPaths: pagesOnlyWarmPaths,
859
+ loadingShellPaths: [],
860
+ pagesPaths: pagesOnlyWarmPaths,
861
+ routePatterns: pagesWarmMetadata.routePatterns,
862
+ rscPaths: []
841
863
  };
842
- const warmPaths = appDir ? appOwnedWarmPaths.htmlPaths : resolvedPagesWarmPaths;
843
- const pagesOwnedWarmPaths = appDir ? appOwnedWarmPaths.pagesPaths : resolvedPagesWarmPaths;
864
+ for (const pathname of configuredCandidatePaths) {
865
+ if (appOwnedWarmPaths.routePatterns[pathname] || !routeMayResolveWarmPathSet.has(pathname) && !requestStageMayTerminateWarmPathSet.has(pathname)) continue;
866
+ appOwnedWarmPaths.htmlPaths.push(pathname);
867
+ (appDir ? appOwnedWarmPaths.appPaths : appOwnedWarmPaths.pagesPaths).push(pathname);
868
+ if (appDir && routeMayResolveWarmPathSet.has(pathname)) appOwnedWarmPaths.rscPaths.push(pathname);
869
+ appOwnedWarmPaths.routePatterns[pathname] = {
870
+ kind: appDir ? "app-page" : "pages-page",
871
+ pattern: pathname
872
+ };
873
+ }
874
+ const warmPaths = appOwnedWarmPaths.htmlPaths;
875
+ const pagesOwnedWarmPaths = appOwnedWarmPaths.pagesPaths;
844
876
  const resolvedPagesDataWarmPaths = pagesOwnedWarmPaths.filter((pathname) => discoveredPagesDataPathSet.has(pathname));
845
877
  const pagesDataPaths = resolvedPagesDataWarmPaths.map((pathname) => buildPagesDataHref(config.basePath, config.buildId, localizePagesDataPath(pathname, config.i18n), ""));
846
878
  const routePatterns = annotateCacheabilityProbeSafety(appOwnedWarmPaths.routePatterns, config, routeMayResolveWarmPathSet, requestStageMayTerminateWarmPathSet, (name) => name.trim().toLowerCase() === "cache-control" || options.isResponsePolicyHeader?.(name) === true);
@@ -41,7 +41,7 @@ export type PrerenderRouteResult = {
41
41
  } | {
42
42
  route: string;
43
43
  status: "skipped";
44
- reason: "ssr" | "dynamic" | "no-static-params" | "api" | "internal";
44
+ reason: "ssr" | "dynamic" | "no-static-params" | "empty-static-params" | "api" | "internal";
45
45
  } | {
46
46
  route: string;
47
47
  status: "error";
@@ -708,7 +708,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
708
708
  results.push({
709
709
  route: route.pattern,
710
710
  status: "skipped",
711
- reason: "no-static-params"
711
+ reason: "empty-static-params"
712
712
  });
713
713
  continue;
714
714
  }
@@ -25,8 +25,8 @@ export type CdnCacheAdapterCapabilities = {
25
25
  * variants when this guarantee is present.
26
26
  */
27
27
  responseVary?: "verbatim";
28
- /** Warm by observing after-render `X-Vinext-Cache` admission from Response Store. */
29
- warmup?: "response-store";
28
+ /** Warm by observing framework `X-Vinext-Cache` admission instead of an edge-cache header. */
29
+ warmup?: "data-cache" | "response-store";
30
30
  /**
31
31
  * Rewrites and other request routing run before the shared response stage,
32
32
  * and the resolved response-stage invocation participates in cache identity.
@@ -81,7 +81,7 @@ export type CacheAdapterDescriptor<O extends Record<string, unknown> = Record<st
81
81
  };
82
82
  export declare function hasVerbatimResponseVary(cache?: VinextCacheConfig | null): boolean;
83
83
  export declare function supportsCanonicalRscWarmup(cache?: VinextCacheConfig | null): boolean;
84
- export declare function usesVinextCacheWarmupStatus(cache?: VinextCacheConfig | null): boolean;
84
+ export declare function cacheWarmupStatusSource(cache?: VinextCacheConfig | null): "cloudflare" | "data-cache" | "vinext";
85
85
  export declare function hasUncachedRequestRouting(cache?: VinextCacheConfig | null): boolean;
86
86
  export declare function hasBuildIdentityResponseHeader(cache?: VinextCacheConfig | null): boolean;
87
87
  export declare function requiresRouteCacheabilityProbeManifest(cache?: VinextCacheConfig | null): boolean;
@@ -22,14 +22,16 @@ function hasVerbatimResponseVary(cache) {
22
22
  function supportsCanonicalRscWarmup(cache) {
23
23
  return hasVerbatimResponseVary(cache);
24
24
  }
25
- function usesVinextCacheWarmupStatus(cache) {
26
- return cache?.cdn?.capabilities?.warmup === "response-store";
25
+ function cacheWarmupStatusSource(cache) {
26
+ if (cache?.cdn?.capabilities?.warmup === "response-store") return "vinext";
27
+ if (!cache?.cdn?.adapter && cache?.data?.capabilities?.warmup === "data-cache") return "data-cache";
28
+ return "cloudflare";
27
29
  }
28
30
  function hasUncachedRequestRouting(cache) {
29
31
  return cache?.cdn?.capabilities?.requestRouting === "uncached-stage";
30
32
  }
31
33
  function hasBuildIdentityResponseHeader(cache) {
32
- return cache?.cdn?.capabilities?.buildIdentity === "response-header";
34
+ return cache?.cdn?.capabilities?.buildIdentity === "response-header" || !cache?.cdn?.adapter && cache?.data?.capabilities?.buildIdentity === "response-header";
33
35
  }
34
36
  function requiresRouteCacheabilityProbeManifest(cache) {
35
37
  return cache?.cdn?.capabilities?.routeCacheability === "probe-manifest";
@@ -79,6 +81,7 @@ function inlineOptions(adapter, options) {
79
81
  function generateCacheAdaptersModule(cache) {
80
82
  const data = cache?.data;
81
83
  const cdn = cache?.cdn;
84
+ const dataProvidesBuildIdentity = !cdn?.adapter && data?.capabilities?.buildIdentity === "response-header";
82
85
  if (!data?.adapter && !cdn?.adapter) return [
83
86
  "// vinext: no cache.cdn/cache.data adapter configured — registration is a no-op.",
84
87
  "export function registerConfiguredCacheAdapters() {}",
@@ -92,16 +95,20 @@ function generateCacheAdaptersModule(cache) {
92
95
  if (cdn?.adapter) {
93
96
  lines.push(`import __vinextCdnAdapterFactory from ${JSON.stringify(cdn.adapter)};`);
94
97
  lines.push(`import { registerCdnCacheAdapter } from "vinext/shims/cdn-cache-state";`);
95
- }
98
+ } else if (dataProvidesBuildIdentity) lines.push(`import { DefaultCdnCacheAdapter } from "vinext/shims/cdn-cache";`, `import { registerCdnCacheAdapter } from "vinext/shims/cdn-cache-state";`);
96
99
  lines.push("", "// A factory that throws (e.g. a missing binding on an incompatible runtime)", "// is logged and skipped so the default handler stays in place.", "function __vinextFormatAdapterError(error) {", " if (error instanceof Error && error.message) return error.message;", " try {", " return String(error);", " } catch {", " return '<unknown error>';", " }", "}", "", "let __vinextCacheAdaptersRegistered = false;", "", "export function registerConfiguredCacheAdapters(env) {", " if (typeof process !== 'undefined' && process.env?.__VINEXT_PRERENDER_PATH_DISCOVERY === '1') return;", " if (__vinextCacheAdaptersRegistered) return;", " __vinextCacheAdaptersRegistered = true;");
97
- if (data?.adapter) lines.push(" try {", ` registerDataCacheHandler(() => __vinextDataAdapterFactory({ env, options: ${inlineOptions(data.adapter, data.options)} }));`, " } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured data cache adapter; using the default handler.\\n\" + __vinextFormatAdapterError(error));", " }");
100
+ if (data?.adapter) {
101
+ lines.push(" try {", ` registerDataCacheHandler(() => __vinextDataAdapterFactory({ env, options: ${inlineOptions(data.adapter, data.options)} }));`);
102
+ if (dataProvidesBuildIdentity) lines.push(" registerCdnCacheAdapter(() => new DefaultCdnCacheAdapter(", " process.env.__VINEXT_RSC_BUILD_IDENTITY || process.env.__VINEXT_BUILD_ID,", " ));");
103
+ lines.push(" } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured data cache adapter; using the default handler.\\n\" + __vinextFormatAdapterError(error));", " }");
104
+ }
98
105
  if (cdn?.adapter) lines.push(" try {", ` registerCdnCacheAdapter(() => __vinextCdnAdapterFactory({ env, options: ${inlineOptions(cdn.adapter, cdn.options)} }));`, " } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured CDN cache adapter; using the default adapter.\\n\" + __vinextFormatAdapterError(error));", " }");
99
106
  lines.push("}", "");
100
107
  return lines.join("\n");
101
108
  }
102
109
  /** Generate request-stage registration without importing a configured data adapter. */
103
110
  function generateCdnCacheAdapterModule(cache) {
104
- return `${generateCacheAdaptersModule(cache?.cdn ? { cdn: cache.cdn } : void 0)}export const hasConfiguredDataCache = ${Boolean(cache?.data?.adapter)};\n`;
111
+ return `${generateCacheAdaptersModule(cache?.cdn ? { cdn: cache.cdn } : void 0)}export const hasConfiguredDataCache = ${Boolean(cache?.data?.adapter)};\nexport const configuredCdnCacheAdapterOptions = ${inlineOptions(cache?.cdn?.adapter ?? "cdn", cache?.cdn?.options)};\n`;
105
112
  }
106
113
  //#endregion
107
- export { VINEXT_CACHE_CONFIG_PLUGIN_PROPERTY, VIRTUAL_CACHE_ADAPTERS, VIRTUAL_CDN_CACHE_ADAPTER, findVinextCacheConfigInPlugins, generateCacheAdaptersModule, generateCdnCacheAdapterModule, hasBuildIdentityResponseHeader, hasUncachedRequestRouting, hasVerbatimResponseVary, isConfiguredCdnResponsePolicyHeader, loadVinextCacheConfigFromViteConfig, requiresRouteCacheabilityProbeManifest, supportsCanonicalRscWarmup, usesVinextCacheWarmupStatus };
114
+ export { VINEXT_CACHE_CONFIG_PLUGIN_PROPERTY, VIRTUAL_CACHE_ADAPTERS, VIRTUAL_CDN_CACHE_ADAPTER, cacheWarmupStatusSource, findVinextCacheConfigInPlugins, generateCacheAdaptersModule, generateCdnCacheAdapterModule, hasBuildIdentityResponseHeader, hasUncachedRequestRouting, hasVerbatimResponseVary, isConfiguredCdnResponsePolicyHeader, loadVinextCacheConfigFromViteConfig, requiresRouteCacheabilityProbeManifest, supportsCanonicalRscWarmup };
package/dist/check.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { __toESM } from "./_virtual/_rolldown/runtime.js";
1
2
  import path from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
3
  import { detectPackageManager, findDir } from "./utils/project.js";
4
+ import { require_ignore } from "./deps/.pnpm/ignore@5.3.2/deps/ignore/index.js";
3
5
  import fs from "node:fs";
4
6
  import { parseAst } from "vite";
5
7
  //#region src/check.ts
@@ -9,6 +11,7 @@ import { parseAst } from "vite";
9
11
  * Scans an existing Next.js app and produces a compatibility report
10
12
  * showing what will work, what needs changes, and an overall score.
11
13
  */
14
+ var import_ignore = /* @__PURE__ */ __toESM(require_ignore(), 1);
12
15
  /** Sort order for statuses: unsupported first, then partial, then supported. */
13
16
  const STATUS_ORDER = {
14
17
  unsupported: 0,
@@ -372,25 +375,69 @@ const LIBRARY_SUPPORT = {
372
375
  detail: "works with D1 on Cloudflare Workers"
373
376
  }
374
377
  };
375
- /**
376
- * Recursively find all source files in a directory.
377
- */
378
- function findSourceFiles(dir, extensions = [
378
+ const IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([
379
+ "node_modules",
380
+ ".next",
381
+ "dist",
382
+ ".git"
383
+ ]);
384
+ const SOURCE_EXTENSIONS = [
379
385
  ".ts",
380
386
  ".tsx",
381
387
  ".js",
382
388
  ".jsx",
383
389
  ".mjs"
384
- ]) {
390
+ ];
391
+ function readGitignoreRule(dir) {
392
+ const gitignore = path.join(dir, ".gitignore");
393
+ let stat;
394
+ try {
395
+ stat = fs.lstatSync(gitignore);
396
+ } catch {
397
+ return;
398
+ }
399
+ if (!stat.isFile()) return;
400
+ return {
401
+ dir,
402
+ matcher: (0, import_ignore.default)({ ignorecase: false }).add(fs.readFileSync(gitignore, "utf-8"))
403
+ };
404
+ }
405
+ function ancestorGitignoreRules(root, dir) {
406
+ const rules = [];
407
+ let current = root;
408
+ for (const segment of path.relative(root, dir).split("/")) {
409
+ const rule = readGitignoreRule(current);
410
+ if (rule) rules.push(rule);
411
+ current = path.join(current, segment);
412
+ if (isGitignored(current, true, rules)) break;
413
+ }
414
+ return rules;
415
+ }
416
+ function isGitignored(fullPath, isDirectory, rules) {
417
+ let ignored = false;
418
+ for (const rule of rules) {
419
+ const relative = path.relative(rule.dir, fullPath) + (isDirectory ? "/" : "");
420
+ const result = rule.matcher.test(relative);
421
+ if (result.ignored) ignored = true;
422
+ else if (result.unignored) ignored = false;
423
+ }
424
+ return ignored;
425
+ }
426
+ /**
427
+ * Recursively find all source files in a directory.
428
+ */
429
+ function findSourceFiles(dir, extensions = SOURCE_EXTENSIONS, inherited = []) {
385
430
  const results = [];
386
431
  if (!fs.existsSync(dir)) return results;
432
+ const localRule = readGitignoreRule(dir);
433
+ const rules = localRule ? [...inherited, localRule] : inherited;
387
434
  const entries = fs.readdirSync(dir, { withFileTypes: true });
388
435
  for (const entry of entries) {
389
436
  const fullPath = path.join(dir, entry.name);
390
- if (entry.isDirectory()) {
391
- if (entry.name === "node_modules" || entry.name === ".next" || entry.name === "dist" || entry.name === ".git") continue;
392
- results.push(...findSourceFiles(fullPath, extensions));
393
- } else if (extensions.some((ext) => entry.name.endsWith(ext))) results.push(fullPath);
437
+ if (entry.isDirectory() && IGNORED_DIRECTORIES.has(entry.name)) continue;
438
+ if (isGitignored(fullPath, entry.isDirectory(), rules)) continue;
439
+ if (entry.isDirectory()) results.push(...findSourceFiles(fullPath, extensions, rules));
440
+ else if (extensions.some((ext) => entry.name.endsWith(ext))) results.push(fullPath);
394
441
  }
395
442
  return results;
396
443
  }
@@ -400,12 +447,13 @@ function findSourceFiles(dir, extensions = [
400
447
  * rather than bundled into the vinext application, so reporting their imports
401
448
  * or CJS globals as migration blockers produces false positives.
402
449
  */
450
+ function isRuntimeSourceFile(file) {
451
+ const basename = path.basename(file);
452
+ const isTestRunnerConfig = /^(?:jest|playwright|vitest)\.config\.[cm]?[jt]sx?$/.test(basename);
453
+ return !/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(basename) && !isTestRunnerConfig;
454
+ }
403
455
  function findRuntimeSourceFiles(root) {
404
- return findSourceFiles(root).filter((file) => {
405
- const basename = path.basename(file);
406
- const isTestRunnerConfig = /^(?:jest|playwright|vitest)\.config\.[cm]?[jt]sx?$/.test(basename);
407
- return !/\.(?:test|spec)\.[cm]?[jt]sx?$/.test(basename) && !isTestRunnerConfig;
408
- });
456
+ return findSourceFiles(root).filter(isRuntimeSourceFile);
409
457
  }
410
458
  function isIdentStart(c) {
411
459
  return c >= "a" && c <= "z" || c >= "A" && c <= "Z" || c === "_" || c === "$";
@@ -839,6 +887,14 @@ function checkLibraries(root) {
839
887
  */
840
888
  function checkConventions(root) {
841
889
  const items = [];
890
+ const sourceFiles = findSourceFiles(root);
891
+ const routeFiles = (dir) => {
892
+ const files = sourceFiles.filter((file) => file.startsWith(`${dir}/`));
893
+ if (files.length || !fs.lstatSync(dir).isSymbolicLink()) return files;
894
+ const rules = ancestorGitignoreRules(root, dir);
895
+ if (isGitignored(dir, true, rules)) return [];
896
+ return findSourceFiles(dir, SOURCE_EXTENSIONS, rules);
897
+ };
842
898
  const pagesDir = findDir(root, "pages", "src/pages");
843
899
  const appDirPath = findDir(root, "app", "src/app");
844
900
  const hasProxy = fs.existsSync(path.join(root, "proxy.ts")) || fs.existsSync(path.join(root, "proxy.js"));
@@ -849,7 +905,7 @@ function checkConventions(root) {
849
905
  name: isSrc ? "Pages Router (src/pages/)" : "Pages Router (pages/)",
850
906
  status: "supported"
851
907
  });
852
- const pageFiles = findSourceFiles(pagesDir);
908
+ const pageFiles = routeFiles(pagesDir);
853
909
  const pages = pageFiles.filter((f) => !f.includes("/api/") && !f.includes("_app") && !f.includes("_document") && !f.includes("_error"));
854
910
  const apiRoutes = pageFiles.filter((f) => f.includes("/api/"));
855
911
  items.push({
@@ -875,7 +931,7 @@ function checkConventions(root) {
875
931
  name: isSrc ? "App Router (src/app/)" : "App Router (app/)",
876
932
  status: "supported"
877
933
  });
878
- const appFiles = findSourceFiles(appDirPath);
934
+ const appFiles = routeFiles(appDirPath);
879
935
  const pages = appFiles.filter((f) => isAppRouterFile(f, "page"));
880
936
  const layouts = appFiles.filter((f) => isAppRouterFile(f, "layout"));
881
937
  const routes = appFiles.filter((f) => f.endsWith("route.tsx") || f.endsWith("route.ts") || f.endsWith("route.js"));
@@ -928,11 +984,11 @@ function checkConventions(root) {
928
984
  detail: "required for Vite — vinext init will add it automatically"
929
985
  });
930
986
  }
931
- const allSourceFiles = findRuntimeSourceFiles(root);
987
+ const runtimeSourceFiles = sourceFiles.filter(isRuntimeSourceFile);
932
988
  const viewTransitionRegex = /import\s+\{[^}]*\bViewTransition\b[^}]*\}\s+from\s+['"]react['"]/;
933
989
  const viewTransitionFiles = [];
934
990
  const cjsGlobalFiles = [];
935
- for (const file of allSourceFiles) {
991
+ for (const file of runtimeSourceFiles) {
936
992
  const content = fs.readFileSync(file, "utf-8");
937
993
  const rel = path.relative(root, file);
938
994
  if (viewTransitionRegex.test(content)) viewTransitionFiles.push(rel);
@@ -1,5 +1,5 @@
1
- import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
2
1
  import { isNavigationSignalError } from "../utils/navigation-signal.js";
2
+ import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
3
3
  import { VINEXT_ORIGINAL_STACK_TRACE_ENDPOINT } from "../utils/dev-stack-sourcemap-endpoint.js";
4
4
  import { dismissOverlay, expandOverlay, getOverlaySnapshot, minimizeOverlay, reportToOverlay, setOverlayIndex, subscribeOverlay, updateOverlayErrorStack } from "./dev-error-overlay-store.js";
5
5
  import { Fragment, useEffect, useMemo, useState, useSyncExternalStore } from "react";
@@ -321,6 +321,10 @@ export type ResolvedNextConfig = {
321
321
  resolveExtensions: string[] | null;
322
322
  serverResolveExtensions: string[] | null;
323
323
  instrumentationClientInject: string[];
324
+ /** Route manifest injected by Next.js-compatible instrumentation plugins. */
325
+ instrumentationClientRouteManifest: string | undefined;
326
+ /** Server globals injected into instrumentation.ts by wrapped webpack configs. */
327
+ instrumentationServerValueInjections: Record<string, unknown>;
324
328
  cacheComponents: boolean;
325
329
  appNavFailHandling: boolean;
326
330
  /**