vinext 1.0.0 → 1.1.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 (263) hide show
  1. package/README.md +72 -1
  2. package/THIRD_PARTY_LICENSES.md +26 -0
  3. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  4. package/dist/build/app-page-static-eligibility.js +82 -0
  5. package/dist/build/lifecycle.js +10 -10
  6. package/dist/build/pages-client-assets-module.js +6 -1
  7. package/dist/build/precompress.js +1 -1
  8. package/dist/build/prerender-paths.js +6 -85
  9. package/dist/build/prerender.d.ts +8 -1
  10. package/dist/build/prerender.js +167 -46
  11. package/dist/build/run-prerender.js +4 -3
  12. package/dist/build/server-entry.d.ts +2 -0
  13. package/dist/build/server-entry.js +7 -1
  14. package/dist/build/server-manifest.d.ts +7 -0
  15. package/dist/build/server-manifest.js +11 -1
  16. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  17. package/dist/cache/cache-adapters-virtual.js +3 -3
  18. package/dist/client/browser-globals.d.ts +4 -0
  19. package/dist/client/browser-globals.js +5 -0
  20. package/dist/client/navigation-runtime.d.ts +11 -1
  21. package/dist/client/navigation-runtime.js +3 -3
  22. package/dist/config/config-matchers.js +3 -1
  23. package/dist/config/dotenv.js +14 -3
  24. package/dist/config/next-config.d.ts +7 -0
  25. package/dist/config/next-config.js +18 -3
  26. package/dist/entries/app-rsc-entry.d.ts +2 -0
  27. package/dist/entries/app-rsc-entry.js +67 -45
  28. package/dist/index.d.ts +4 -1
  29. package/dist/index.js +200 -100
  30. package/dist/init-cloudflare.d.ts +1 -1
  31. package/dist/init-cloudflare.js +6 -6
  32. package/dist/init-platform.js +1 -1
  33. package/dist/init.js +4 -2
  34. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  35. package/dist/plugins/cache-flight-codec.js +68 -0
  36. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  37. package/dist/plugins/commonjs-esm-facade.js +80 -0
  38. package/dist/plugins/commonjs-syntax.d.ts +16 -0
  39. package/dist/plugins/commonjs-syntax.js +22 -0
  40. package/dist/plugins/fonts.d.ts +8 -11
  41. package/dist/plugins/fonts.js +71 -34
  42. package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
  43. package/dist/plugins/ignore-dynamic-requests.js +54 -3
  44. package/dist/plugins/import-meta-url.js +6 -6
  45. package/dist/plugins/og-asset-ownership.d.ts +2 -0
  46. package/dist/plugins/og-asset-ownership.js +24 -13
  47. package/dist/plugins/og-assets.d.ts +18 -0
  48. package/dist/plugins/og-assets.js +50 -8
  49. package/dist/plugins/og-harfbuzz.js +38 -27
  50. package/dist/plugins/optimize-imports.js +2 -1
  51. package/dist/plugins/require-context.d.ts +1 -0
  52. package/dist/plugins/require-context.js +28 -1
  53. package/dist/plugins/scan-build-css.d.ts +12 -0
  54. package/dist/plugins/scan-build-css.js +39 -0
  55. package/dist/plugins/strip-server-exports.d.ts +2 -0
  56. package/dist/plugins/strip-server-exports.js +3 -1
  57. package/dist/plugins/transform-result.d.ts +18 -0
  58. package/dist/plugins/transform-result.js +23 -2
  59. package/dist/plugins/typeof-window.d.ts +10 -0
  60. package/dist/plugins/typeof-window.js +33 -9
  61. package/dist/routing/app-route-graph.d.ts +0 -1
  62. package/dist/routing/app-route-graph.js +2 -4
  63. package/dist/routing/app-route-ids.d.ts +3 -0
  64. package/dist/routing/app-route-ids.js +6 -0
  65. package/dist/routing/file-matcher.d.ts +1 -0
  66. package/dist/routing/file-matcher.js +1 -1
  67. package/dist/server/api-handler.js +17 -7
  68. package/dist/server/app-bfcache-id.d.ts +1 -0
  69. package/dist/server/app-bfcache-id.js +7 -1
  70. package/dist/server/app-bfcache-identity.js +1 -2
  71. package/dist/server/app-browser-entry.js +15 -9
  72. package/dist/server/app-browser-history-controller.d.ts +2 -0
  73. package/dist/server/app-browser-history-controller.js +8 -0
  74. package/dist/server/app-browser-hydration.d.ts +1 -1
  75. package/dist/server/app-browser-hydration.js +2 -2
  76. package/dist/server/app-browser-interception-context.js +26 -2
  77. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  78. package/dist/server/app-browser-navigation-controller.js +94 -11
  79. package/dist/server/app-browser-state.js +1 -1
  80. package/dist/server/app-browser-stream.d.ts +1 -1
  81. package/dist/server/app-fallback-renderer.d.ts +2 -0
  82. package/dist/server/app-fallback-renderer.js +1 -0
  83. package/dist/server/app-history-state.d.ts +3 -1
  84. package/dist/server/app-history-state.js +9 -5
  85. package/dist/server/app-middleware.js +2 -1
  86. package/dist/server/app-optimistic-routing.js +1 -1
  87. package/dist/server/app-page-boundary-render.d.ts +5 -0
  88. package/dist/server/app-page-boundary-render.js +6 -4
  89. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  90. package/dist/server/app-page-cache-finalizer.js +41 -7
  91. package/dist/server/app-page-cache-render.d.ts +18 -0
  92. package/dist/server/app-page-cache-render.js +65 -44
  93. package/dist/server/app-page-cache.d.ts +5 -0
  94. package/dist/server/app-page-cache.js +27 -7
  95. package/dist/server/app-page-dispatch.d.ts +9 -1
  96. package/dist/server/app-page-dispatch.js +47 -30
  97. package/dist/server/app-page-element-builder.d.ts +7 -0
  98. package/dist/server/app-page-element-builder.js +27 -42
  99. package/dist/server/app-page-execution.d.ts +15 -12
  100. package/dist/server/app-page-execution.js +30 -40
  101. package/dist/server/app-page-head.d.ts +5 -0
  102. package/dist/server/app-page-head.js +9 -3
  103. package/dist/server/app-page-probe.d.ts +0 -109
  104. package/dist/server/app-page-probe.js +3 -136
  105. package/dist/server/app-page-render-identity.d.ts +0 -1
  106. package/dist/server/app-page-render-identity.js +1 -1
  107. package/dist/server/app-page-render-observation.js +2 -2
  108. package/dist/server/app-page-render.d.ts +13 -5
  109. package/dist/server/app-page-render.js +219 -118
  110. package/dist/server/app-page-request.d.ts +0 -1
  111. package/dist/server/app-page-request.js +1 -2
  112. package/dist/server/app-page-response.d.ts +4 -3
  113. package/dist/server/app-page-response.js +4 -3
  114. package/dist/server/app-page-route-wiring.d.ts +17 -5
  115. package/dist/server/app-page-route-wiring.js +55 -33
  116. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  117. package/dist/server/app-page-rsc-render-status.js +54 -0
  118. package/dist/server/app-page-search-params-observation.js +1 -1
  119. package/dist/server/app-page-stream.d.ts +15 -8
  120. package/dist/server/app-page-stream.js +7 -1
  121. package/dist/server/app-page-tracing.js +2 -1
  122. package/dist/server/app-pages-bridge.js +3 -2
  123. package/dist/server/app-render-abort-error.d.ts +3 -0
  124. package/dist/server/app-render-abort-error.js +8 -0
  125. package/dist/server/app-request-stage-dispatch.js +1 -1
  126. package/dist/server/app-request-stage-independent-entry.js +8 -11
  127. package/dist/server/app-response-header-provenance.d.ts +2 -0
  128. package/dist/server/app-response-header-provenance.js +10 -4
  129. package/dist/server/app-route-handler-cache.d.ts +2 -1
  130. package/dist/server/app-route-handler-cache.js +11 -7
  131. package/dist/server/app-route-handler-dispatch.js +11 -4
  132. package/dist/server/app-route-handler-execution.d.ts +9 -1
  133. package/dist/server/app-route-handler-execution.js +28 -13
  134. package/dist/server/app-route-handler-policy.js +2 -2
  135. package/dist/server/app-route-handler-response.d.ts +1 -1
  136. package/dist/server/app-route-handler-response.js +14 -5
  137. package/dist/server/app-router-entry.d.ts +2 -1
  138. package/dist/server/app-router-entry.js +8 -12
  139. package/dist/server/app-rsc-errors.d.ts +0 -1
  140. package/dist/server/app-rsc-errors.js +2 -6
  141. package/dist/server/app-rsc-handler.d.ts +5 -0
  142. package/dist/server/app-rsc-handler.js +229 -102
  143. package/dist/server/app-rsc-request-normalization.d.ts +4 -2
  144. package/dist/server/app-rsc-request-normalization.js +7 -4
  145. package/dist/server/app-rsc-response-finalizer.js +4 -1
  146. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  147. package/dist/server/app-rsc-response-stage.js +6 -4
  148. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  149. package/dist/server/app-rsc-route-matching.js +37 -20
  150. package/dist/server/app-server-action-execution.d.ts +2 -1
  151. package/dist/server/app-server-action-execution.js +1 -1
  152. package/dist/server/app-ssr-entry.d.ts +3 -2
  153. package/dist/server/app-ssr-entry.js +9 -7
  154. package/dist/server/app-ssr-search-params-gate.js +1 -1
  155. package/dist/server/app-ssr-stream.d.ts +6 -1
  156. package/dist/server/app-ssr-stream.js +35 -16
  157. package/dist/server/app-worker-stages.d.ts +2 -2
  158. package/dist/server/app-worker-stages.js +3 -3
  159. package/dist/server/cache-control.js +3 -11
  160. package/dist/server/cacheability-request.js +56 -52
  161. package/dist/server/config-headers.js +3 -1
  162. package/dist/server/dev-server.js +23 -5
  163. package/dist/server/headers.d.ts +16 -0
  164. package/dist/server/headers.js +19 -1
  165. package/dist/server/http-error-responses.js +1 -0
  166. package/dist/server/image-optimization.d.ts +16 -0
  167. package/dist/server/image-optimization.js +26 -6
  168. package/dist/server/isr-cache.d.ts +2 -0
  169. package/dist/server/isr-cache.js +8 -3
  170. package/dist/server/metadata-route-response.js +94 -37
  171. package/dist/server/middleware-matcher-pattern.js +8 -4
  172. package/dist/server/middleware-response-headers.js +2 -0
  173. package/dist/server/multi-stage.d.ts +8 -0
  174. package/dist/server/navigation-planner.js +1 -1
  175. package/dist/server/node-response-signal.d.ts +16 -0
  176. package/dist/server/node-response-signal.js +26 -0
  177. package/dist/server/open-redirect.d.ts +47 -0
  178. package/dist/server/open-redirect.js +74 -1
  179. package/dist/server/pages-api-route.js +8 -2
  180. package/dist/server/pages-asset-tags.d.ts +1 -0
  181. package/dist/server/pages-asset-tags.js +73 -22
  182. package/dist/server/pages-client-assets.d.ts +2 -0
  183. package/dist/server/pages-page-data.d.ts +6 -1
  184. package/dist/server/pages-page-data.js +71 -65
  185. package/dist/server/pages-page-handler.js +50 -15
  186. package/dist/server/pages-page-response.js +3 -1
  187. package/dist/server/pages-request-pipeline.d.ts +2 -1
  188. package/dist/server/pages-request-pipeline.js +20 -5
  189. package/dist/server/pages-request-stage-entry.js +14 -8
  190. package/dist/server/prerender-manifest.d.ts +6 -0
  191. package/dist/server/prerender-manifest.js +1 -1
  192. package/dist/server/prod-server.d.ts +8 -7
  193. package/dist/server/prod-server.js +152 -78
  194. package/dist/server/request-pipeline.d.ts +20 -8
  195. package/dist/server/request-pipeline.js +21 -7
  196. package/dist/server/response-compression.d.ts +43 -0
  197. package/dist/server/response-compression.js +111 -0
  198. package/dist/server/response-stage-cacheability.js +1 -1
  199. package/dist/server/seed-cache.js +10 -7
  200. package/dist/server/socket-error-backstop.d.ts +14 -0
  201. package/dist/server/socket-error-backstop.js +27 -4
  202. package/dist/server/worker-revalidation-context.d.ts +2 -1
  203. package/dist/server/worker-revalidation-context.js +1 -0
  204. package/dist/server/workers-tracing.d.ts +17 -0
  205. package/dist/server/workers-tracing.js +48 -8
  206. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  207. package/dist/shims/cache-adapter-instantiate.js +118 -0
  208. package/dist/shims/cache-callable-runtime.d.ts +2 -40
  209. package/dist/shims/cache-callable-runtime.js +50 -168
  210. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  211. package/dist/shims/cache-flight-arguments.js +56 -0
  212. package/dist/shims/cache-request-state.d.ts +18 -14
  213. package/dist/shims/cache-request-state.js +33 -21
  214. package/dist/shims/cache-runtime.d.ts +6 -19
  215. package/dist/shims/cache-runtime.js +168 -226
  216. package/dist/shims/cache.d.ts +3 -2
  217. package/dist/shims/cache.js +8 -5
  218. package/dist/shims/cacheability-classification.d.ts +8 -1
  219. package/dist/shims/cacheability-classification.js +2 -2
  220. package/dist/shims/cdn-cache.d.ts +10 -1
  221. package/dist/shims/cdn-cache.js +16 -9
  222. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  223. package/dist/shims/error-boundary-navigation.js +19 -1
  224. package/dist/shims/error-boundary.d.ts +10 -10
  225. package/dist/shims/error-boundary.js +26 -7
  226. package/dist/shims/error.d.ts +4 -18
  227. package/dist/shims/error.js +17 -10
  228. package/dist/shims/error.react-server.d.ts +4 -6
  229. package/dist/shims/error.react-server.js +4 -1
  230. package/dist/shims/fetch-cache.d.ts +6 -0
  231. package/dist/shims/fetch-cache.js +23 -4
  232. package/dist/shims/form.js +1 -1
  233. package/dist/shims/headers.d.ts +19 -69
  234. package/dist/shims/headers.js +82 -183
  235. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  236. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  237. package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
  238. package/dist/shims/internal/cache-context-accessor.js +15 -0
  239. package/dist/shims/internal/headers-state.d.ts +73 -0
  240. package/dist/shims/internal/headers-state.js +157 -0
  241. package/dist/shims/metadata.js +3 -3
  242. package/dist/shims/navigation-errors.d.ts +6 -0
  243. package/dist/shims/navigation-errors.js +11 -1
  244. package/dist/shims/navigation.d.ts +7 -0
  245. package/dist/shims/navigation.js +16 -6
  246. package/dist/shims/request-context.d.ts +9 -0
  247. package/dist/shims/request-state-types.d.ts +2 -1
  248. package/dist/shims/root-params.js +1 -1
  249. package/dist/shims/server.js +52 -2
  250. package/dist/shims/thenable-params.d.ts +4 -0
  251. package/dist/shims/thenable-params.js +25 -3
  252. package/dist/shims/unified-request-context.d.ts +1 -1
  253. package/dist/shims/unified-request-context.js +1 -0
  254. package/dist/utils/encode-cache-tag.d.ts +1 -0
  255. package/dist/utils/encode-cache-tag.js +11 -1
  256. package/dist/utils/mdx-scan.d.ts +5 -0
  257. package/dist/utils/mdx-scan.js +8 -1
  258. package/dist/utils/regex-safety.d.ts +10 -0
  259. package/dist/utils/regex-safety.js +70 -18
  260. package/dist/utils/vite-cli-invocation.js +8 -1
  261. package/package.json +8 -4
  262. package/dist/server/metadata-route-cache-policy.d.ts +0 -5
  263. package/dist/server/metadata-route-cache-policy.js +0 -6
