vinext 1.0.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (334) hide show
  1. package/README.md +93 -10
  2. package/dist/build/app-page-static-eligibility.d.ts +15 -0
  3. package/dist/build/app-page-static-eligibility.js +82 -0
  4. package/dist/build/client-build-config.d.ts +10 -0
  5. package/dist/build/client-build-config.js +18 -2
  6. package/dist/build/pages-client-assets-module.d.ts +8 -0
  7. package/dist/build/pages-client-assets-module.js +21 -1
  8. package/dist/build/prerender-paths.js +8 -81
  9. package/dist/build/prerender.js +33 -8
  10. package/dist/build/run-prerender.js +1 -1
  11. package/dist/build/server-manifest.d.ts +7 -0
  12. package/dist/build/server-manifest.js +11 -1
  13. package/dist/build/ssr-manifest.d.ts +2 -0
  14. package/dist/build/ssr-manifest.js +6 -2
  15. package/dist/cache/cache-adapters-virtual.d.ts +7 -1
  16. package/dist/cache/cache-adapters-virtual.js +3 -3
  17. package/dist/check.js +7 -6
  18. package/dist/cli.js +2 -1
  19. package/dist/client/client-redirect-matcher.d.ts +14 -0
  20. package/dist/client/client-redirect-matcher.js +37 -0
  21. package/dist/client/client-redirects.d.ts +27 -0
  22. package/dist/client/client-redirects.js +28 -0
  23. package/dist/client/client-rewrites.d.ts +2 -1
  24. package/dist/client/client-rewrites.js +1 -1
  25. package/dist/client/navigation-runtime.d.ts +11 -0
  26. package/dist/client/navigation-runtime.js +1 -1
  27. package/dist/config/config-matchers.d.ts +26 -11
  28. package/dist/config/config-matchers.js +81 -82
  29. package/dist/config/destination-params.d.ts +47 -0
  30. package/dist/config/destination-params.js +116 -0
  31. package/dist/config/next-config.d.ts +14 -0
  32. package/dist/config/next-config.js +21 -3
  33. package/dist/entries/app-rsc-entry.d.ts +6 -0
  34. package/dist/entries/app-rsc-entry.js +84 -49
  35. package/dist/entries/pages-client-entry.js +3 -1
  36. package/dist/entries/pages-server-entry.js +13 -37
  37. package/dist/index.d.ts +7 -2
  38. package/dist/index.js +193 -73
  39. package/dist/init-cloudflare.d.ts +9 -0
  40. package/dist/init-cloudflare.js +107 -31
  41. package/dist/init-platform.d.ts +4 -0
  42. package/dist/init-platform.js +27 -2
  43. package/dist/init.d.ts +1 -0
  44. package/dist/init.js +67 -3
  45. package/dist/plugins/ast-scope.d.ts +7 -0
  46. package/dist/plugins/ast-scope.js +59 -3
  47. package/dist/plugins/cache-flight-codec.d.ts +19 -0
  48. package/dist/plugins/cache-flight-codec.js +68 -0
  49. package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
  50. package/dist/plugins/commonjs-esm-facade.js +80 -0
  51. package/dist/plugins/dynamic-preload-metadata.d.ts +1 -1
  52. package/dist/plugins/dynamic-preload-metadata.js +9 -8
  53. package/dist/plugins/fonts.d.ts +8 -11
  54. package/dist/plugins/fonts.js +71 -34
  55. package/dist/plugins/ignore-dynamic-requests.d.ts +1 -1
  56. package/dist/plugins/ignore-dynamic-requests.js +3 -4
  57. package/dist/plugins/middleware-server-only.d.ts +5 -4
  58. package/dist/plugins/middleware-server-only.js +8 -5
  59. package/dist/plugins/pages-node-externals.js +1 -1
  60. package/dist/plugins/rsc-scan-glob-imports.d.ts +19 -0
  61. package/dist/plugins/rsc-scan-glob-imports.js +50 -0
  62. package/dist/plugins/strip-server-exports.js +262 -98
  63. package/dist/plugins/transform-result.d.ts +9 -5
  64. package/dist/plugins/transitive-externals.js +1 -1
  65. package/dist/plugins/typeof-window.d.ts +2 -2
  66. package/dist/plugins/use-cache-callable.js +8 -2
  67. package/dist/plugins/worker-server-only-imports.d.ts +20 -0
  68. package/dist/plugins/worker-server-only-imports.js +31 -0
  69. package/dist/plugins/worker-use-server.d.ts +25 -0
  70. package/dist/plugins/worker-use-server.js +129 -0
  71. package/dist/routing/file-matcher.d.ts +1 -0
  72. package/dist/routing/file-matcher.js +1 -1
  73. package/dist/server/api-handler.d.ts +1 -0
  74. package/dist/server/api-handler.js +19 -8
  75. package/dist/server/app-browser-action-result.d.ts +1 -1
  76. package/dist/server/app-browser-action-result.js +9 -2
  77. package/dist/server/app-browser-entry.js +11 -7
  78. package/dist/server/app-browser-history-controller.d.ts +2 -0
  79. package/dist/server/app-browser-history-controller.js +8 -0
  80. package/dist/server/app-browser-interception-context.js +26 -2
  81. package/dist/server/app-browser-navigation-controller.d.ts +7 -1
  82. package/dist/server/app-browser-navigation-controller.js +94 -11
  83. package/dist/server/app-browser-server-action-client.js +1 -1
  84. package/dist/server/app-fallback-renderer.d.ts +2 -0
  85. package/dist/server/app-fallback-renderer.js +1 -0
  86. package/dist/server/app-history-state.d.ts +3 -0
  87. package/dist/server/app-history-state.js +7 -0
  88. package/dist/server/app-middleware.d.ts +11 -0
  89. package/dist/server/app-middleware.js +19 -3
  90. package/dist/server/app-optimistic-routing.js +1 -1
  91. package/dist/server/app-page-boundary-render.d.ts +5 -0
  92. package/dist/server/app-page-boundary-render.js +6 -4
  93. package/dist/server/app-page-cache-finalizer.d.ts +11 -0
  94. package/dist/server/app-page-cache-finalizer.js +41 -7
  95. package/dist/server/app-page-cache-render.d.ts +18 -0
  96. package/dist/server/app-page-cache-render.js +63 -43
  97. package/dist/server/app-page-cache.d.ts +6 -1
  98. package/dist/server/app-page-cache.js +28 -8
  99. package/dist/server/app-page-dispatch.d.ts +12 -2
  100. package/dist/server/app-page-dispatch.js +51 -33
  101. package/dist/server/app-page-element-builder.d.ts +7 -0
  102. package/dist/server/app-page-element-builder.js +27 -42
  103. package/dist/server/app-page-execution.d.ts +15 -12
  104. package/dist/server/app-page-execution.js +30 -40
  105. package/dist/server/app-page-head.d.ts +5 -0
  106. package/dist/server/app-page-head.js +9 -3
  107. package/dist/server/app-page-ppr-runtime.js +1 -1
  108. package/dist/server/app-page-probe.d.ts +0 -109
  109. package/dist/server/app-page-probe.js +3 -136
  110. package/dist/server/app-page-render-identity.d.ts +0 -1
  111. package/dist/server/app-page-render-identity.js +1 -1
  112. package/dist/server/app-page-render-observation.js +3 -3
  113. package/dist/server/app-page-render.d.ts +13 -5
  114. package/dist/server/app-page-render.js +219 -119
  115. package/dist/server/app-page-request.d.ts +0 -1
  116. package/dist/server/app-page-request.js +54 -17
  117. package/dist/server/app-page-response.d.ts +4 -3
  118. package/dist/server/app-page-response.js +4 -3
  119. package/dist/server/app-page-route-wiring.d.ts +17 -5
  120. package/dist/server/app-page-route-wiring.js +57 -35
  121. package/dist/server/app-page-rsc-render-status.d.ts +48 -0
  122. package/dist/server/app-page-rsc-render-status.js +54 -0
  123. package/dist/server/app-page-stream.d.ts +15 -8
  124. package/dist/server/app-page-stream.js +6 -0
  125. package/dist/server/app-pages-bridge.d.ts +1 -1
  126. package/dist/server/app-pages-bridge.js +2 -3
  127. package/dist/server/app-prerender-endpoints.js +9 -6
  128. package/dist/server/app-request-stage-dispatch.js +7 -3
  129. package/dist/server/app-request-stage-independent-entry.js +29 -9
  130. package/dist/server/app-response-header-provenance.d.ts +2 -0
  131. package/dist/server/app-response-header-provenance.js +10 -4
  132. package/dist/server/app-response-stage-entry.js +10 -2
  133. package/dist/server/app-route-handler-cache.d.ts +1 -0
  134. package/dist/server/app-route-handler-cache.js +1 -0
  135. package/dist/server/app-route-handler-dispatch.d.ts +1 -0
  136. package/dist/server/app-route-handler-dispatch.js +6 -3
  137. package/dist/server/app-route-handler-execution.d.ts +1 -0
  138. package/dist/server/app-route-handler-execution.js +1 -0
  139. package/dist/server/app-route-handler-runtime.d.ts +4 -1
  140. package/dist/server/app-route-handler-runtime.js +45 -24
  141. package/dist/server/app-router-entry.js +27 -8
  142. package/dist/server/app-rsc-cache-busting.js +1 -1
  143. package/dist/server/app-rsc-errors.js +20 -16
  144. package/dist/server/app-rsc-handler.d.ts +11 -0
  145. package/dist/server/app-rsc-handler.js +291 -125
  146. package/dist/server/app-rsc-request-normalization.d.ts +3 -1
  147. package/dist/server/app-rsc-request-normalization.js +4 -2
  148. package/dist/server/app-rsc-response-stage.d.ts +1 -1
  149. package/dist/server/app-rsc-response-stage.js +10 -6
  150. package/dist/server/app-rsc-route-matching.d.ts +9 -1
  151. package/dist/server/app-rsc-route-matching.js +36 -19
  152. package/dist/server/app-segment-config.d.ts +2 -1
  153. package/dist/server/app-server-action-execution.d.ts +2 -1
  154. package/dist/server/app-server-action-execution.js +62 -23
  155. package/dist/server/app-ssr-entry.d.ts +3 -2
  156. package/dist/server/app-ssr-entry.js +8 -5
  157. package/dist/server/app-ssr-stream.d.ts +6 -1
  158. package/dist/server/app-ssr-stream.js +34 -15
  159. package/dist/server/app-worker-stages.d.ts +7 -2
  160. package/dist/server/app-worker-stages.js +4 -4
  161. package/dist/server/cacheability-request.js +11 -7
  162. package/dist/server/client-build-files.d.ts +16 -0
  163. package/dist/server/client-build-files.js +36 -0
  164. package/dist/server/client-reuse-manifest.js +1 -1
  165. package/dist/server/config-headers.js +2 -0
  166. package/dist/server/dev-server.js +50 -29
  167. package/dist/server/dev-stack-sourcemap.js +18 -23
  168. package/dist/server/document-initial-head.d.ts +0 -11
  169. package/dist/server/document-initial-head.js +1 -1
  170. package/dist/server/forwarded-middleware-context.d.ts +5 -0
  171. package/dist/server/forwarded-middleware-context.js +22 -0
  172. package/dist/server/headers.d.ts +18 -1
  173. package/dist/server/headers.js +19 -2
  174. package/dist/server/http-conditional.d.ts +11 -0
  175. package/dist/server/http-conditional.js +10 -1
  176. package/dist/server/http-error-responses.d.ts +1 -1
  177. package/dist/server/image-optimization.d.ts +54 -0
  178. package/dist/server/image-optimization.js +118 -9
  179. package/dist/server/isr-cache.d.ts +10 -0
  180. package/dist/server/isr-cache.js +43 -8
  181. package/dist/server/metadata-route-response.js +9 -8
  182. package/dist/server/middleware-matcher-pattern.js +8 -4
  183. package/dist/server/middleware-matcher.d.ts +2 -0
  184. package/dist/server/middleware-matcher.js +23 -2
  185. package/dist/server/middleware-response-headers.js +2 -0
  186. package/dist/server/middleware-runtime.d.ts +13 -0
  187. package/dist/server/middleware-runtime.js +33 -20
  188. package/dist/server/middleware.d.ts +1 -1
  189. package/dist/server/middleware.js +3 -1
  190. package/dist/server/multi-stage.d.ts +19 -0
  191. package/dist/server/navigation-planner.js +1 -1
  192. package/dist/server/node-response-signal.d.ts +16 -0
  193. package/dist/server/node-response-signal.js +26 -0
  194. package/dist/server/normalize-path.d.ts +0 -13
  195. package/dist/server/normalize-path.js +1 -34
  196. package/dist/server/open-redirect.d.ts +47 -0
  197. package/dist/server/open-redirect.js +74 -1
  198. package/dist/server/pages-api-route.d.ts +3 -2
  199. package/dist/server/pages-api-route.js +4 -3
  200. package/dist/server/pages-cache-tag.d.ts +12 -0
  201. package/dist/server/pages-cache-tag.js +19 -0
  202. package/dist/server/pages-client-assets.d.ts +2 -0
  203. package/dist/server/pages-data-route.d.ts +10 -0
  204. package/dist/server/pages-data-route.js +19 -2
  205. package/dist/server/pages-document-asset-props.d.ts +5 -1
  206. package/dist/server/pages-document-asset-props.js +13 -5
  207. package/dist/server/pages-document-splice.d.ts +19 -0
  208. package/dist/server/pages-document-splice.js +55 -0
  209. package/dist/server/pages-i18n.d.ts +12 -1
  210. package/dist/server/pages-i18n.js +18 -4
  211. package/dist/server/pages-node-compat.d.ts +16 -5
  212. package/dist/server/pages-node-compat.js +20 -12
  213. package/dist/server/pages-page-data.d.ts +32 -24
  214. package/dist/server/pages-page-data.js +50 -120
  215. package/dist/server/pages-page-handler.d.ts +0 -6
  216. package/dist/server/pages-page-handler.js +209 -130
  217. package/dist/server/pages-page-response.d.ts +12 -6
  218. package/dist/server/pages-page-response.js +41 -34
  219. package/dist/server/pages-request-pipeline.d.ts +10 -2
  220. package/dist/server/pages-request-pipeline.js +37 -18
  221. package/dist/server/pages-request-stage-entry.d.ts +6 -0
  222. package/dist/server/pages-request-stage-entry.js +79 -16
  223. package/dist/server/pages-response-stage-entry.js +4 -0
  224. package/dist/server/pages-revalidate.js +1 -1
  225. package/dist/server/pages-router-entry.js +4 -3
  226. package/dist/server/prerender-manifest.d.ts +3 -3
  227. package/dist/server/prerender-manifest.js +4 -3
  228. package/dist/server/prerender-work-unit-setup.js +4 -0
  229. package/dist/server/prod-server.d.ts +20 -7
  230. package/dist/server/prod-server.js +343 -129
  231. package/dist/server/proper-error.d.ts +4 -0
  232. package/dist/server/proper-error.js +31 -0
  233. package/dist/server/request-pipeline.d.ts +24 -9
  234. package/dist/server/request-pipeline.js +24 -9
  235. package/dist/server/response-compression.d.ts +43 -0
  236. package/dist/server/response-compression.js +111 -0
  237. package/dist/server/revalidation-request.d.ts +1 -0
  238. package/dist/server/revalidation-request.js +1 -1
  239. package/dist/server/rsc-stream-hints.js +31 -2
  240. package/dist/server/seed-cache.d.ts +1 -0
  241. package/dist/server/seed-cache.js +15 -11
  242. package/dist/server/server-reference-loader.d.ts +4 -0
  243. package/dist/server/server-reference-loader.js +29 -0
  244. package/dist/server/socket-error-backstop.d.ts +23 -1
  245. package/dist/server/socket-error-backstop.js +69 -17
  246. package/dist/server/static-file-signal.d.ts +15 -4
  247. package/dist/server/static-file-signal.js +46 -12
  248. package/dist/server/worker-image-optimization.d.ts +34 -0
  249. package/dist/server/worker-image-optimization.js +86 -0
  250. package/dist/server/worker-stages.d.ts +1 -1
  251. package/dist/server/worker-stages.js +2 -2
  252. package/dist/server/worker-utils.d.ts +8 -3
  253. package/dist/server/worker-utils.js +12 -7
  254. package/dist/shims/app-router-scroll.js +4 -1
  255. package/dist/shims/app-router-tree-context.d.ts +5 -0
  256. package/dist/shims/app-router-tree-context.js +27 -0
  257. package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
  258. package/dist/shims/cache-adapter-instantiate.js +118 -0
  259. package/dist/shims/cache-callable-runtime.d.ts +6 -42
  260. package/dist/shims/cache-callable-runtime.js +65 -174
  261. package/dist/shims/cache-flight-arguments.d.ts +22 -0
  262. package/dist/shims/cache-flight-arguments.js +56 -0
  263. package/dist/shims/cache-handler.js +1 -9
  264. package/dist/shims/cache-request-state.d.ts +15 -0
  265. package/dist/shims/cache-request-state.js +31 -8
  266. package/dist/shims/cache-runtime.d.ts +12 -20
  267. package/dist/shims/cache-runtime.js +166 -225
  268. package/dist/shims/cache.d.ts +4 -4
  269. package/dist/shims/cache.js +44 -16
  270. package/dist/shims/cacheability-classification.d.ts +7 -0
  271. package/dist/shims/cdn-cache.d.ts +8 -0
  272. package/dist/shims/cdn-cache.js +17 -1
  273. package/dist/shims/disable-smooth-scroll.d.ts +3 -0
  274. package/dist/shims/disable-smooth-scroll.js +36 -0
  275. package/dist/shims/document-placeholders.d.ts +19 -0
  276. package/dist/shims/document-placeholders.js +45 -0
  277. package/dist/shims/document.js +21 -5
  278. package/dist/shims/dynamic-preload-chunks.d.ts +1 -0
  279. package/dist/shims/dynamic-preload-chunks.js +13 -9
  280. package/dist/shims/dynamic.d.ts +1 -1
  281. package/dist/shims/dynamic.js +60 -8
  282. package/dist/shims/error-boundary-navigation.d.ts +7 -0
  283. package/dist/shims/error-boundary-navigation.js +19 -1
  284. package/dist/shims/error-boundary.d.ts +10 -10
  285. package/dist/shims/error-boundary.js +26 -7
  286. package/dist/shims/fetch-cache-state.d.ts +66 -0
  287. package/dist/shims/fetch-cache-state.js +92 -0
  288. package/dist/shims/fetch-cache.d.ts +3 -61
  289. package/dist/shims/fetch-cache.js +161 -108
  290. package/dist/shims/form.js +1 -1
  291. package/dist/shims/head.d.ts +10 -6
  292. package/dist/shims/head.js +15 -13
  293. package/dist/shims/headers.d.ts +13 -0
  294. package/dist/shims/headers.js +47 -4
  295. package/dist/shims/image.js +2 -1
  296. package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
  297. package/dist/shims/internal/app-page-props-cache-key.js +24 -15
  298. package/dist/shims/internal/headers-state.d.ts +0 -1
  299. package/dist/shims/internal/work-store-scope.d.ts +5 -0
  300. package/dist/shims/internal/work-store-scope.js +24 -0
  301. package/dist/shims/metadata.js +3 -3
  302. package/dist/shims/navigation-errors.d.ts +6 -0
  303. package/dist/shims/navigation-errors.js +11 -1
  304. package/dist/shims/navigation.d.ts +7 -0
  305. package/dist/shims/navigation.js +45 -9
  306. package/dist/shims/request-context.d.ts +11 -0
  307. package/dist/shims/request-state-types.d.ts +2 -1
  308. package/dist/shims/router.js +12 -20
  309. package/dist/shims/server.d.ts +16 -0
  310. package/dist/shims/server.js +24 -4
  311. package/dist/shims/thenable-params.d.ts +4 -0
  312. package/dist/shims/thenable-params.js +25 -3
  313. package/dist/shims/unified-request-context.d.ts +1 -1
  314. package/dist/shims/unified-request-context.js +1 -0
  315. package/dist/shims/url-utils.d.ts +2 -0
  316. package/dist/shims/url-utils.js +3 -1
  317. package/dist/utils/client-runtime-metadata.js +1 -1
  318. package/dist/utils/hash.d.ts +7 -0
  319. package/dist/utils/hash.js +11 -1
  320. package/dist/utils/mdx-scan.d.ts +5 -0
  321. package/dist/utils/mdx-scan.js +8 -1
  322. package/dist/utils/package-name.d.ts +6 -0
  323. package/dist/utils/package-name.js +12 -1
  324. package/dist/utils/plugin-rsc-version.d.ts +4 -0
  325. package/dist/utils/plugin-rsc-version.js +15 -0
  326. package/dist/utils/prerender-output-paths.js +15 -4
  327. package/dist/utils/public-file-path.d.ts +10 -2
  328. package/dist/utils/public-file-path.js +13 -9
  329. package/dist/utils/public-routes.js +2 -2
  330. package/dist/utils/react-version.d.ts +3 -0
  331. package/dist/utils/react-version.js +1 -1
  332. package/dist/utils/regex-safety.d.ts +10 -0
  333. package/dist/utils/regex-safety.js +70 -18
  334. package/package.json +9 -5