@@ -1,7 +1,19 @@
1
1
  import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
2
  import fs from "node:fs";
3
- import { parseEnv } from "node:util";
4
3
  //#region src/config/dotenv.ts
4
+ const DOTENV_LINE = /^\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?$/gm;
5
+ function parseDotenv(content) {
6
+ const parsed = {};
7
+ const lines = content.replace(/\r\n?/g, "\n");
8
+ for (const match of lines.matchAll(DOTENV_LINE)) {
9
+ let value = (match[2] ?? "").trim();
10
+ const quote = value[0];
11
+ value = value.replace(/^(['"`])([\s\S]*)\1$/gm, "$2");
12
+ if (quote === "\"") value = value.replace(/\\n/g, "\n").replace(/\\r/g, "\r");
13
+ parsed[match[1]] = value;
14
+ }
15
+ return parsed;
16
+ }
5
17
  /**
6
18
  * Next.js-compatible dotenv lookup order (highest priority first).
7
19
  */
@@ -42,8 +54,7 @@ function loadDotenv({ root, mode, processEnv = process.env }) {
42
54
  for (const relativeFile of getDotenvFiles(mode)) {
43
55
  const filePath = path.join(root, relativeFile);
44
56
  if (!fs.existsSync(filePath)) continue;
45
- const fileContent = fs.readFileSync(filePath, "utf-8");
46
- const expanded = expandEnv(parseEnv(fileContent), processEnv);
57
+ const expanded = expandEnv(parseDotenv(fs.readFileSync(filePath, "utf-8")), processEnv);
47
58
  for (const [key, value] of Object.entries(expanded)) {
48
59
  if (processEnv[key] !== void 0) continue;
49
60
  processEnv[key] = value;
@@ -111,6 +111,11 @@ export type NextConfig = {
111
111
  crossOrigin?: "anonymous" | "use-credentials";
112
112
  /** Whether to add trailing slashes */
113
113
  trailingSlash?: boolean;
114
+ /**
115
+ * Compress responses from the Node production server. Defaults to true.
116
+ * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/compress
117
+ */
118
+ compress?: boolean;
114
119
  /** Keep the original request URL visible to middleware/proxy. */
115
120
  skipProxyUrlNormalize?: boolean;
116
121
  /** @deprecated Use `skipProxyUrlNormalize` instead. */
@@ -312,6 +317,8 @@ export type ResolvedNextConfig = {
312
317
  */
313
318
  assetPrefix: string;
314
319
  trailingSlash: boolean;
320
+ /** Whether the Node production server compresses responses (`compress`, default true). */
321
+ compress: boolean;
315
322
  skipProxyUrlNormalize: boolean;
316
323
  typescript: {
317
324
  tsconfigPath?: string;
@@ -1,5 +1,5 @@
1
1
  import path, { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
2
- import { normalizePageExtensions } from "../routing/file-matcher.js";
2
+ import { DEFAULT_PAGE_EXTENSIONS, normalizePageExtensions } from "../routing/file-matcher.js";
3
3
  import { loadCommonJsModule, shouldRetryAsCommonJs } from "../utils/commonjs-loader.js";
4
4
  import { isUnknownRecord } from "../utils/record.js";
5
5
  import { PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_BUILD } from "../shims/constants.js";
@@ -184,11 +184,24 @@ function warnConfigLoadFailure(filename, err) {
184
184
  if (isNextIntlPlugin) console.warn("[vinext] Hint: createNextIntlPlugin() is not needed with vinext. Remove the next-intl/plugin wrapper from your next.config — vinext auto-detects next-intl and registers the i18n config alias automatically.");
185
185
  }
186
186
  /**
187
+ * The `defaultConfig` handed to a function-form next.config. Next.js passes
188
+ * its full `defaultConfig` (packages/next/src/server/config-shared.ts); vinext
189
+ * passes the subset configs are known to read, with values matching Next.js,
190
+ * so `[...defaultConfig.pageExtensions, "page.js"]` works. Fresh per call so a
191
+ * config that mutates it cannot leak into later loads.
192
+ */
193
+ function createFunctionConfigDefaults() {
194
+ return {
195
+ pageExtensions: [...DEFAULT_PAGE_EXTENSIONS],
196
+ compress: true
197
+ };
198
+ }
199
+ /**
187
200
  * Resolve a Next-style config value, calling it if it's a function-form config
188
201
  * (Next.js supports `module.exports = (phase, opts) => config`).
189
202
  */
190
203
  async function resolveConfigValue(config, phase = DEFAULT_PHASE) {
191
- if (typeof config === "function") return await config(phase, { defaultConfig: {} });
204
+ if (typeof config === "function") return await config(phase, { defaultConfig: createFunctionConfigDefaults() });
192
205
  return config;
193
206
  }
194
207
  /**
@@ -436,7 +449,7 @@ async function loadNextConfigWithPackageIdentity(root, phase) {
436
449
  },
437
450
  load(id) {
438
451
  if (id !== resolvedVirtualConfigId) return;
439
- return `import * as configModule from ${configPathLiteral};\nconst cjsModule = configModule[${JSON.stringify(VINEXT_CJS_EXPORTS_KEY)}];\nconst cjsInitial = configModule[${JSON.stringify(VINEXT_CJS_INITIAL_KEY)}];\nconst cjsExports = cjsModule && cjsModule.exports;\nconst cjsValue = cjsExports != null && (cjsExports !== cjsInitial || (typeof cjsExports === "object" && Object.keys(cjsExports).length > 0)) ? cjsExports : undefined;\nconst value = cjsValue ?? configModule.default ?? configModule;\nexport default typeof value === "function" ? await value(${phaseLiteral}, { defaultConfig: {} }) : value;\n`;
452
+ return `import * as configModule from ${configPathLiteral};\nconst cjsModule = configModule[${JSON.stringify(VINEXT_CJS_EXPORTS_KEY)}];\nconst cjsInitial = configModule[${JSON.stringify(VINEXT_CJS_INITIAL_KEY)}];\nconst cjsExports = cjsModule && cjsModule.exports;\nconst cjsValue = cjsExports != null && (cjsExports !== cjsInitial || (typeof cjsExports === "object" && Object.keys(cjsExports).length > 0)) ? cjsExports : undefined;\nconst value = cjsValue ?? configModule.default ?? configModule;\nexport default typeof value === "function" ? await value(${phaseLiteral}, { defaultConfig: ${JSON.stringify(createFunctionConfigDefaults())} }) : value;\n`;
440
453
  }
441
454
  },
442
455
  ...isTypeScriptConfig ? [cjsGlobalsInjectorPlugin(configPath)] : [],
@@ -748,6 +761,7 @@ async function resolveNextConfig(config, root = toSlash(process.cwd()), options
748
761
  basePath: "",
749
762
  assetPrefix: "",
750
763
  trailingSlash: false,
764
+ compress: true,
751
765
  skipProxyUrlNormalize: false,
752
766
  typescript: {},
753
767
  output: "",
@@ -933,6 +947,7 @@ async function resolveNextConfig(config, root = toSlash(process.cwd()), options
933
947
  basePath: config.basePath ?? "",
934
948
  assetPrefix: normalizeAssetPrefix(config.assetPrefix),
935
949
  trailingSlash: config.trailingSlash ?? false,
950
+ compress: config.compress !== false,
936
951
  skipProxyUrlNormalize: config.skipProxyUrlNormalize ?? config.skipMiddlewareUrlNormalize ?? false,
937
952
  typescript: typeof config.typescript?.tsconfigPath === "string" ? { tsconfigPath: config.typescript.tsconfigPath } : {},
938
953
  output: output === "export" || output === "standalone" ? output : "",
@@ -60,6 +60,8 @@ type AppRouterConfig = {
60
60
  globalNotFound?: boolean;
61
61
  /** Enables Next.js Cache Components semantics for App Router document HTML. */
62
62
  cacheComponents?: boolean;
63
+ /** Reads an MDX source's ESM exports, as the prerender listing does. */
64
+ readMdxEsm?: ((source: string) => string) | null;
63
65
  /** Resolved `experimental.prefetchInlining` thresholds. */
64
66
  prefetchInlining?: PrefetchInliningConfig;
65
67
  /** Whether the RSC build discovered any server references. Defaults to true. */
@@ -2,11 +2,12 @@ import { toSlash } from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index
2
2
  import { appRouteHasMainTreeLoadingBoundary } from "../routing/app-router.js";
3
3
  import { resolveEntryPath } from "./runtime-entry-module.js";
4
4
  import { isProxyFile } from "../server/middleware.js";
5
- import { extractExportConstString } from "../build/report.js";
5
+ import { extractExportConstString, getAppRouteRenderEntryPath } from "../build/report.js";
6
6
  import { routePatternParts } from "../routing/route-pattern.js";
7
7
  import { safeJsonStringify } from "../server/html.js";
8
8
  import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES } from "../server/image-optimization.js";
9
9
  import { buildAppRscManifestCode } from "./app-rsc-manifest.js";
10
+ import { classifyAppPageRouteStaticEligibility } from "../build/app-page-static-eligibility.js";
10
11
  import { generateDevOriginCheckCode } from "../server/dev-origin-check.js";
11
12
  import { ACTION_OWNER_MANIFEST_ID } from "../plugins/action-owner-manifest.js";
12
13
  import fs from "node:fs";
@@ -38,7 +39,6 @@ const appPageExecutionPath = resolveEntryPath("../server/app-page-execution.js",
38
39
  const appFallbackRendererPath = resolveEntryPath("../server/app-fallback-renderer.js", import.meta.url);
39
40
  const appElementsPath = resolveEntryPath("../server/app-elements.js", import.meta.url);
40
41
  const appPageRouteWiringPath = resolveEntryPath("../server/app-page-route-wiring.js", import.meta.url);
41
- const appPageProbePath = resolveEntryPath("../server/app-page-probe.js", import.meta.url);
42
42
  const appPageDispatchPath = resolveEntryPath("../server/app-page-dispatch.js", import.meta.url);
43
43
  const appPagePprRuntimePath = resolveEntryPath("../server/app-page-ppr-runtime.js", import.meta.url);
44
44
  const fileBasedMetadataPath = resolveEntryPath("../server/file-based-metadata.js", import.meta.url);
@@ -46,7 +46,6 @@ const appPageRequestPath = resolveEntryPath("../server/app-page-request.js", imp
46
46
  const appSegmentConfigPath = resolveEntryPath("../server/app-segment-config.js", import.meta.url);
47
47
  const appRscRouteMatchingPath = resolveEntryPath("../server/app-rsc-route-matching.js", import.meta.url);
48
48
  const appRscResponseStagePath = resolveEntryPath("../server/app-rsc-response-stage.js", import.meta.url);
49
- const appRscCombinedHandlerPath = resolveEntryPath("../server/app-rsc-combined-handler.js", import.meta.url);
50
49
  const rscStreamHintsPath = resolveEntryPath("../server/rsc-stream-hints.js", import.meta.url);
51
50
  const isrCachePath = resolveEntryPath("../server/isr-cache.js", import.meta.url);
52
51
  const thenableParamsShimPath = resolveEntryPath("../shims/thenable-params.js", import.meta.url);
@@ -64,10 +63,10 @@ const appHookWarningSuppressionPath = resolveEntryPath("../server/app-hook-warni
64
63
  const serverGlobalsPath = resolveEntryPath("../server/server-globals.js", import.meta.url);
65
64
  const appPagesBridgePath = resolveEntryPath("../server/app-pages-bridge.js", import.meta.url);
66
65
  const routePatternPath = resolveEntryPath("../routing/route-pattern.js", import.meta.url);
67
- function buildAppRequestRouteMetadata(routes) {
66
+ function createSegmentSourceReader() {
68
67
  const sourceCache = /* @__PURE__ */ new Map();
69
- const forcesDynamic = (filePath) => {
70
- if (!filePath) return false;
68
+ return (filePath) => {
69
+ if (!filePath) return null;
71
70
  let source = sourceCache.get(filePath);
72
71
  if (source === void 0) {
73
72
  try {
@@ -77,19 +76,57 @@ function buildAppRequestRouteMetadata(routes) {
77
76
  }
78
77
  sourceCache.set(filePath, source);
79
78
  }
79
+ return source;
80
+ };
81
+ }
82
+ /** Segment config files of the tree a direct request to a page route renders. */
83
+ function appPageSegmentConfigPaths(route) {
84
+ return [
85
+ ...route.layouts,
86
+ route.pagePath,
87
+ ...route.parallelSlots.flatMap((slot) => [
88
+ slot.layoutPath,
89
+ ...slot.configLayoutPaths ?? [],
90
+ slot.pagePath ?? slot.defaultPath
91
+ ])
92
+ ];
93
+ }
94
+ /**
95
+ * Patterns of the static App pages that answer a request whose raw pathname
96
+ * reaches a dynamic sibling but whose segment-decoded pathname names them, so
97
+ * `/%61` and `/caf%C3%A9` render `/a` and `/café` rather than `/[slug]`.
98
+ *
99
+ * Next.js serves those requests from the response cached under the decoded
100
+ * pathname, which exists only for a page it prerendered. The prerender listing
101
+ * classifies those: a page whose effective segment config renders it
102
+ * dynamically (`dynamic = "force-dynamic"`, `revalidate = 0` or the edge
103
+ * runtime on any segment) and a Route Handler have no such entry, so the
104
+ * dynamic sibling renders. So does a page whose sources can't be read here;
105
+ * its sibling's render stays out of the shared caches. A cacheComponents
106
+ * build lists every page route, as the prerender listing does.
107
+ */
108
+ function buildAppDecodedPathnamePatterns(routes, config) {
109
+ const isPrerenderedPage = (route) => {
110
+ if (config?.cacheComponents) return true;
111
+ try {
112
+ return classifyAppPageRouteStaticEligibility(route, config?.readMdxEsm ?? null) === "eligible";
113
+ } catch {
114
+ return false;
115
+ }
116
+ };
117
+ return routes.filter((route) => !route.isDynamic && !route.routePath && getAppRouteRenderEntryPath(route) !== null && isPrerenderedPage(route)).map((route) => route.pattern);
118
+ }
119
+ function buildAppRequestRouteMetadata(routes) {
120
+ const readSource = createSegmentSourceReader();
121
+ const forcesDynamic = (filePath) => {
122
+ const source = readSource(filePath);
80
123
  return source !== null && extractExportConstString(source, "dynamic") === "force-dynamic";
81
124
  };
82
125
  return routes.map((route) => ({
83
126
  canUseCanonicalLoadingShell: appRouteHasMainTreeLoadingBoundary(route),
84
127
  forceDynamic: route.routePath ? forcesDynamic(route.routePath) : [
85
- ...route.layouts,
86
- route.pagePath,
87
- ...route.parallelSlots.flatMap((slot) => [
88
- slot.layoutPath,
89
- ...slot.configLayoutPaths ?? [],
90
- slot.pagePath ?? slot.defaultPath,
91
- ...slot.interceptingRoutes.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])
92
- ]),
128
+ ...appPageSegmentConfigPaths(route),
129
+ ...route.parallelSlots.flatMap((slot) => slot.interceptingRoutes.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])),
93
130
  ...route.siblingIntercepts.flatMap((intercept) => [...intercept.layoutPaths, intercept.pagePath])
94
131
  ].some(forcesDynamic),
95
132
  ids: route.ids ?? null,
@@ -202,11 +239,12 @@ export const __imageConfig = ${JSON.stringify({
202
239
  contentSecurityPolicy: config?.imageConfig?.contentSecurityPolicy
203
240
  })};
204
241
  const __routes = ${JSON.stringify(requestRoutes)};
205
- const __routeMatcher = __createAppRscRouteMatcher(__routes);
242
+ const __routeMatcher = __createAppRscRouteMatcher(__routes, ${JSON.stringify(buildAppDecodedPathnamePatterns(routes, config))});
206
243
  const __metadataRouteMatchers = ${JSON.stringify(metadataRouteMatchers)};
207
244
 
208
245
  function matchRoute(pathname) { return __routeMatcher.matchRoute(pathname); }
209
246
  function matchRequestRoute(pathname) { return __routeMatcher.matchRequestRoute(pathname); }
247
+ function matchRawRequestRoute(pathname) { return __routeMatcher.matchRawRequestRoute(pathname); }
210
248
  function hasInterceptionId(interceptionId) { return __routeMatcher.hasInterceptionId(interceptionId); }
211
249
  function __isMetadataPath(pathname) {
212
250
  const parts = pathname.split("/").filter(Boolean);
@@ -240,6 +278,7 @@ function __isMetadataPath(pathname) {
240
278
  ${generateDevOriginCheckCode(config?.allowedDevOrigins)}
241
279
 
242
280
  const __requestHandler = createAppRscRequestHandler({
281
+ assetPrefix: __assetPrefix,
243
282
  basePath: __basePath,
244
283
  buildId: process.env.__VINEXT_BUILD_ID ?? null,
245
284
  cacheabilityRequestProjection: __cacheabilityRequestProjection,
@@ -262,6 +301,7 @@ const __requestHandler = createAppRscRequestHandler({
262
301
  hasInterceptionId,
263
302
  matchRoute,
264
303
  matchRequestRoute,
304
+ matchRawRequestRoute,
265
305
  matchInterceptRoute(pathname, sourcePathname, interceptionId) {
266
306
  const intercept = __routeMatcher.findIntercept(pathname, sourcePathname, interceptionId);
267
307
  if (!intercept) return null;
@@ -475,7 +515,7 @@ ${instrumentationPath ? `import * as _instrumentation from ${JSON.stringify(toSl
475
515
  import { ensureInstrumentationRegistered as __ensureInstrumentationRegistered } from ${JSON.stringify(instrumentationRuntimePath)};` : ""}
476
516
  ${applicationInitializationCode}
477
517
  ${middlewarePath ? instrumentationPath ? "let middlewareModule;" : `import * as middlewareModule from ${JSON.stringify(toSlash(middlewarePath))};` : ""}
478
- ${responseStageOnly ? `import { renderAppWorkerResponseStage as __renderAppWorkerResponseStage } from ${JSON.stringify(appRscResponseStagePath)};` : `import { createAppRscHandler } from ${JSON.stringify(appRscCombinedHandlerPath)};`}
518
+ ${responseStageOnly ? `import { renderAppWorkerResponseStage as __renderAppWorkerResponseStage } from ${JSON.stringify(appRscResponseStagePath)};` : `import { createAppRscHandler } from "vinext/server/app-rsc-combined-handler";`}
479
519
  import { registerConfiguredCacheAdapters as __registerConfiguredCacheAdapters } from "virtual:vinext-cache-adapters";
480
520
  import __pagesClientAssets from "virtual:vinext-pages-client-assets";
481
521
  ${actionOwners === void 0 ? `import __vinextActionOwners from ${JSON.stringify(ACTION_OWNER_MANIFEST_ID)};` : ""}
@@ -513,7 +553,6 @@ import {
513
553
  resolveAppPageChildSegments as __resolveAppPageChildSegments,
514
554
  } from ${JSON.stringify(appPageRouteWiringPath)};
515
555
  import { buildPageElements as __buildPageElements } from ${JSON.stringify(appPageElementBuilderPath)};
516
- import { buildAppPageProbes as __buildAppPageProbes } from ${JSON.stringify(appPageProbePath)};
517
556
  import {
518
557
  dispatchAppPage as __dispatchAppPage,
519
558
  } from ${JSON.stringify(appPageDispatchPath)};
@@ -566,7 +605,7 @@ import { suppressHookWarningAls } from ${JSON.stringify(appHookWarningSuppressio
566
605
  import { clearAppRequestContext as __clearRequestContext, setAppNavigationContext as setNavigationContext } from ${JSON.stringify(appRequestContextPath)};
567
606
  __configureMemoryCacheHandler({ cacheMaxMemorySize: ${JSON.stringify(cacheMaxMemorySize)} });
568
607
  import { createAppPrerenderStaticParamsResolver as __createAppPrerenderStaticParamsResolver } from ${JSON.stringify(appPrerenderStaticParamsPath)};
569
- import { ensureAppRouteModulesLoaded as __ensureRouteLoaded, loadAppInterceptPage as __loadAppInterceptPage } from ${JSON.stringify(appRouteModuleLoaderPath)};
608
+ import { ensureAppRouteModulesLoaded as __ensureRouteLoaded } from ${JSON.stringify(appRouteModuleLoaderPath)};
570
609
  import {
571
610
  getRenderedConcreteUrlPathsForRoute as __getRenderedConcreteUrlPathsForRoute,
572
611
  initPregeneratedPathsFromGlobals as __initPregeneratedPathsFromGlobals,
@@ -744,7 +783,7 @@ function __VINEXT_CLASS_REASONS(routeIdx) {
744
783
  const routes = [
745
784
  ${routeEntries.join(",\n")}
746
785
  ];
747
- const __routeMatcher = __createAppRscRouteMatcher(routes);
786
+ const __routeMatcher = __createAppRscRouteMatcher(routes, ${JSON.stringify(buildAppDecodedPathnamePatterns(routes, config))});
748
787
 
749
788
  ${instrumentationPath ? "let metadataRoutes;" : `const metadataRoutes = [
750
789
  ${metaRouteEntries.join(",\n")}
@@ -841,6 +880,10 @@ function matchRequestRoute(url) {
841
880
  return __routeMatcher.matchRequestRoute(url);
842
881
  }
843
882
 
883
+ function matchRawRequestRoute(url) {
884
+ return __routeMatcher.matchRawRequestRoute(url);
885
+ }
886
+
844
887
  /**
845
888
  * Check if a pathname matches any intercepting route.
846
889
  * Returns the match info or null.
@@ -952,6 +995,7 @@ ${rootParamNameEntries.join("\n")}
952
995
  __setPagesClientAssets(__pagesClientAssets);
953
996
  function __VINEXT_ACTION_OWNERS() { return ${actionOwners === void 0 ? "__vinextActionOwners" : safeJsonStringify(actionOwners)}; }
954
997
  ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandler = createAppRscHandler({"}
998
+ assetPrefix: __assetPrefix,
955
999
  basePath: __basePath,
956
1000
  buildId: process.env.__VINEXT_BUILD_ID ?? null,
957
1001
  ensureRouteLoaded: __ensureRouteLoaded,
@@ -999,6 +1043,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
999
1043
  scriptNonce,
1000
1044
  searchParams,
1001
1045
  renderMode,
1046
+ renderWholeDocument,
1002
1047
  }) {
1003
1048
  const PageComponent = route.page?.default;
1004
1049
  const __segmentConfigBranches = __resolveRouteSegmentConfigBranches(route);
@@ -1020,7 +1065,6 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1020
1065
  routePatternParts: route.patternParts,
1021
1066
  routeSegments: route.routeSegments,
1022
1067
  });
1023
- const _asyncRouteParams = makeThenableParams(params);
1024
1068
  return __dispatchAppPage({
1025
1069
  basePath: __basePath,
1026
1070
  bypassInterceptionContextCache,
@@ -1039,6 +1083,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1039
1083
  observePageSearchParamsAccess: buildOptions?.observePageSearchParamsAccess === true,
1040
1084
  isForceStatic: buildOptions?.isForceStatic === true,
1041
1085
  serveStreamingMetadata: buildOptions?.serveStreamingMetadata,
1086
+ placeStreamedMetadataInHead: buildOptions?.placeStreamedMetadataInHead === true,
1042
1087
  isProduction: process.env.NODE_ENV === "production",
1043
1088
  }, layoutParamAccess, displayPathname, scriptNonce);
1044
1089
  },
@@ -1126,31 +1171,6 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1126
1171
  route,
1127
1172
  });
1128
1173
  },
1129
- async probePage(probeSearchParams = searchParams) {
1130
- const __probeIntercept = findIntercept(
1131
- interceptionPathname,
1132
- interceptionContext,
1133
- interceptionId,
1134
- );
1135
- // The intercepting-route page module is lazy (page: null + __pageLoader).
1136
- // Resolve it before probing so buildAppPageProbes inspects the real page
1137
- // component for dynamic bailout — matching the render path, which also
1138
- // hydrates it (resolveAppPageInterceptState). Without this the intercept
1139
- // probe branch silently inspects an undefined component and never
1140
- // observes the page's searchParams/headers access. Shared loader, so
1141
- // the import is isolated from the request context here too.
1142
- if (__probeIntercept) await __loadAppInterceptPage(__probeIntercept);
1143
- return Promise.all(__buildAppPageProbes({
1144
- route,
1145
- pageComponent: PageComponent,
1146
- asyncRouteParams: _asyncRouteParams,
1147
- searchParams: probeSearchParams,
1148
- intercept: __probeIntercept,
1149
- isRscRequest,
1150
- matchedParams: params,
1151
- makeThenableParams,
1152
- }));
1153
- },
1154
1174
  renderErrorBoundaryPage(renderErr, errorOrigin) {
1155
1175
  const __activeIntercept = findIntercept(
1156
1176
  interceptionPathname,
@@ -1209,6 +1229,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1209
1229
  searchParams,
1210
1230
  setNavigationContext,
1211
1231
  renderMode,
1232
+ renderWholeDocument,
1212
1233
  });
1213
1234
  },
1214
1235
  async dispatchMatchedRouteHandler({
@@ -1563,6 +1584,7 @@ ${responseStageOnly ? "const __responseStageOptions = {" : "const __appRscHandle
1563
1584
  },` : ""}
1564
1585
  matchRoute,
1565
1586
  matchRequestRoute,
1587
+ matchRawRequestRoute,
1566
1588
  hasInterceptionId,
1567
1589
  matchInterceptRoute(pathname, sourcePathname, interceptionId) {
1568
1590
  const intercept = findIntercept(pathname, sourcePathname, interceptionId);
package/dist/index.d.ts CHANGED
@@ -106,7 +106,10 @@ export type VinextOptions = {
106
106
  * Configure cache handlers declaratively, so you don't need a custom worker
107
107
  * entry that calls `setDataCacheHandler()` / `setCdnCacheAdapter()`. Each slot
108
108
  * is a `{ adapter, options }` descriptor pointing at an adapter module whose
109
- * default export is a factory; the plugin registers them automatically on the
109
+ * default export is a factory function or a class; either receives one
110
+ * `{ env, options }` argument (classes are invoked with `new`, other
111
+ * functions are called; see `CacheAdapterDescriptor.adapter` for how
112
+ * classes are recognised). The plugin registers them automatically on the
110
113
  * first request, passing the host `env` (Worker bindings) so adapters that
111
114
  * need a binding — e.g. a KV namespace — can read it.
112
115
  *