@@ -5,18 +5,20 @@ import { ASSET_PREFIX_URL_DIR, assetPrefixPathname, isAbsoluteAssetPrefix } from
5
5
  import { StaticFileCache, contentTypeForPath, etagFromFilenameHash } from "./static-file-cache.js";
6
6
  import { normalizePathnameForRouteMatchStrict } from "../routing/utils.js";
7
7
  import { hasBasePath, stripBasePath } from "../utils/base-path.js";
8
- import { VINEXT_PRERENDER_RENDER_ERROR_HEADER } from "./headers.js";
8
+ import { VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_SPECIAL_ERROR_HEADER } from "./headers.js";
9
9
  import { normalizePath } from "./normalize-path.js";
10
10
  import { notFoundResponse } from "./http-error-responses.js";
11
- import { isOpenRedirectShaped } from "./open-redirect.js";
11
+ import { getRepeatedSlashRedirect, isOpenRedirectShaped, sendRepeatedSlashRedirect } from "./open-redirect.js";
12
12
  import { readStaticFileSignal } from "./static-file-signal.js";
13
13
  import { canonicalizeRequestPathname, filterInternalHeaders } from "./request-pipeline.js";
14
+ import { buildNextDataNotFoundResponse, encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, parseNextDataPathname, shouldAddTrailingSlashToPagesDataPath, urlParserCreatesPagesDataPath } from "./pages-data-route.js";
15
+ import { buildCacheStateHeaders } from "./cache-headers.js";
14
16
  import { parseHttpDate } from "./http-date.js";
15
17
  import { evaluateStaticPreconditions } from "./http-conditional.js";
16
- import { buildNextDataNotFoundResponse, encodeUrlParserIgnoredCharacters, isNextDataPathname, normalizeNextDataPagePathname, parseNextDataPathname, shouldAddTrailingSlashToPagesDataPath, urlParserCreatesPagesDataPath } from "./pages-data-route.js";
17
18
  import { setPagesClientAssets } from "./pages-client-assets.js";
18
19
  import { resolveRequestHost, resolveRequestProtocol, trustProxy, trustedHosts } from "./proxy-trust.js";
19
- import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, isImageOptimizationPath, isSafeImageContentType, parseImageParams } from "./image-optimization.js";
20
+ import { signalFromNodeResponse } from "./node-response-signal.js";
21
+ import { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_RESPONSE_CACHE_STATE, INVALID_IMAGE_SOURCE_MESSAGE, isImageOptimizationPath, isImageSourceBodyStatus, isSafeImageContentType, parseImageParams, readImageOptimizationSignal } from "./image-optimization.js";
20
22
  import { installSocketErrorBackstop } from "./socket-error-backstop.js";
21
23
  import { collectInlineCssManifest } from "../build/inline-css.js";
22
24
  import { readTrustedRevalidationHostname } from "./revalidation-host.js";
@@ -24,11 +26,13 @@ import { traceFrameworkRequest } from "./request-tracing.js";
24
26
  import { mergeHeaders } from "./worker-utils.js";
25
27
  import { runPagesRequest, wrapMiddlewareWithBasePath } from "./pages-request-pipeline.js";
26
28
  import { computeClientRuntimeMetadata } from "../utils/client-runtime-metadata.js";
27
- import { readPrerenderSecret } from "../build/server-manifest.js";
29
+ import { readPrerenderSecret, readServerCompress } from "../build/server-manifest.js";
28
30
  import { readTrustedPrerenderRouteParamsFromHeaders, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
31
+ import { resolveClientBuildFile } from "./client-build-files.js";
29
32
  import { registerPrerenderCloudflareLoader } from "../build/prerender-cloudflare-loader.js";
30
33
  import { seedMemoryCacheFromPrerender } from "./seed-cache.js";
31
34
  import { negotiateEncoding, parseAcceptedEncodings, selectContentEncoding } from "./accept-encoding.js";
35
+ import { COMPRESS_THRESHOLD, hasNoTransform, isCompressibleContentType, parseContentLengthHeader, resolveResponseCompression } from "./response-compression.js";
32
36
  import { ifRangeAllowsRange, parseByteRange } from "./http-range.js";
33
37
  import { createRequire } from "node:module";
34
38
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -192,25 +196,6 @@ function readNodeStream(req) {
192
196
  }
193
197
  });
194
198
  }
195
- /** Content types that benefit from compression. */
196
- const COMPRESSIBLE_TYPES = /* @__PURE__ */ new Set([
197
- "text/html",
198
- "text/css",
199
- "text/plain",
200
- "text/xml",
201
- "text/javascript",
202
- "application/javascript",
203
- "application/json",
204
- "application/xml",
205
- "application/xhtml+xml",
206
- "application/rss+xml",
207
- "application/atom+xml",
208
- "image/svg+xml",
209
- "application/manifest+json",
210
- "application/wasm"
211
- ]);
212
- /** Minimum size threshold for compression (in bytes). Below this, compression overhead isn't worth it. */
213
- const COMPRESS_THRESHOLD = 1024;
214
199
  /**
215
200
  * Create a compression stream for the given encoding.
216
201
  */
@@ -276,12 +261,14 @@ const NO_BODY_RESPONSE_STATUSES = /* @__PURE__ */ new Set([
276
261
  205,
277
262
  304
278
263
  ]);
264
+ const IMAGE_REPRESENTATION_HEADERS = buildCacheStateHeaders(IMAGE_RESPONSE_CACHE_STATE);
279
265
  const OMIT_BODY_HEADERS = /* @__PURE__ */ new Set(["content-length", "content-type"]);
280
266
  const OMIT_STATIC_RESPONSE_HEADERS = /* @__PURE__ */ new Set([
281
267
  "content-encoding",
282
268
  "content-length",
283
269
  "content-range",
284
- "content-type"
270
+ "content-type",
271
+ VINEXT_PRERENDER_SPECIAL_ERROR_HEADER
285
272
  ]);
286
273
  function omitHeadersCaseInsensitive(headersRecord, targets) {
287
274
  const filtered = {};
@@ -291,6 +278,23 @@ function omitHeadersCaseInsensitive(headersRecord, targets) {
291
278
  }
292
279
  return filtered;
293
280
  }
281
+ function readHeaderCaseInsensitive(headersRecord, name) {
282
+ const key = Object.keys(headersRecord).find((entry) => entry.toLowerCase() === name);
283
+ if (key === void 0) return void 0;
284
+ const value = headersRecord[key];
285
+ return Array.isArray(value) ? value.join(", ") : value;
286
+ }
287
+ /** Remove one field name from a Vary header, dropping the header if it empties. */
288
+ function omitVaryToken(headers, token) {
289
+ const varyKey = Object.keys(headers).find((key) => key.toLowerCase() === "vary");
290
+ if (varyKey === void 0) return headers;
291
+ const rawVary = headers[varyKey];
292
+ const remaining = (Array.isArray(rawVary) ? rawVary.join(",") : rawVary).split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0 && entry.toLowerCase() !== token.toLowerCase());
293
+ const result = { ...headers };
294
+ delete result[varyKey];
295
+ if (remaining.length > 0) result[varyKey] = remaining.join(", ");
296
+ return result;
297
+ }
294
298
  function mergeVaryHeader(headers, value) {
295
299
  const merged = { ...headers };
296
300
  const existingKey = Object.keys(merged).find((key) => key.toLowerCase() === "vary");
@@ -332,10 +336,41 @@ function installClientBuildManifestGlobals(clientDir, assetBase, assetPrefix, cr
332
336
  function isNoBodyResponseStatus(status) {
333
337
  return NO_BODY_RESPONSE_STATUSES.has(status);
334
338
  }
335
- function cancelResponseBody(response) {
339
+ /**
340
+ * Discard a response body nobody will read. When the client is gone, pass the
341
+ * request signal's reason: React reports a reasonless cancel of a pending
342
+ * render as a server error, but recognizes `ResponseAborted` as a disconnect.
343
+ */
344
+ function cancelResponseBody(response, reason) {
336
345
  const body = response.body;
337
346
  if (!body || body.locked) return;
338
- body.cancel().catch(() => {});
347
+ body.cancel(reason).catch(() => {});
348
+ }
349
+ /**
350
+ * Buffer a response body, cancelling it if the client disconnects first so a
351
+ * stalled stream does not outlive the connection. Resolves null when aborted.
352
+ */
353
+ async function bufferResponseBodyUntilAborted(response, signal) {
354
+ const body = response.body;
355
+ if (!body) return Buffer.alloc(0);
356
+ const reader = body.getReader();
357
+ const cancel = () => {
358
+ reader.cancel(signal.reason).catch(() => {});
359
+ };
360
+ if (signal.aborted) cancel();
361
+ else signal.addEventListener("abort", cancel, { once: true });
362
+ const chunks = [];
363
+ try {
364
+ while (true) {
365
+ const result = await reader.read();
366
+ if (result.done) break;
367
+ chunks.push(result.value);
368
+ }
369
+ } finally {
370
+ signal.removeEventListener("abort", cancel);
371
+ reader.releaseLock();
372
+ }
373
+ return signal.aborted ? null : Buffer.concat(chunks);
339
374
  }
340
375
  function isVinextStreamedHtmlResponse(response) {
341
376
  return response.__vinextStreamedHtmlResponse === true;
@@ -370,24 +405,23 @@ function mergeWebResponse(middlewareHeaders, response, statusOverride) {
370
405
  */
371
406
  function sendCompressed(req, res, body, contentType, statusCode, extraHeaders = {}, compress = true, statusText) {
372
407
  const buf = typeof body === "string" ? Buffer.from(body) : body;
373
- const baseType = contentType.split(";")[0].trim();
374
- const varyByEncoding = compress && COMPRESSIBLE_TYPES.has(baseType);
375
- const encoding = compress ? negotiateEncoding(req) : "identity";
376
408
  const headersWithoutBodyHeaders = omitHeadersCaseInsensitive(extraHeaders, OMIT_BODY_HEADERS);
409
+ const { varyAcceptEncoding: varyByEncoding, encoding } = resolveResponseCompression(req, compress, {
410
+ contentType,
411
+ cacheControl: readHeaderCaseInsensitive(extraHeaders, "cache-control"),
412
+ contentEncoding: readHeaderCaseInsensitive(extraHeaders, "content-encoding"),
413
+ contentLength: buf.length
414
+ });
377
415
  const writeHead = (headers, responseStatus = statusCode, responseStatusText = statusText) => {
378
416
  if (responseStatusText) res.writeHead(responseStatus, responseStatusText, headers);
379
417
  else res.writeHead(responseStatus, headers);
380
418
  };
381
- if (encoding !== "identity" && varyByEncoding && buf.length >= 1024) {
419
+ if (encoding !== "identity") {
382
420
  writeHead(mergeVaryHeader({
383
421
  ...headersWithoutBodyHeaders,
384
422
  "Content-Type": contentType,
385
423
  "Content-Encoding": encoding
386
424
  }, "Accept-Encoding"));
387
- if (req.method === "HEAD") {
388
- res.end();
389
- return;
390
- }
391
425
  const compressor = createCompressor(encoding);
392
426
  compressor.end(buf);
393
427
  pipeline(compressor, res, () => {});
@@ -405,6 +439,21 @@ function sendCompressed(req, res, body, contentType, statusCode, extraHeaders =
405
439
  res.end(buf);
406
440
  }
407
441
  }
442
+ /** The StaticFileCache key for a request pathname, or null when it is never served. */
443
+ function staticCacheLookupPath(pathname) {
444
+ let lookupPath = pathname;
445
+ if (pathname.includes("%")) try {
446
+ lookupPath = decodeURIComponent(pathname);
447
+ } catch {
448
+ return null;
449
+ }
450
+ if (lookupPath.startsWith("/.vite/") || lookupPath === "/.vite") return null;
451
+ return lookupPath;
452
+ }
453
+ /** Pathnames the Pages Router serves from routes rather than the client directory. */
454
+ function isPagesFilesystemExcludedPath(pathname, phase) {
455
+ return pathname === "/" || pathname === "/api" || pathname.startsWith("/api/") || phase === "direct" && pathname.startsWith(`/_next/static/`);
456
+ }
408
457
  /**
409
458
  * Try to serve a static file from the client build directory.
410
459
  *
@@ -415,8 +464,12 @@ function sendCompressed(req, res, body, contentType, statusCode, extraHeaders =
415
464
  *
416
465
  * Without a cache, falls back to async filesystem probing (still non-blocking,
417
466
  * unlike the old sync existsSync/statSync approach).
467
+ *
468
+ * `extraHeaders` go on every response for the file. `representationHeaders` go
469
+ * only on responses that carry the file's bytes (200 and 206), never on a 304,
470
+ * 412, 416 or 405.
418
471
  */
419
- async function tryServeStatic(req, res, clientDir, pathname, compress, cache, extraHeaders, statusCode) {
472
+ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, extraHeaders, statusCode, representationHeaders) {
420
473
  if (pathname === "/") return false;
421
474
  const responseStatus = statusCode ?? 200;
422
475
  const omitBody = isNoBodyResponseStatus(responseStatus);
@@ -424,41 +477,35 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
424
477
  const rawIfRange = req.headers["if-range"];
425
478
  const ifRange = typeof rawIfRange === "string" ? rawIfRange : void 0;
426
479
  if (cache) {
427
- let lookupPath;
428
- if (pathname.includes("%")) {
429
- try {
430
- lookupPath = decodeURIComponent(pathname);
431
- } catch {
432
- return false;
433
- }
434
- if (lookupPath.startsWith("/.vite/") || lookupPath === "/.vite") return false;
435
- } else {
436
- if (pathname.startsWith("/.vite/") || pathname === "/.vite") return false;
437
- lookupPath = pathname;
438
- }
480
+ const lookupPath = staticCacheLookupPath(pathname);
481
+ if (lookupPath === null) return false;
439
482
  const entry = cache.lookup(lookupPath);
440
483
  if (!entry) return false;
441
484
  if (req.method !== "GET" && req.method !== "HEAD") {
442
485
  sendStaticMethodNotAllowed(res, extraHeaders);
443
486
  return true;
444
487
  }
445
- const rawAe = compress ? req.headers["accept-encoding"] : void 0;
488
+ const encodingAllowed = compress && !hasNoTransform((extraHeaders && readHeaderCaseInsensitive(extraHeaders, "cache-control")) ?? entry.original.headers["Cache-Control"]);
489
+ const rawAe = encodingAllowed ? req.headers["accept-encoding"] : void 0;
446
490
  const parsed = typeof rawAe === "string" ? parseAcceptedEncodings(rawAe) : void 0;
447
491
  const availableVariants = [
448
492
  ...entry.zst ? ["zstd"] : [],
449
493
  ...entry.br ? ["br"] : [],
450
494
  ...entry.gz ? ["gzip"] : []
451
495
  ];
452
- const variesByEncoding = compress && availableVariants.length > 0;
496
+ const variesByEncoding = encodingAllowed && availableVariants.length > 0;
453
497
  const selected = parsed ? selectContentEncoding(parsed, availableVariants) : "identity";
454
498
  const variant = selected === "zstd" ? entry.zst : selected === "br" ? entry.br : selected === "gzip" ? entry.gz : entry.original;
499
+ const notModifiedBaseHeaders = encodingAllowed ? entry.notModifiedHeaders : omitVaryToken(entry.notModifiedHeaders, "Accept-Encoding");
500
+ const originalHeaders = encodingAllowed ? entry.original.headers : omitVaryToken(entry.original.headers, "Accept-Encoding");
501
+ const variantHeaders = variant === entry.original ? originalHeaders : variant.headers;
455
502
  const validators = extraHeaders ? resolveStaticValidators(entry.etag, entry.mtimeMs, extraHeaders) : void 0;
456
503
  const effectiveEtag = validators ? validators.etag : entry.etag;
457
504
  const effectiveMtimeMs = validators ? validators.mtimeMs : entry.mtimeMs;
458
505
  const preconditionResult = responseStatus === 200 ? evaluateRequestPreconditions(req, effectiveEtag, effectiveMtimeMs) : "proceed";
459
506
  if (preconditionResult === "precondition-failed") {
460
507
  res.writeHead(412, {
461
- ...entry.notModifiedHeaders,
508
+ ...notModifiedBaseHeaders,
462
509
  ...extraHeaders,
463
510
  "Content-Type": entry.original.headers["Content-Type"],
464
511
  "Accept-Ranges": "bytes"
@@ -468,10 +515,10 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
468
515
  }
469
516
  if (preconditionResult === "not-modified") {
470
517
  const notModifiedHeaders = variesByEncoding ? mergeVaryHeader({
471
- ...entry.notModifiedHeaders,
518
+ ...notModifiedBaseHeaders,
472
519
  ...extraHeaders
473
520
  }, "Accept-Encoding") : {
474
- ...entry.notModifiedHeaders,
521
+ ...notModifiedBaseHeaders,
475
522
  ...extraHeaders
476
523
  };
477
524
  if (selected !== "identity") notModifiedHeaders["Content-Encoding"] = selected;
@@ -482,7 +529,7 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
482
529
  const range = resolveRequestedRange(requestRange, ifRange, entry.original.size, effectiveEtag ?? "", effectiveMtimeMs, responseStatus);
483
530
  if (range.kind === "unsatisfiable") {
484
531
  res.writeHead(416, {
485
- ...entry.notModifiedHeaders,
532
+ ...notModifiedBaseHeaders,
486
533
  ...extraHeaders,
487
534
  "Content-Type": entry.original.headers["Content-Type"],
488
535
  "Accept-Ranges": "bytes",
@@ -494,8 +541,9 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
494
541
  if (range.kind === "range") {
495
542
  const length = range.end - range.start + 1;
496
543
  const rangeHeaders = {
497
- ...entry.original.headers,
544
+ ...originalHeaders,
498
545
  ...extraHeaders,
546
+ ...representationHeaders,
499
547
  "Accept-Ranges": "bytes",
500
548
  "Content-Length": String(length),
501
549
  "Content-Range": `bytes ${range.start}-${range.end}/${entry.original.size}`
@@ -510,8 +558,9 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
510
558
  return true;
511
559
  }
512
560
  const responseHeaders = {
513
- ...variant.headers,
561
+ ...variantHeaders,
514
562
  ...extraHeaders,
563
+ ...representationHeaders,
515
564
  "Accept-Ranges": "bytes"
516
565
  };
517
566
  res.writeHead(responseStatus, variesByEncoding ? mergeVaryHeader(responseHeaders, "Accept-Encoding") : responseHeaders);
@@ -549,8 +598,6 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
549
598
  const isHashed = pathname.includes(`/${ASSET_PREFIX_URL_DIR}/`);
550
599
  const cacheControl = isHashed ? "public, max-age=31536000, immutable" : "public, max-age=3600";
551
600
  const etag = isHashed && etagFromFilenameHash(resolved.path, ext) || `W/"${resolved.size}-${Math.floor(resolved.mtimeMs / 1e3)}"`;
552
- const baseType = ct.split(";")[0].trim();
553
- const isCompressible = compress && COMPRESSIBLE_TYPES.has(baseType);
554
601
  const baseHeaders = {
555
602
  "Content-Type": ct,
556
603
  "Cache-Control": cacheControl,
@@ -559,7 +606,12 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
559
606
  "Accept-Ranges": "bytes",
560
607
  ...extraHeaders
561
608
  };
562
- const encoding = isCompressible ? negotiateEncoding(req) : "identity";
609
+ const { varyAcceptEncoding: isCompressible, encoding } = resolveResponseCompression(req, compress, {
610
+ contentType: ct,
611
+ cacheControl: (extraHeaders && readHeaderCaseInsensitive(extraHeaders, "cache-control")) ?? cacheControl,
612
+ contentEncoding: extraHeaders && readHeaderCaseInsensitive(extraHeaders, "content-encoding"),
613
+ contentLength: resolved.size
614
+ });
563
615
  const validators = extraHeaders ? resolveStaticValidators(etag, resolved.mtimeMs, extraHeaders) : void 0;
564
616
  const effectiveEtag = validators ? validators.etag : etag;
565
617
  const effectiveMtimeMs = validators ? validators.mtimeMs : resolved.mtimeMs;
@@ -595,6 +647,7 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
595
647
  const length = range.end - range.start + 1;
596
648
  const rangeHeaders = {
597
649
  ...baseHeaders,
650
+ ...representationHeaders,
598
651
  "Content-Length": String(length),
599
652
  "Content-Range": `bytes ${range.start}-${range.end}/${resolved.size}`
600
653
  };
@@ -609,6 +662,7 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
609
662
  if (isCompressible && encoding !== "identity") {
610
663
  res.writeHead(responseStatus, mergeVaryHeader({
611
664
  ...baseHeaders,
665
+ ...representationHeaders,
612
666
  "Content-Encoding": encoding
613
667
  }, "Accept-Encoding"));
614
668
  if (omitBody || req.method === "HEAD") {
@@ -626,6 +680,7 @@ async function tryServeStatic(req, res, clientDir, pathname, compress, cache, ex
626
680
  }
627
681
  const identityHeaders = {
628
682
  ...baseHeaders,
683
+ ...representationHeaders,
629
684
  "Content-Length": String(resolved.size)
630
685
  };
631
686
  res.writeHead(responseStatus, isCompressible ? mergeVaryHeader(identityHeaders, "Accept-Encoding") : identityHeaders);
@@ -734,7 +789,7 @@ async function statIfFile(filePath) {
734
789
  * When `urlOverride` is provided, it is used as the path + query string
735
790
  * instead of `req.url`.
736
791
  */
737
- function nodeToWebRequest(req, urlOverride, prerenderSecret, i18nConfig, authorizeOnDemandRevalidate) {
792
+ function nodeToWebRequest(req, urlOverride, prerenderSecret, i18nConfig, authorizeOnDemandRevalidate, signal) {
738
793
  const proto = resolveRequestProtocol(req);
739
794
  const rawHeaders = nodeHeadersToWebHeaders(req.headers);
740
795
  const revalidationHostname = readTrustedRevalidationHostname(rawHeaders, i18nConfig, authorizeOnDemandRevalidate);
@@ -751,9 +806,10 @@ function nodeToWebRequest(req, urlOverride, prerenderSecret, i18nConfig, authori
751
806
  const hasBody = method !== "GET" && method !== "HEAD";
752
807
  const init = {
753
808
  method,
754
- headers
809
+ headers,
810
+ signal
755
811
  };
756
- if (hasBody) {
812
+ if (hasBody && !signal?.aborted) {
757
813
  init.body = readNodeStream(req);
758
814
  init.duplex = "half";
759
815
  }
@@ -776,22 +832,23 @@ async function sendWebResponse(webResponse, req, res, compress) {
776
832
  if (existing !== void 0) nodeHeaders[key] = Array.isArray(existing) ? [...existing, value] : [existing, value];
777
833
  else nodeHeaders[key] = value;
778
834
  });
779
- const alreadyEncoded = webResponse.headers.get("content-encoding") !== null;
780
- if (!webResponse.body) {
781
- writeHead(nodeHeaders);
782
- res.end();
783
- return;
784
- }
785
- const baseType = (webResponse.headers.get("content-type") ?? "").split(";")[0].trim();
786
- const varyByEncoding = compress && !alreadyEncoded && COMPRESSIBLE_TYPES.has(baseType);
787
- const encoding = compress && !alreadyEncoded ? negotiateEncoding(req) : "identity";
788
- const shouldCompress = encoding !== "identity" && COMPRESSIBLE_TYPES.has(baseType);
835
+ const { varyAcceptEncoding: varyByEncoding, encoding } = resolveResponseCompression(req, compress, {
836
+ contentType: webResponse.headers.get("content-type"),
837
+ cacheControl: webResponse.headers.get("cache-control"),
838
+ contentEncoding: webResponse.headers.get("content-encoding"),
839
+ contentLength: webResponse.body ? parseContentLengthHeader(webResponse.headers.get("content-length")) : 0
840
+ });
841
+ const shouldCompress = encoding !== "identity";
789
842
  if (shouldCompress) {
790
843
  delete nodeHeaders["content-length"];
791
- delete nodeHeaders["Content-Length"];
844
+ delete nodeHeaders["content-encoding"];
792
845
  nodeHeaders["Content-Encoding"] = encoding;
793
846
  }
794
847
  writeHead(varyByEncoding ? mergeVaryHeader(nodeHeaders, "Accept-Encoding") : nodeHeaders);
848
+ if (!webResponse.body) {
849
+ res.end();
850
+ return;
851
+ }
795
852
  if (req.method === "HEAD") {
796
853
  cancelResponseBody(webResponse);
797
854
  res.end();
@@ -832,7 +889,7 @@ function waitForNodeResponseCompletion(res) {
832
889
  * Pages Router (dist/server/entry.js) and configures the appropriate handler.
833
890
  */
834
891
  async function startProdServer(options = {}) {
835
- installSocketErrorBackstop();
892
+ installSocketErrorBackstop({ runningServer: options.purpose !== "prerender" });
836
893
  const { port = process.env.PORT ? parseInt(process.env.PORT) : 3e3, host = "0.0.0.0", outDir = path.resolve("dist"), rscEntryPath: explicitRscEntryPath, serverDir: explicitServerDir, serverEntryPath: explicitServerEntryPath, noCompression = false, purpose, silent = false } = options;
837
894
  if (purpose === "prerender") registerPrerenderCloudflareLoader();
838
895
  const compress = !noCompression;
@@ -861,6 +918,7 @@ async function startProdServer(options = {}) {
861
918
  port,
862
919
  host,
863
920
  clientDir,
921
+ serverDir,
864
922
  serverEntryPath,
865
923
  compress,
866
924
  purpose,
@@ -877,6 +935,23 @@ function createNodeExecutionContext(trustedRevalidateOrigin) {
877
935
  trustedRevalidateOrigin
878
936
  };
879
937
  }
938
+ /**
939
+ * Sets the prerender special-error marker only from the page's recorded
940
+ * special error, which middleware, route handlers and external rewrites can't
941
+ * reach, and drops one they set.
942
+ */
943
+ function markPrerenderSpecialError(response, marker) {
944
+ const trusted = marker !== void 0 && marker.status === response.status;
945
+ if (!trusted && !response.headers.has("x-vinext-prerender-special-error")) return response;
946
+ const headers = new Headers(response.headers);
947
+ headers.delete(VINEXT_PRERENDER_SPECIAL_ERROR_HEADER);
948
+ if (trusted) headers.set(VINEXT_PRERENDER_SPECIAL_ERROR_HEADER, JSON.stringify(marker.headers));
949
+ return new Response(response.body, {
950
+ headers,
951
+ status: response.status,
952
+ statusText: response.statusText
953
+ });
954
+ }
880
955
  function resolveTrustedNodeRevalidateOrigin(req, configuredHost, configuredPort) {
881
956
  const port = req.socket.localPort ?? configuredPort;
882
957
  return `http://${normalizeInternalFetchHost(configuredHost)}:${port}`;
@@ -1008,8 +1083,9 @@ function installPagesClientAssets(options) {
1008
1083
  * 4. Stream the Web Response back (with optional compression)
1009
1084
  */
1010
1085
  async function startAppRouterServer(options) {
1011
- const { port, host, clientDir, serverDir, rscEntryPath, compress, purpose, silent } = options;
1086
+ const { port, host, clientDir, serverDir, rscEntryPath, compress: compressOption, purpose, silent } = options;
1012
1087
  const prerenderSecret = readPrerenderSecret(serverDir);
1088
+ const compress = compressOption && readServerCompress(serverDir);
1013
1089
  const rscModule = await importServerEntryModule(rscEntryPath);
1014
1090
  const rscEntryRequire = createServerEntryRequire(rscEntryPath);
1015
1091
  const rscHandler = resolveAppRouterHandler(rscModule.default);
@@ -1045,9 +1121,63 @@ async function startAppRouterServer(options) {
1045
1121
  const seededRoutes = await runWithServerEntryRequire(rscEntryRequire, () => seedPrerenderedRoutes(serverDir));
1046
1122
  if (seededRoutes > 0) console.log(`[vinext] Seeded ${seededRoutes} pre-rendered route${seededRoutes !== 1 ? "s" : ""} into memory cache`);
1047
1123
  const staticCache = await StaticFileCache.create(clientDir);
1124
+ const serveImageOptimization = async (req, res, request, signal) => {
1125
+ const stagedHeaders = omitHeadersCaseInsensitive(mergeResponseHeaders({}, new Response(null, { headers: signal.middlewareHeaders })), OMIT_STATIC_RESPONSE_HEADERS);
1126
+ for (const [name, value] of Object.entries(stagedHeaders)) res.setHeader(name, value);
1127
+ const parsedUrl = new URL(`/${signal.search}`, "http://localhost");
1128
+ const params = parseImageParams(parsedUrl, appImageAllowedWidths, imageConfig?.qualities);
1129
+ if (!params) {
1130
+ res.writeHead(400);
1131
+ res.end("Bad Request");
1132
+ return;
1133
+ }
1134
+ const sendUnsafeContentType = () => {
1135
+ res.writeHead(400);
1136
+ res.end("The requested resource is not an allowed image type");
1137
+ };
1138
+ const isSafeSourcePath = (sourcePath) => isSafeImageContentType(contentTypeForPath(sourcePath), imageConfig?.dangerouslyAllowSVG);
1139
+ const imageSecurityHeaders = {
1140
+ "Content-Security-Policy": imageConfig?.contentSecurityPolicy ?? "script-src 'none'; frame-src 'none'; sandbox;",
1141
+ "X-Content-Type-Options": "nosniff",
1142
+ "Content-Disposition": imageConfig?.contentDispositionType === "attachment" ? "attachment" : "inline"
1143
+ };
1144
+ const serveSource = (sourcePath) => tryServeStatic(req, res, clientDir, sourcePath, false, staticCache, imageSecurityHeaders, void 0, IMAGE_REPRESENTATION_HEADERS);
1145
+ const sourceUrl = new URL(params.imageUrl, request.url);
1146
+ let sourcePathname = null;
1147
+ try {
1148
+ sourcePathname = normalizePath(normalizePathnameForRouteMatchStrict(sourceUrl.pathname));
1149
+ } catch {}
1150
+ if (!isSafeSourcePath(sourcePathname ?? params.imageUrl)) {
1151
+ sendUnsafeContentType();
1152
+ return;
1153
+ }
1154
+ const assetLookupPath = sourcePathname !== null ? resolveAppRouterAssetPath(sourcePathname, appAssetPathPrefix, appRouterAssetPrefix) : null;
1155
+ if (assetLookupPath && await serveSource(assetLookupPath)) return;
1156
+ if (sourcePathname !== null) {
1157
+ const sourceResponse = await rscHandler(new Request(sourceUrl, { signal: request.signal }), createNodeExecutionContext(resolveTrustedNodeRevalidateOrigin(req, host, port)));
1158
+ const sourceSignal = isImageSourceBodyStatus(sourceResponse.status) ? readStaticFileSignal(sourceResponse) : null;
1159
+ cancelResponseBody(sourceResponse, request.signal.reason);
1160
+ if (request.signal.aborted) return;
1161
+ if (sourceSignal !== null) {
1162
+ let sourcePath = sourceSignal;
1163
+ try {
1164
+ sourcePath = decodeURIComponent(sourceSignal);
1165
+ } catch {}
1166
+ if (!isSafeSourcePath(sourcePath)) {
1167
+ sendUnsafeContentType();
1168
+ return;
1169
+ }
1170
+ if (await serveSource(sourcePath)) return;
1171
+ }
1172
+ }
1173
+ res.writeHead(400);
1174
+ res.end(INVALID_IMAGE_SOURCE_MESSAGE);
1175
+ };
1176
+ const clientBuildFiles = new Set(Array.isArray(rscModule.__clientBuildFiles) ? rscModule.__clientBuildFiles : []);
1048
1177
  const handleRequestImpl = async (req, res) => {
1049
1178
  const rawUrl = req.url ?? "/";
1050
1179
  const rawPathname = rawUrl.split("?")[0];
1180
+ if (sendRepeatedSlashRedirect(rawUrl, res)) return;
1051
1181
  if (isOpenRedirectShaped(rawPathname)) {
1052
1182
  res.writeHead(404);
1053
1183
  res.end("This page could not be found");
@@ -1076,33 +1206,28 @@ async function startAppRouterServer(options) {
1076
1206
  if (await tryServeStatic(req, res, clientDir, assetLookupPath, compress, staticCache)) return;
1077
1207
  }
1078
1208
  }
1079
- if (isImageOptimizationPath(pathname)) {
1080
- const parsedUrl = new URL(rawUrl, "http://localhost");
1081
- const params = parseImageParams(parsedUrl, appImageAllowedWidths, imageConfig?.qualities);
1082
- if (!params) {
1083
- res.writeHead(400);
1084
- res.end("Bad Request");
1209
+ if (req.method === "GET" || req.method === "HEAD") {
1210
+ const clientBuildFile = resolveClientBuildFile(normalizedRawPathname, appRouterBasePath, clientBuildFiles);
1211
+ if (clientBuildFile && await tryServeStatic(req, res, clientDir, clientBuildFile, compress, staticCache)) return;
1212
+ }
1213
+ try {
1214
+ const request = nodeToWebRequest(req, rawUrl, prerenderSecret, appRouterI18nConfig, appRouterAuthorizeOnDemandRevalidate, signalFromNodeResponse(res));
1215
+ const ctx = createNodeExecutionContext(resolveTrustedNodeRevalidateOrigin(req, host, port));
1216
+ const recorded = {};
1217
+ if (purpose === "prerender") ctx.recordPrerenderSpecialError = (marker) => {
1218
+ recorded.marker = marker;
1219
+ };
1220
+ const response = await rscHandler(request, ctx);
1221
+ if (request.signal.aborted) {
1222
+ cancelResponseBody(response, request.signal.reason);
1085
1223
  return;
1086
1224
  }
1087
- const ct = contentTypeForPath(params.imageUrl);
1088
- if (!isSafeImageContentType(ct, imageConfig?.dangerouslyAllowSVG)) {
1089
- res.writeHead(400);
1090
- res.end("The requested resource is not an allowed image type");
1225
+ const imageSignal = readImageOptimizationSignal(response);
1226
+ if (imageSignal) {
1227
+ cancelResponseBody(response);
1228
+ await serveImageOptimization(req, res, request, imageSignal);
1091
1229
  return;
1092
1230
  }
1093
- const imageSecurityHeaders = {
1094
- "Content-Security-Policy": imageConfig?.contentSecurityPolicy ?? "script-src 'none'; frame-src 'none'; sandbox;",
1095
- "X-Content-Type-Options": "nosniff",
1096
- "Content-Disposition": imageConfig?.contentDispositionType === "attachment" ? "attachment" : "inline"
1097
- };
1098
- if (await tryServeStatic(req, res, clientDir, params.imageUrl, false, staticCache, imageSecurityHeaders)) return;
1099
- res.writeHead(404);
1100
- res.end("Image not found");
1101
- return;
1102
- }
1103
- try {
1104
- const request = nodeToWebRequest(req, rawUrl, prerenderSecret, appRouterI18nConfig, appRouterAuthorizeOnDemandRevalidate);
1105
- const response = await rscHandler(request, createNodeExecutionContext(resolveTrustedNodeRevalidateOrigin(req, host, port)));
1106
1231
  const staticFileSignal = readStaticFileSignal(response);
1107
1232
  if (staticFileSignal) {
1108
1233
  let staticFilePath = "/";
@@ -1118,7 +1243,7 @@ async function startAppRouterServer(options) {
1118
1243
  await sendWebResponse(notFoundResponse({ headers: toWebHeaders(staticResponseHeaders) }), req, res, compress);
1119
1244
  return;
1120
1245
  }
1121
- await sendWebResponse(response, req, res, compress);
1246
+ await sendWebResponse(purpose === "prerender" ? markPrerenderSpecialError(response, recorded.marker) : response, req, res, compress);
1122
1247
  } catch (e) {
1123
1248
  console.error("[vinext] Server error:", e);
1124
1249
  if (!res.headersSent) {
@@ -1149,7 +1274,7 @@ async function startAppRouterServer(options) {
1149
1274
  },
1150
1275
  getStatus: () => res.statusCode,
1151
1276
  headers,
1152
- isRsc: new URL(target, "http://localhost").pathname.endsWith(".rsc") || headers.get("RSC") === "1",
1277
+ isRsc: target.split("?", 1)[0].endsWith(".rsc") || headers.get("RSC") === "1",
1153
1278
  method: req.method ?? "GET",
1154
1279
  target
1155
1280
  });
@@ -1195,7 +1320,45 @@ function readPagesServerEntryPageRoutes(value) {
1195
1320
  * - vinextConfig — embedded next.config.js settings
1196
1321
  */
1197
1322
  async function startPagesRouterServer(options) {
1198
- const { port, host, clientDir, serverEntryPath, compress, purpose, silent } = options;
1323
+ const { port, host, purpose, silent } = options;
1324
+ const handler = await createPagesRouterRequestHandler(options);
1325
+ const server = createServer(handler);
1326
+ await new Promise((resolve) => {
1327
+ server.listen(port, host, () => {
1328
+ const addr = server.address();
1329
+ const actualPort = typeof addr === "object" && addr ? addr.port : port;
1330
+ if (!silent) logProdServerStarted(host, actualPort, purpose);
1331
+ resolve();
1332
+ });
1333
+ });
1334
+ const addr = server.address();
1335
+ return {
1336
+ server,
1337
+ port: typeof addr === "object" && addr ? addr.port : port
1338
+ };
1339
+ }
1340
+ /**
1341
+ * Create the Pages Router request handler for `vite preview`. Vite's preview
1342
+ * middleware (proxy, compression, `base`, static files) runs first, so this
1343
+ * handles only the requests Vite doesn't serve and leaves compression to Vite.
1344
+ * Resolves to null when the build has no Pages Router server entry.
1345
+ */
1346
+ async function createPagesPreviewHandler(options) {
1347
+ const clientDir = path.resolve(options.clientDir);
1348
+ const serverDir = path.resolve(options.serverDir);
1349
+ const serverEntryPath = path.join(serverDir, "entry.js");
1350
+ if (!fs.existsSync(serverEntryPath)) return null;
1351
+ return createPagesRouterRequestHandler({
1352
+ port: options.port,
1353
+ host: options.host,
1354
+ clientDir,
1355
+ serverDir,
1356
+ serverEntryPath,
1357
+ compress: false
1358
+ });
1359
+ }
1360
+ async function createPagesRouterRequestHandler(options) {
1361
+ const { port, host, clientDir, serverDir, serverEntryPath, compress: compressOption, purpose } = options;
1199
1362
  const serverEntry = await importServerEntryModule(serverEntryPath);
1200
1363
  const serverEntryRequire = createServerEntryRequire(serverEntryPath);
1201
1364
  const { renderPage, handleApiRoute: handleApi, authorizeOnDemandRevalidate, runMiddleware, vinextConfig, buildId: pagesBuildId } = serverEntry;
@@ -1205,11 +1368,13 @@ async function startPagesRouterServer(options) {
1205
1368
  const hasMiddleware = serverEntry.hasMiddleware === true;
1206
1369
  const pageRoutes = readPagesServerEntryPageRoutes(serverEntry.pageRoutes);
1207
1370
  const prerenderSecret = readPrerenderSecret(path.dirname(serverEntryPath));
1371
+ const compress = compressOption && readServerCompress(serverDir);
1208
1372
  const basePath = vinextConfig?.basePath ?? "";
1209
1373
  const assetPrefix = vinextConfig?.assetPrefix ?? "";
1210
1374
  const pagesAssetPathPrefix = assetPrefixPathname(assetPrefix);
1211
1375
  const assetBase = basePath ? `${basePath}/` : "/";
1212
1376
  const trailingSlash = vinextConfig?.trailingSlash ?? false;
1377
+ const skipTrailingSlashRedirect = vinextConfig?.skipTrailingSlashRedirect ?? false;
1213
1378
  const skipProxyUrlNormalize = vinextConfig?.skipProxyUrlNormalize ?? false;
1214
1379
  const i18nConfig = vinextConfig?.i18n ?? null;
1215
1380
  const configRedirects = vinextConfig?.redirects ?? [];
@@ -1261,6 +1426,7 @@ async function startPagesRouterServer(options) {
1261
1426
  const handleRequestImpl = async (req, res) => {
1262
1427
  const rawUrl = req.url ?? "/";
1263
1428
  const rawPagesPathnameBeforeNormalize = rawUrl.split("?")[0];
1429
+ if (sendRepeatedSlashRedirect(rawUrl, res)) return;
1264
1430
  if (isOpenRedirectShaped(rawPagesPathnameBeforeNormalize)) {
1265
1431
  res.writeHead(404);
1266
1432
  res.end("This page could not be found");
@@ -1366,18 +1532,55 @@ async function startPagesRouterServer(options) {
1366
1532
  const reqHeaders = filterInternalHeaders(rawReqHeaders);
1367
1533
  if (revalidationHostname) reqHeaders.set("host", revalidationHostname);
1368
1534
  const method = req.method ?? "GET";
1369
- const hasBody = method !== "GET" && method !== "HEAD";
1370
- const webRequest = new Request(`${protocol}://${revalidationHostname ?? hostHeader}${url}`, {
1535
+ const signal = signalFromNodeResponse(res);
1536
+ const hasBody = method !== "GET" && method !== "HEAD" && !signal.aborted;
1537
+ const requestOrigin = `${protocol}://${revalidationHostname ?? hostHeader}`;
1538
+ const webRequest = new Request(new URL(url, requestOrigin), {
1371
1539
  method,
1372
1540
  headers: reqHeaders,
1541
+ signal,
1373
1542
  body: hasBody ? readNodeStream(req) : void 0,
1374
1543
  duplex: hasBody ? "half" : void 0
1375
1544
  });
1376
1545
  const middlewareRequest = isDataReq && skipProxyUrlNormalize ? new Request(new URL(originalRenderUrl, webRequest.url), webRequest) : void 0;
1546
+ const resolvePublicImageSource = async (sourceUrl) => {
1547
+ const rawSourcePathname = sourceUrl.pathname;
1548
+ if (getRepeatedSlashRedirect(rawSourcePathname) || isOpenRedirectShaped(rawSourcePathname)) return null;
1549
+ const sourceRequestPathname = normalizePath(rawSourcePathname);
1550
+ const sourceHadBasePath = !basePath || hasBasePath(sourceRequestPathname, basePath);
1551
+ const strippedSourcePathname = stripBasePath(sourceRequestPathname, basePath);
1552
+ if (isNextDataPathname(strippedSourcePathname)) return null;
1553
+ let sourcePath = null;
1554
+ const result = await runPagesRequest(new Request(new URL(strippedSourcePathname + sourceUrl.search, sourceUrl), { signal: webRequest.signal }), {
1555
+ ...deps,
1556
+ hadBasePath: sourceHadBasePath,
1557
+ isDataReq: false,
1558
+ isDataRequest: false,
1559
+ middlewareRequest: void 0,
1560
+ dataNotFoundResponse: null,
1561
+ recordCacheability: false,
1562
+ rawSearch: sourceUrl.search,
1563
+ configMatchPathname: strippedSourcePathname,
1564
+ runMiddleware: typeof runMiddleware === "function" ? wrapMiddlewareWithBasePath(runMiddleware, basePath, sourceHadBasePath) : null,
1565
+ renderPage: null,
1566
+ handleApi: null,
1567
+ serveFilesystemRoute: async (candidate, _stagedHeaders, phase) => {
1568
+ if (isImageOptimizationPath(candidate) || isPagesFilesystemExcludedPath(candidate, phase)) return false;
1569
+ const lookupPath = staticCacheLookupPath(candidate);
1570
+ if (lookupPath === null || lookupPath === "/" || !staticCache.lookup(lookupPath)) return false;
1571
+ sourcePath = candidate;
1572
+ return new Response(null);
1573
+ }
1574
+ });
1575
+ if (result.type !== "response") return null;
1576
+ cancelResponseBody(result.response);
1577
+ return isImageSourceBodyStatus(result.response.status) ? sourcePath : null;
1578
+ };
1377
1579
  const deps = {
1378
1580
  assetPrefix,
1379
1581
  basePath,
1380
1582
  trailingSlash,
1583
+ skipTrailingSlashRedirect,
1381
1584
  i18nConfig,
1382
1585
  configRedirects,
1383
1586
  configRewrites,
@@ -1400,8 +1603,8 @@ async function startPagesRouterServer(options) {
1400
1603
  originalUrl: originalRenderUrl
1401
1604
  }, stagedHeaders?.has("Cache-Control") ? new Headers({ "Cache-Control": stagedHeaders.get("Cache-Control") }) : void 0) : null,
1402
1605
  handleApi: typeof handleApi === "function" ? (request, apiUrl) => handleApi(request, apiUrl, createNodeExecutionContext(), resolveTrustedNodeRevalidateOrigin(req, host, port), "node") : null,
1403
- serveFilesystemRoute: async (requestPathname, stagedHeaders, phase, resolvedUrl) => {
1404
- if (isImageOptimizationPath(requestPathname)) {
1606
+ serveFilesystemRoute: async (requestPathname, stagedHeaders, phase, resolvedUrl, _request, resolvedPathnameHasBasePath) => {
1607
+ if (resolvedPathnameHasBasePath && isImageOptimizationPath(requestPathname)) {
1405
1608
  for (const [name, value] of Object.entries(stagedHeaders)) res.setHeader(name, value);
1406
1609
  const parsedUrl = new URL(resolvedUrl, "http://localhost");
1407
1610
  const params = parseImageParams(parsedUrl, allowedImageWidths, pagesImageConfig?.qualities);
@@ -1410,23 +1613,42 @@ async function startPagesRouterServer(options) {
1410
1613
  res.end("Bad Request");
1411
1614
  return true;
1412
1615
  }
1413
- const ct = contentTypeForPath(params.imageUrl);
1414
- if (!isSafeImageContentType(ct, pagesImageConfig?.dangerouslyAllowSVG)) {
1616
+ const sendUnsafeContentType = () => {
1415
1617
  res.writeHead(400);
1416
1618
  res.end("The requested resource is not an allowed image type");
1417
- return true;
1418
- }
1619
+ };
1620
+ const isSafeSourcePath = (sourcePath) => isSafeImageContentType(contentTypeForPath(sourcePath), pagesImageConfig?.dangerouslyAllowSVG);
1419
1621
  const imageSecurityHeaders = {
1420
1622
  "Content-Security-Policy": pagesImageConfig?.contentSecurityPolicy ?? "script-src 'none'; frame-src 'none'; sandbox;",
1421
1623
  "X-Content-Type-Options": "nosniff",
1422
1624
  "Content-Disposition": pagesImageConfig?.contentDispositionType === "attachment" ? "attachment" : "inline"
1423
1625
  };
1424
- if (await tryServeStatic(req, res, clientDir, params.imageUrl, false, staticCache, imageSecurityHeaders)) return true;
1425
- res.writeHead(404);
1426
- res.end("Image not found");
1626
+ const serveSource = (sourcePath) => tryServeStatic(req, res, clientDir, sourcePath, false, staticCache, imageSecurityHeaders, void 0, IMAGE_REPRESENTATION_HEADERS);
1627
+ const sourceUrl = new URL(params.imageUrl, webRequest.url);
1628
+ let sourcePathname = null;
1629
+ try {
1630
+ sourcePathname = normalizePath(normalizePathnameForRouteMatchStrict(sourceUrl.pathname));
1631
+ } catch {}
1632
+ if (!isSafeSourcePath(sourcePathname ?? params.imageUrl)) {
1633
+ sendUnsafeContentType();
1634
+ return true;
1635
+ }
1636
+ const assetLookupPath = sourcePathname !== null ? resolveAppRouterAssetPath(sourcePathname, pagesAssetPathPrefix, assetPrefix) : null;
1637
+ if (assetLookupPath && await serveSource(assetLookupPath)) return true;
1638
+ const sourcePath = sourcePathname !== null ? await resolvePublicImageSource(sourceUrl) : null;
1639
+ if (webRequest.signal.aborted) return true;
1640
+ if (sourcePath !== null) {
1641
+ if (!isSafeSourcePath(staticCacheLookupPath(sourcePath) ?? sourcePath)) {
1642
+ sendUnsafeContentType();
1643
+ return true;
1644
+ }
1645
+ if (await serveSource(sourcePath)) return true;
1646
+ }
1647
+ res.writeHead(400);
1648
+ res.end(INVALID_IMAGE_SOURCE_MESSAGE);
1427
1649
  return true;
1428
1650
  }
1429
- if (requestPathname === "/" || requestPathname === "/api" || requestPathname.startsWith("/api/") || phase === "direct" && requestPathname.startsWith(`/_next/static/`)) return false;
1651
+ if (isPagesFilesystemExcludedPath(requestPathname, phase)) return false;
1430
1652
  return tryServeStatic(req, res, clientDir, requestPathname, compress, staticCache, stagedHeaders);
1431
1653
  }
1432
1654
  };
@@ -1434,13 +1656,18 @@ async function startPagesRouterServer(options) {
1434
1656
  if (result.type === "handled") return;
1435
1657
  if (result.type === "response") {
1436
1658
  const { response } = result;
1659
+ if (webRequest.signal.aborted) {
1660
+ cancelResponseBody(response, webRequest.signal.reason);
1661
+ return;
1662
+ }
1437
1663
  const streamedApi = isVinextStreamedApiResponse(response);
1438
1664
  if (isVinextStreamedHtmlResponse(response) || streamedApi || !response.body || result.defaultContentType === void 0) {
1439
1665
  if (streamedApi && result.defaultContentType !== void 0 && !response.headers.has("content-type")) response.headers.set("content-type", result.defaultContentType);
1440
1666
  await sendWebResponse(response, req, res, compress);
1441
1667
  return;
1442
1668
  }
1443
- const responseBody = Buffer.from(await response.arrayBuffer());
1669
+ const responseBody = await bufferResponseBodyUntilAborted(response, webRequest.signal);
1670
+ if (!responseBody) return;
1444
1671
  const ct = response.headers.get("content-type") ?? result.defaultContentType;
1445
1672
  const responseHeaders = {};
1446
1673
  response.headers.forEach((v, k) => {
@@ -1464,22 +1691,9 @@ async function startPagesRouterServer(options) {
1464
1691
  }
1465
1692
  }
1466
1693
  };
1467
- const server = createServer((req, res) => {
1694
+ return (req, res) => {
1468
1695
  runWithServerEntryRequire(serverEntryRequire, () => handleRequest(req, res));
1469
- });
1470
- await new Promise((resolve) => {
1471
- server.listen(port, host, () => {
1472
- const addr = server.address();
1473
- const actualPort = typeof addr === "object" && addr ? addr.port : port;
1474
- if (!silent) logProdServerStarted(host, actualPort, purpose);
1475
- resolve();
1476
- });
1477
- });
1478
- const addr = server.address();
1479
- return {
1480
- server,
1481
- port: typeof addr === "object" && addr ? addr.port : port
1482
1696
  };
1483
1697
  }
1484
1698
  //#endregion
1485
- export { COMPRESSIBLE_TYPES, COMPRESS_THRESHOLD, importServerEntryModule, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, readNodeStream, rememberCurrentServerEntryImportMtime, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, resolveServerEntryImportUrl, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic, waitForNodeResponseCompletion };
1699
+ export { COMPRESS_THRESHOLD, createPagesPreviewHandler, importServerEntryModule, isCompressibleContentType, mergeResponseHeaders, mergeWebResponse, negotiateEncoding, nodeToWebRequest, readNodeStream, rememberCurrentServerEntryImportMtime, resolveAppRouterAssetPath, resolveAppRouterPrerenderSeeder, resolveRequestHost as resolveHost, resolveServerEntryImportUrl, sendCompressed, sendWebResponse, startProdServer, trustProxy, trustedHosts, tryServeStatic, waitForNodeResponseCompletion };