@wular/pnext 0.1.5 → 0.1.7

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 (302) hide show
  1. package/bin/pnext +9 -2
  2. package/dist/server/_chunks/aliases-j47a10ce.js +44 -0
  3. package/dist/server/_chunks/analyze-arswqe6s.js +445 -0
  4. package/dist/server/_chunks/boot-af0mv3dy.js +36 -0
  5. package/dist/server/_chunks/build-spy3dxp4.js +84 -0
  6. package/dist/server/_chunks/build-t9h0hec3.js +3550 -0
  7. package/dist/server/_chunks/build-tier-m7yvqz61.js +2472 -0
  8. package/dist/server/_chunks/compile-53j02j27.js +22 -0
  9. package/dist/server/_chunks/config-1yzwexq6.js +27 -0
  10. package/dist/server/_chunks/config-n2z7yxps.js +22 -0
  11. package/dist/server/_chunks/create-meec9hs6.js +134 -0
  12. package/dist/server/_chunks/dev-fjmqg6en.js +220 -0
  13. package/dist/server/_chunks/esbuild-yyktfrtt.js +15 -0
  14. package/dist/server/_chunks/generate-n9sh6hzt.js +21 -0
  15. package/dist/server/_chunks/index-0374j2b9.js +66 -0
  16. package/dist/server/_chunks/index-06nyqntx.js +213 -0
  17. package/dist/server/_chunks/index-1011cscr.js +5263 -0
  18. package/dist/server/_chunks/index-11sfk4hb.js +170 -0
  19. package/dist/server/_chunks/index-20ppawv7.js +297 -0
  20. package/dist/server/_chunks/index-2dv4y4wd.js +1065 -0
  21. package/dist/server/_chunks/index-2vz0wzdn.js +59 -0
  22. package/dist/server/_chunks/index-2wfv4kvx.js +182 -0
  23. package/dist/server/_chunks/index-357na4a8.js +109 -0
  24. package/dist/server/_chunks/index-3b3at80h.js +109 -0
  25. package/dist/server/_chunks/index-3tf1xjsp.js +6166 -0
  26. package/dist/server/_chunks/index-3xbr4eyv.js +105 -0
  27. package/dist/server/_chunks/index-4399bvd2.js +18 -0
  28. package/dist/server/_chunks/index-4hgjrqh7.js +851 -0
  29. package/dist/server/_chunks/index-4q2gbfwk.js +2530 -0
  30. package/dist/server/_chunks/index-4t92hdxd.js +172 -0
  31. package/dist/server/_chunks/index-4zzebszd.js +10 -0
  32. package/dist/server/_chunks/index-5gyr4emz.js +107 -0
  33. package/dist/server/_chunks/index-5hr4062s.js +70 -0
  34. package/dist/server/_chunks/index-68m3mwbd.js +84 -0
  35. package/dist/server/_chunks/index-6b009mt0.js +56 -0
  36. package/dist/server/_chunks/index-6e4fqv30.js +588 -0
  37. package/dist/server/_chunks/index-6gex3pfa.js +15 -0
  38. package/dist/server/_chunks/index-6kp9r0d9.js +11 -0
  39. package/dist/server/_chunks/index-6q7zvrap.js +134 -0
  40. package/dist/server/_chunks/index-73z4esab.js +38 -0
  41. package/dist/server/_chunks/index-79ngvam8.js +60 -0
  42. package/dist/server/_chunks/index-7wc9n8be.js +25 -0
  43. package/dist/server/_chunks/index-8k7pfejn.js +1599 -0
  44. package/dist/server/_chunks/index-8kcxdfya.js +206 -0
  45. package/dist/server/_chunks/index-91x12ykq.js +274 -0
  46. package/dist/server/_chunks/index-9ch50vtq.js +18 -0
  47. package/dist/server/_chunks/index-9hx2641q.js +28 -0
  48. package/dist/server/_chunks/index-9n2914ww.js +535 -0
  49. package/dist/server/_chunks/index-9ych9ma8.js +207 -0
  50. package/dist/server/_chunks/index-b6wtkdp4.js +24 -0
  51. package/dist/server/_chunks/index-bcws5eh2.js +35 -0
  52. package/dist/server/_chunks/index-c0g2wf3z.js +92 -0
  53. package/dist/server/_chunks/index-cf4rvxv6.js +95 -0
  54. package/dist/server/_chunks/index-cjgqs13g.js +65 -0
  55. package/dist/server/_chunks/index-ckkdpht5.js +41 -0
  56. package/dist/server/_chunks/index-cyfednwb.js +87 -0
  57. package/dist/server/_chunks/index-danncfhy.js +311 -0
  58. package/dist/server/_chunks/index-dg0f05zs.js +199 -0
  59. package/dist/server/_chunks/index-e3a6yx84.js +18 -0
  60. package/dist/server/_chunks/index-e88tyv35.js +45 -0
  61. package/dist/server/_chunks/index-eajaspjk.js +1253 -0
  62. package/dist/server/_chunks/index-eeaanp2e.js +483 -0
  63. package/dist/server/_chunks/index-egykcqg3.js +101 -0
  64. package/dist/server/_chunks/index-en7n9f7m.js +22 -0
  65. package/dist/server/_chunks/index-ezgj0tr1.js +88 -0
  66. package/dist/server/_chunks/index-fkp000p1.js +590 -0
  67. package/dist/server/_chunks/index-fn1chkkd.js +214 -0
  68. package/dist/server/_chunks/index-fp8r0sqs.js +64 -0
  69. package/dist/server/_chunks/index-ggk2j965.js +9432 -0
  70. package/dist/server/_chunks/index-grta8ap3.js +238 -0
  71. package/dist/server/_chunks/index-h2a70tg4.js +7 -0
  72. package/dist/server/_chunks/index-h4xy648y.js +51 -0
  73. package/dist/server/_chunks/index-hkdfj58q.js +92 -0
  74. package/dist/server/_chunks/index-j2zrcp1k.js +66 -0
  75. package/dist/server/_chunks/index-jcsjq3d1.js +20 -0
  76. package/dist/server/_chunks/index-jepjvcrf.js +198 -0
  77. package/dist/server/_chunks/index-jks0x0a1.js +14 -0
  78. package/dist/server/_chunks/index-jx7bqvw1.js +57 -0
  79. package/dist/server/_chunks/index-k1g3epw0.js +1299 -0
  80. package/dist/server/_chunks/index-knp0s912.js +7 -0
  81. package/dist/server/_chunks/index-kq8kpzye.js +472 -0
  82. package/dist/server/_chunks/index-kqyy1d4f.js +50 -0
  83. package/dist/server/_chunks/index-kresp2n8.js +445 -0
  84. package/dist/server/_chunks/index-ms9v9tnx.js +31 -0
  85. package/dist/server/_chunks/index-n4hxpng2.js +11 -0
  86. package/dist/server/_chunks/index-ncnes8c6.js +17 -0
  87. package/dist/server/_chunks/index-nqh3xhdc.js +57 -0
  88. package/dist/server/_chunks/index-nyrba2kr.js +4130 -0
  89. package/dist/server/_chunks/index-p77b4kcx.js +296 -0
  90. package/dist/server/_chunks/index-pym1cezq.js +39 -0
  91. package/dist/server/_chunks/index-q738kkhj.js +100 -0
  92. package/dist/server/_chunks/index-qjj6gddn.js +54 -0
  93. package/dist/server/_chunks/index-qm6kmhqs.js +110 -0
  94. package/dist/server/_chunks/index-qn4z5s3c.js +819 -0
  95. package/dist/server/_chunks/index-qpwsgt3a.js +158 -0
  96. package/dist/server/_chunks/index-r97ptz1q.js +97 -0
  97. package/dist/server/_chunks/index-ras0sdab.js +26 -0
  98. package/dist/server/_chunks/index-rcs322t1.js +19 -0
  99. package/dist/server/_chunks/index-rn8dyr1f.js +126 -0
  100. package/dist/server/_chunks/index-rt9qq1va.js +4 -0
  101. package/dist/server/_chunks/index-rthrsed5.js +356 -0
  102. package/dist/server/_chunks/index-sctcgyvv.js +185 -0
  103. package/dist/server/_chunks/index-sjpckxqn.js +213 -0
  104. package/dist/server/_chunks/index-sq3kvz3g.js +200 -0
  105. package/dist/server/_chunks/index-stbk3jhn.js +31 -0
  106. package/dist/server/_chunks/index-sv8m6789.js +266 -0
  107. package/dist/server/_chunks/index-tgcakdxc.js +125 -0
  108. package/dist/server/_chunks/index-tgsfjmep.js +74 -0
  109. package/dist/server/_chunks/index-tq0pc7eg.js +154 -0
  110. package/dist/server/_chunks/index-tq1f96v7.js +51 -0
  111. package/dist/server/_chunks/index-tqn2qnnn.js +241 -0
  112. package/dist/server/_chunks/index-tvqkq6e6.js +128 -0
  113. package/dist/server/_chunks/index-v1ags1na.js +132 -0
  114. package/dist/server/_chunks/index-vvmmknm1.js +1431 -0
  115. package/dist/server/_chunks/index-vvq7rqtn.js +329 -0
  116. package/dist/server/_chunks/index-vz0km5qk.js +33 -0
  117. package/dist/server/_chunks/index-w6h8m6vp.js +138 -0
  118. package/dist/server/_chunks/index-web361b8.js +138 -0
  119. package/dist/server/_chunks/index-wpfhfbs4.js +194 -0
  120. package/dist/server/_chunks/index-x0y005nh.js +283 -0
  121. package/dist/server/_chunks/index-x3yn4ywm.js +22 -0
  122. package/dist/server/_chunks/index-x93hv0sc.js +271 -0
  123. package/dist/server/_chunks/index-xvj80c3a.js +30 -0
  124. package/dist/server/_chunks/index-xywjg2vc.js +100 -0
  125. package/dist/server/_chunks/index-y2jr2n72.js +152 -0
  126. package/dist/server/_chunks/index-y36a0ybw.js +57 -0
  127. package/dist/server/_chunks/index-ye9hmsvf.js +47 -0
  128. package/dist/server/_chunks/index-yhxkxghe.js +56 -0
  129. package/dist/server/_chunks/index-ym67zqxp.js +130 -0
  130. package/dist/server/_chunks/index-ytjvpbm2.js +736 -0
  131. package/dist/server/_chunks/index-yz54pxrh.js +960 -0
  132. package/dist/server/_chunks/index-z4z9zv3b.js +733 -0
  133. package/dist/server/_chunks/index-z84ab1w0.js +1270 -0
  134. package/dist/server/_chunks/index-z88qv16t.js +11 -0
  135. package/dist/server/_chunks/index-zqpqyg8p.js +666 -0
  136. package/dist/server/_chunks/loader-7yw0j98z.js +78 -0
  137. package/dist/server/_chunks/modules-jn8bmbn8.js +74 -0
  138. package/dist/server/_chunks/pipeline-yy9jhydf.js +832 -0
  139. package/dist/server/_chunks/production-jar9ztm3.js +44 -0
  140. package/dist/server/_chunks/proxy-config-j84dgksn.js +21 -0
  141. package/dist/server/_chunks/proxy-w1d0wmsn.js +33 -0
  142. package/dist/server/_chunks/router-k1reahfn.js +498 -0
  143. package/dist/server/_chunks/routes-2s277fc6.js +64 -0
  144. package/dist/server/_chunks/run-pvd8bs1t.js +696 -0
  145. package/dist/server/_chunks/server-mt4a994c.js +1835 -0
  146. package/dist/server/_chunks/tsconfig-defaults-1nb3308g.js +20 -0
  147. package/dist/server/_chunks/typegen-0qr0459b.js +35 -0
  148. package/dist/server/api/client-cache.js +14 -0
  149. package/dist/server/cli/index.js +378 -0
  150. package/dist/server/cli/start.js +137 -0
  151. package/dist/server/client/reference.js +16 -0
  152. package/dist/server/compat/next/cache.js +56 -0
  153. package/dist/server/compat/next/canonical-url.js +13 -0
  154. package/dist/server/compat/next/client-cache.js +57 -0
  155. package/dist/server/compat/next/client-navigation.js +232 -0
  156. package/dist/server/compat/next/client-only.js +1 -0
  157. package/dist/server/compat/next/client-script.js +178 -0
  158. package/dist/server/compat/next/client-server.js +34 -0
  159. package/dist/server/compat/next/config-headers.js +32 -0
  160. package/dist/server/compat/next/config-loader.js +25 -0
  161. package/dist/server/compat/next/config.js +10 -0
  162. package/dist/server/compat/next/constants.js +18 -0
  163. package/dist/server/compat/next/custom-server.js +10 -0
  164. package/dist/server/compat/next/dist/client/components/app-router-headers.js +48 -0
  165. package/dist/server/compat/next/dist/server/web/spec-extension/revalidate.js +27 -0
  166. package/dist/server/compat/next/dist/server/web/spec-extension/unstable-cache.js +25 -0
  167. package/dist/server/compat/next/dist/server/web/spec-extension/unstable-no-store.js +25 -0
  168. package/dist/server/compat/next/dynamic.js +32 -0
  169. package/dist/server/compat/next/error.js +112 -0
  170. package/dist/server/compat/next/font/cache.js +14 -0
  171. package/dist/server/compat/next/font/google.js +3 -0
  172. package/dist/server/compat/next/font/index.js +1 -0
  173. package/dist/server/compat/next/font/local.js +22 -0
  174. package/dist/server/compat/next/font/runtime-client.js +33 -0
  175. package/dist/server/compat/next/font/runtime.js +41 -0
  176. package/dist/server/compat/next/font/shared.js +22 -0
  177. package/dist/server/compat/next/form.js +129 -0
  178. package/dist/server/compat/next/head.js +10 -0
  179. package/dist/server/compat/next/headers.js +30 -0
  180. package/dist/server/compat/next/image/client.js +11 -0
  181. package/dist/server/compat/next/image/config.js +18 -0
  182. package/dist/server/compat/next/image/optimizer.js +25 -0
  183. package/dist/server/compat/next/image/patterns.js +12 -0
  184. package/dist/server/compat/next/image/props.js +16 -0
  185. package/dist/server/compat/next/image/shared.js +86 -0
  186. package/dist/server/compat/next/image/static-metadata.js +32 -0
  187. package/dist/server/compat/next/image/validate.js +8 -0
  188. package/dist/server/compat/next/image.js +59 -0
  189. package/dist/server/compat/next/index.js +1 -0
  190. package/dist/server/compat/next/legacy-image.js +78 -0
  191. package/dist/server/compat/next/legacy-request-apis.js +24 -0
  192. package/dist/server/compat/next/link-transform.js +14 -0
  193. package/dist/server/compat/next/link.js +14 -0
  194. package/dist/server/compat/next/navigation.js +190 -0
  195. package/dist/server/compat/next/offline.js +45 -0
  196. package/dist/server/compat/next/og.js +8 -0
  197. package/dist/server/compat/next/preferred-region.js +8 -0
  198. package/dist/server/compat/next/redirects.js +30 -0
  199. package/dist/server/compat/next/resource-hints.js +30 -0
  200. package/dist/server/compat/next/rewrites.js +41 -0
  201. package/dist/server/compat/next/root-params.js +121 -0
  202. package/dist/server/compat/next/route-state.js +23 -0
  203. package/dist/server/compat/next/router.js +103 -0
  204. package/dist/server/compat/next/script.js +37 -0
  205. package/dist/server/compat/next/server-only.js +1 -0
  206. package/dist/server/compat/next/server.js +131 -0
  207. package/dist/server/compat/next/svgr.js +14 -0
  208. package/dist/server/compat/next/telemetry.js +10 -0
  209. package/dist/server/compat/next/usage.js +13 -0
  210. package/dist/server/compat/next/user-agent.js +12 -0
  211. package/dist/server/compat/next/web-vitals.js +35 -0
  212. package/dist/server/compat/react/action-state.js +11 -0
  213. package/dist/server/compat/react/client-lite.js +83 -0
  214. package/dist/server/compat/react/client.js +131 -0
  215. package/dist/server/compat/react/compiler-runtime.js +42 -0
  216. package/dist/server/compat/react/dom-client.js +106 -0
  217. package/dist/server/compat/react/dom-react-server.js +37 -0
  218. package/dist/server/compat/react/dom-server.js +40 -0
  219. package/dist/server/compat/react/dom.js +52 -0
  220. package/dist/server/compat/react/hooks-extra.js +12 -0
  221. package/dist/server/compat/react/internals.js +14 -0
  222. package/dist/server/compat/react/parity.js +11 -0
  223. package/dist/server/compat/react/preact.js +113 -0
  224. package/dist/server/compat/react/react-server.js +133 -0
  225. package/dist/server/compat/react/router-shim.js +8 -0
  226. package/dist/server/compat/react/server-component-use.js +14 -0
  227. package/dist/server/compat/react/server-inserted-html.js +14 -0
  228. package/dist/server/compat/react/server.js +194 -0
  229. package/dist/server/compat/react/style-values.js +10 -0
  230. package/dist/server/compat/react/use.js +10 -0
  231. package/dist/server/compat/react/view-transition.js +12 -0
  232. package/dist/server/generation.json +1 -0
  233. package/package.json +4 -1
  234. package/src/api/dynamic.tsx +2 -0
  235. package/src/api/server.ts +24 -6
  236. package/src/cli/adapters/vercel-warm.ts +315 -61
  237. package/src/cli/adapters/vercel.ts +348 -71
  238. package/src/cli/build.ts +58 -33
  239. package/src/cli/index.ts +23 -10
  240. package/src/cli/serve/entry.ts +21 -159
  241. package/src/cli/serve/immutable.ts +31 -0
  242. package/src/cli/serve/pipeline.ts +82 -84
  243. package/src/cli/start.ts +3 -1
  244. package/src/client/chunk-fold.ts +19 -6
  245. package/src/client/react-tier.ts +3 -2
  246. package/src/client/reference-stub.ts +21 -2
  247. package/src/compat/actions/client-plugin.ts +4 -2
  248. package/src/compat/actions/config.ts +6 -5
  249. package/src/compat/actions/extensions.ts +2 -3
  250. package/src/compat/aliases.ts +8 -1
  251. package/src/compat/bundler/config.ts +88 -0
  252. package/src/compat/bundler/optimize-package-imports.ts +86 -26
  253. package/src/compat/bundler/relay-transform.ts +15 -3
  254. package/src/compat/cache-control.ts +16 -8
  255. package/src/compat/css/modules.ts +18 -5
  256. package/src/compat/lifecycle/error-funnel.ts +1 -1
  257. package/src/compat/lifecycle/instrumentation.ts +117 -24
  258. package/src/compat/lifecycle/testmode.ts +3 -2
  259. package/src/compat/next/config-loader.ts +137 -13
  260. package/src/compat/next/font/runtime.ts +22 -2
  261. package/src/compat/next/og.ts +3 -3
  262. package/src/compat/next/usage.ts +3 -2
  263. package/src/compat/pages/api.ts +83 -14
  264. package/src/compat/pages/router.ts +30 -14
  265. package/src/compat/register/bundler.ts +3 -1
  266. package/src/compat/register/middleware.ts +1 -1
  267. package/src/compat/register/otel.ts +5 -9
  268. package/src/compat/register/render.ts +3 -1
  269. package/src/compat/register/use-cache.ts +3 -1
  270. package/src/compat/release.ts +46 -0
  271. package/src/compat/segment/serve.ts +1 -1
  272. package/src/compat/validation/validate.ts +10 -7
  273. package/src/config.ts +51 -7
  274. package/src/css/assets.ts +213 -0
  275. package/src/css/build.ts +174 -238
  276. package/src/dev/server.ts +27 -8
  277. package/src/extensions.ts +4 -0
  278. package/src/render/hooks.ts +13 -0
  279. package/src/render/renderer.ts +52 -32
  280. package/src/request/context.ts +9 -0
  281. package/src/resolve/dynamic.ts +3 -1
  282. package/src/resolve/imports.ts +12 -52
  283. package/src/resolve/package-json.ts +56 -0
  284. package/src/resolve/scan-facts.ts +65 -0
  285. package/src/routing/href.ts +10 -3
  286. package/src/routing/match.ts +287 -0
  287. package/src/routing/metadata-files.ts +19 -5
  288. package/src/routing/proxy-config.ts +137 -0
  289. package/src/routing/proxy.ts +35 -134
  290. package/src/routing/routes.ts +22 -281
  291. package/src/runtime/fingerprint.ts +23 -8
  292. package/src/runtime/load.ts +170 -0
  293. package/src/runtime/loader.ts +215 -43
  294. package/src/runtime/module-cache.ts +13 -0
  295. package/src/runtime/modules.ts +370 -81
  296. package/src/runtime/prebundle.ts +81 -0
  297. package/src/runtime/production.ts +391 -0
  298. package/src/runtime/release-graph.ts +334 -0
  299. package/src/runtime/vendor-build.ts +724 -13
  300. package/src/runtime/vendor.ts +16 -3
  301. package/src/types.ts +2 -0
  302. package/src/utils/fs.ts +89 -3
@@ -1,4 +1,4 @@
1
- import { resolveManifest } from '../../utils/fs'
1
+ import { type ExactNames, exactNameIndex, hasExactName, resolveManifest } from '../../utils/fs'
2
2
  /**
3
3
  * The production request pipeline. Split out of `start.ts` so the prebundled
4
4
  * server entry parses only what listening needs: this module (renderer,
@@ -14,10 +14,14 @@ import { Readable } from 'node:stream'
14
14
  import { loadConfig, pathToFileHref } from '../../config'
15
15
  import type { ResolvedConfig } from '../../config'
16
16
  import { bootstrapCompat } from '../../compat-bootstrap'
17
- import { registerServerRuntime, serverBundleTargetForRuntime } from '../../runtime/loader'
18
- import { importModuleOnce } from '../../runtime/modules'
17
+ import {
18
+ importModuleOnce,
19
+ registerServerRuntime,
20
+ serverBundleTargetForRuntime,
21
+ } from '../../runtime/load'
19
22
  import { abortUpstreamFetchOnDisconnect } from '../../runtime/fetch-host'
20
- import { applyProxyResponse, createProxyRunner } from '../../routing/proxy'
23
+ import { applyProxyResponse, createProxyRunner, type ProxyRunnerOptions } from '../../routing/proxy'
24
+ import { attachRelease, releaseModuleHref } from '../../runtime/production'
21
25
  import {
22
26
  isPprShellUpgradeEligible,
23
27
  renderGlobalNotFoundResponse,
@@ -32,15 +36,16 @@ import {
32
36
  import {
33
37
  canonicalTrailingSlashPath,
34
38
  malformedUrlResponse,
39
+ repeatedSlashRedirect,
35
40
  trailingSlashRedirect,
36
41
  } from '../../routing/href'
37
42
  import { type PeerAddressSource, withForwardedHeaders } from '../../routing/forwarded'
38
- import { normalizePathname, parseNavState, selectRouteForRequest } from '../../routing/routes'
43
+ import { normalizePathname, parseNavState, selectRouteForRequest } from '../../routing/match'
39
44
  import { runWithCacheScope } from '../../request/cache'
40
45
  import { metadataRouteHandlerModule } from '../../routing/metadata-files'
46
+ import { immutableAssetPath, immutableCacheControl } from './immutable'
41
47
  import {
42
48
  finalizeResponse,
43
- getAssetExtensions,
44
49
  getRenderExtensions,
45
50
  getProxyExtensions,
46
51
  getRequestExtensions,
@@ -55,13 +60,13 @@ import {
55
60
  getWorkUnit,
56
61
  runWithWorkUnit,
57
62
  setPhase,
63
+ setWorkUnitRelease,
58
64
  setWorkUnitRoute,
59
65
  } from '../../request/context'
60
66
  import { setRequestRuntime } from '../../routing/request-environment'
61
67
  import { getRenderSpanExtensions } from '../../render/hooks'
62
- import { publishEmittedAssets } from '../../css/build'
68
+ import { publishEmittedAssets } from '../../css/assets'
63
69
  import { contentType } from '../../utils/content-type'
64
- import { stopEsbuildService } from '../../utils/esbuild'
65
70
  import { markErrorLogged } from '../../utils/error-log'
66
71
  import type {
67
72
  BuildManifest,
@@ -70,17 +75,6 @@ import type {
70
75
  StaticFileMetadata,
71
76
  } from '../../types'
72
77
 
73
- /** Compat module-mode route hrefs are the only prod use of the dev import layer; keep it off the start graph. */
74
- async function moduleHrefForRoute(
75
- config: ResolvedConfig,
76
- route: RouteManifestEntry,
77
- ): Promise<string> {
78
- const { devServerModuleHref } = await import('../../runtime/modules')
79
- return devServerModuleHref(config, route.file, 'build', {
80
- conditionTarget: serverBundleTargetForRuntime(route.segmentConfig?.runtime),
81
- })
82
- }
83
-
84
78
  /**
85
79
  * The production request handler `pnext start` serves with. Exposed on its own
86
80
  * so deployment adapters (e.g. Vercel) can serve the exact same pipeline
@@ -105,6 +99,22 @@ export async function createRequestHandler(
105
99
  config.outPath,
106
100
  config.root,
107
101
  )
102
+ // Everything a request imports comes from the build's release; each handler resolves once, here.
103
+ const release = attachRelease(config)
104
+ release.staticMetadataFiles = manifest.staticMetadataFiles
105
+ const handlerHrefs = new Map(
106
+ manifest.routes
107
+ .filter(route => route.kind === 'handler')
108
+ .map(route => [
109
+ route.id,
110
+ releaseModuleHref(
111
+ release,
112
+ 'server',
113
+ serverBundleTargetForRuntime(route.segmentConfig?.runtime),
114
+ route.file,
115
+ ),
116
+ ]),
117
+ )
108
118
  const persistManifest = async () => {
109
119
  const stored = JSON.parse(await readFile(manifestPath, 'utf8')) as BuildManifest
110
120
  stored.staticFiles = manifest.staticFiles
@@ -120,6 +130,7 @@ export async function createRequestHandler(
120
130
  // Content-hashed asset names, as the build emitted them: a render in THIS
121
131
  // process must link the same files, not the logical `global.css` spelling.
122
132
  publishEmittedAssets(config.outPath, manifest.assetNames)
133
+ const exactNames = exactNameIndex(config.outPath)
123
134
  // Publish the live routing state the compat request interceptors (action
124
135
  // dispatch, rewrites) read; prod loads the route table once.
125
136
  setRequestRuntime({ config, routes: manifest.routes, dev: false })
@@ -127,6 +138,7 @@ export async function createRequestHandler(
127
138
  compiledModuleHref: manifest.proxyModule
128
139
  ? pathToFileHref(path.resolve(config.outPath, manifest.proxyModule))
129
140
  : undefined,
141
+ released: release.proxy as ProxyRunnerOptions['released'],
130
142
  })
131
143
  const routesById = new Map(manifest.routes.map(route => [route.id, route]))
132
144
  const nextCompat = Boolean(config.compat?.next)
@@ -149,6 +161,7 @@ export async function createRequestHandler(
149
161
  const route = routesById.get(metadata.routeId)
150
162
  if (!route) return
151
163
  await runWithWorkUnit('render', async () => {
164
+ setWorkUnitRelease(release)
152
165
  const url = new URL(`http://pnext.local${pathname}`)
153
166
  const params = routeParamsFromPath(route, pathname)
154
167
  const fetchCache = route.segmentConfig?.fetchCache
@@ -156,11 +169,10 @@ export async function createRequestHandler(
156
169
  if (route.kind === 'handler') {
157
170
  setWorkUnitRoute('route-handler', 'isr', { revalidateReason: reason })
158
171
  setPhase('handler')
159
- registerServerRuntime(config, route.sourceFiles)
160
- const href = compatModuleMode(config)
161
- ? await moduleHrefForRoute(config, route)
162
- : pathToFileHref(route.file)
163
- const module = await importModuleOnce<Parameters<typeof handleRouteModule>[0]>(href)
172
+ await registerServerRuntime(config, route.sourceFiles)
173
+ const module = await importModuleOnce<Parameters<typeof handleRouteModule>[0]>(
174
+ handlerHrefs.get(route.id)!,
175
+ )
164
176
  const rendered = await getRenderExtensions().collectRenderMeta(
165
177
  () =>
166
178
  withRouteRuntime(route.segmentConfig?.runtime, () =>
@@ -255,7 +267,13 @@ export async function createRequestHandler(
255
267
 
256
268
  setRequestExtensions({
257
269
  onDemandRevalidatePath: async pathname => {
258
- const built = await builtFileInfo(config.outPath, pathname, manifest.staticFiles)
270
+ const built = await builtFileInfo(
271
+ config.outPath,
272
+ pathname,
273
+ manifest.staticFiles,
274
+ false,
275
+ exactNames,
276
+ )
259
277
  if (!built?.metadata) return
260
278
  await runRegeneration(pathname, built.file, built.relative, built.metadata, 'on-demand')
261
279
  },
@@ -269,6 +287,8 @@ export async function createRequestHandler(
269
287
  request.method,
270
288
  request.headers,
271
289
  nextCompat,
290
+ manifest.publicAssets,
291
+ exactNames,
272
292
  )
273
293
  if (built) {
274
294
  setWorkUnitRoute('html', 'static')
@@ -293,15 +313,13 @@ export async function createRequestHandler(
293
313
  )
294
314
  }
295
315
 
296
- // The boot config compile is the only build work a prod server does; drop the
297
- // resident esbuild service child (~10+ MB RSS) — it respawns if ever needed.
298
- stopEsbuildService()
299
-
300
316
  return function handleRequest(request: Request, server?: PeerAddressSource): Promise<Response> {
301
317
  // One work unit spans the whole request; its after-queue flushes once the
302
318
  // response fully closes (stream end, redirect, notFound, error, abort).
303
319
  return runWithWorkUnit('render', async () => {
304
320
  const unit = getWorkUnit()
321
+ // Every request is work of this release: app-directory facts come from it, never the disk.
322
+ setWorkUnitRelease(release)
305
323
  try {
306
324
  const raw = await handle(request, server)
307
325
  const finalized = await finalizeResponse(
@@ -343,6 +361,8 @@ export async function createRequestHandler(
343
361
  if (badRequest) return badRequest
344
362
  request = withForwardedHeaders(request, server)
345
363
  const requestedUrl = new URL(request.url)
364
+ const slashRedirect = repeatedSlashRedirect(requestedUrl)
365
+ if (slashRedirect) return slashRedirect
346
366
  // assetPrefix is independent from basePath. Strip a path-style asset
347
367
  // prefix first so `/cdn/_next/static/*` remains servable even when the app
348
368
  // itself lives under a different basePath.
@@ -383,6 +403,11 @@ export async function createRequestHandler(
383
403
  const revalidateBypass = Boolean(
384
404
  bypassToken && request.headers.get('x-prerender-revalidate') === bypassToken,
385
405
  )
406
+ // Trailing-slash normalization applies to the browser-visible (as-requested)
407
+ // URL, never to an internal rewrite destination, and precedes the proxy for
408
+ // every method as in Next: the proxy only ever sees canonical paths.
409
+ const canonicalRedirect = trailingSlashRedirect(config, requestedUrl)
410
+ if (canonicalRedirect) return canonicalRedirect
386
411
  const canonicalUrl = new URL(request.url)
387
412
  const canonicalHeaders = request.headers
388
413
  let proxyResponse: Response | undefined
@@ -427,11 +452,6 @@ export async function createRequestHandler(
427
452
  : new Request(canonicalRequestUrl, { headers: canonicalHeaders })
428
453
 
429
454
  const method = request.method.toUpperCase()
430
- // Trailing-slash normalization applies to the browser-visible (as-requested)
431
- // URL, never to an internal rewrite destination. A middleware/next.config
432
- // rewrite to `/en/` must render internally, not 308 the visitor to `/en`.
433
- const canonicalRedirect = trailingSlashRedirect(config, requestedUrl, method)
434
- if (canonicalRedirect) return applyProxyResponse(canonicalRedirect, proxyResponse)
435
455
  // Soft navigations carry the client's parallel-route state; when the
436
456
  // target involves slots, interception, or a host render, the response is
437
457
  // state-dependent and must render dynamically (never from prebuilt html).
@@ -461,7 +481,13 @@ export async function createRequestHandler(
461
481
  // rewrites it.
462
482
  const built =
463
483
  method === 'GET' || method === 'HEAD'
464
- ? await builtFileInfo(config.outPath, url.pathname, manifest.staticFiles, nextCompat)
484
+ ? await builtFileInfo(
485
+ config.outPath,
486
+ url.pathname,
487
+ manifest.staticFiles,
488
+ nextCompat,
489
+ exactNames,
490
+ )
465
491
  : null
466
492
  const hardStaticStale =
467
493
  built !== null &&
@@ -526,6 +552,8 @@ export async function createRequestHandler(
526
552
  request.method,
527
553
  request.headers,
528
554
  nextCompat,
555
+ manifest.publicAssets,
556
+ exactNames,
529
557
  )
530
558
  if (staticFile && !(draftBypass && isHtmlResponse(staticFile))) {
531
559
  const staticMode = servedBuilt.metadata?.revalidateSeconds !== undefined ? 'isr' : 'static'
@@ -594,7 +622,14 @@ export async function createRequestHandler(
594
622
  // isOnDemandRevalidate semantics) and persist the fresh bytes so
595
623
  // subsequent requests serve the regenerated static copy again.
596
624
  const renderedHandler = await getRenderExtensions().collectRenderMeta(
597
- () => handleRoute(config, matched.route, canonicalRequest, matched.params),
625
+ () =>
626
+ handleRoute(
627
+ config,
628
+ matched.route,
629
+ handlerHrefs.get(matched.route.id)!,
630
+ canonicalRequest,
631
+ matched.params,
632
+ ),
598
633
  {
599
634
  fetchCache: matched.route.segmentConfig?.fetchCache,
600
635
  refreshFetches: staleOnDemand,
@@ -971,34 +1006,20 @@ function maybeCloseNodeFetchConnection(response: Response, request: Request) {
971
1006
  return response
972
1007
  }
973
1008
 
974
- // Compat mode gate (a pure read of config.compat, no compat import): under
975
- // compat the compiled module is loaded so bare next/* / react aliases resolve
976
- // to the compat layer. Mirrors compat/aliases.ts reactCompatEnabled — kept inline
977
- // so start.ts carries no static edge into compat.
978
- function compatModuleMode(config: Awaited<ReturnType<typeof loadConfig>>): boolean {
979
- return Boolean(config.compat?.next || config.compat?.react || config.compat?.reactCompiler)
980
- }
981
-
982
1009
  async function handleRoute(
983
1010
  config: Awaited<ReturnType<typeof loadConfig>>,
984
1011
  route: RouteManifestEntry,
1012
+ href: string,
985
1013
  request: Request,
986
1014
  params: Record<string, RouteParamValue>,
987
1015
  ) {
988
1016
  return withRouteRuntime(route.segmentConfig?.runtime, async () => {
989
- registerServerRuntime(config, route.sourceFiles)
1017
+ await registerServerRuntime(config, route.sourceFiles)
990
1018
  // Module resolution and handler invocation run through the render-span seam
991
1019
  // (compat/otel emits `resolve page components` + `executing api route`;
992
1020
  // pass-through for pure-core apps).
993
1021
  const spans = getRenderSpanExtensions()
994
1022
  const module = await spans.withFindPageComponentsSpan(route.route, async () => {
995
- // Compat mode loads the compiled module (aliases baked in): a raw import
996
- // would resolve bare next/* specifiers (next/headers etc.) against whatever
997
- // next package is installed instead of the compat layer — Bun's runtime
998
- // onResolve plugin cannot alias bare imports. Same pattern as pageRender.
999
- const href = compatModuleMode(config)
1000
- ? await moduleHrefForRoute(config, route)
1001
- : new URL(`file://${route.file}`).href
1002
1023
  const imported = await importModuleOnce<
1003
1024
  RouteHandlerModule & Parameters<typeof metadataRouteHandlerModule>[0]
1004
1025
  >(href)
@@ -1067,10 +1088,12 @@ async function builtFileInfo(
1067
1088
  pathname: string,
1068
1089
  staticFiles: Record<string, StaticFileMetadata> = {},
1069
1090
  nextStaticFallback = false,
1091
+ exactNames?: ExactNames,
1070
1092
  ): Promise<BuiltFileInfo | null> {
1071
1093
  const file = await firstFile(
1072
1094
  path.join(outPath, 'public'),
1073
1095
  builtFileCandidates(outPath, pathname, nextStaticFallback),
1096
+ exactNames,
1074
1097
  )
1075
1098
  if (!file) return null
1076
1099
  const publicPath = path.join(outPath, 'public')
@@ -1195,6 +1218,8 @@ export async function maybeBuiltFile(
1195
1218
  method = 'GET',
1196
1219
  requestHeaders?: Headers,
1197
1220
  nextStaticFallback = false,
1221
+ publicAssets: string[] = [],
1222
+ exactNames?: ExactNames,
1198
1223
  ) {
1199
1224
  const normalizedMethod = method.toUpperCase()
1200
1225
  if (normalizedMethod !== 'GET' && normalizedMethod !== 'HEAD') return null
@@ -1203,6 +1228,7 @@ export async function maybeBuiltFile(
1203
1228
  const file = await firstFile(
1204
1229
  publicPath,
1205
1230
  builtFileCandidates(outPath, pathname, nextStaticFallback),
1231
+ exactNames,
1206
1232
  )
1207
1233
  if (!file) return null
1208
1234
  const relative = path.relative(publicPath, file).split(path.sep).join('/')
@@ -1219,7 +1245,8 @@ export async function maybeBuiltFile(
1219
1245
  const variant = requestHeaders?.get('rsc') === '1' ? '-rsc' : ''
1220
1246
  const etag = `W/"${fileStat.size.toString(16)}-${Math.trunc(fileStat.mtimeMs).toString(16)}${variant}"`
1221
1247
  if (!headers.has('cache-control')) {
1222
- headers.set('cache-control', immutableAssetPath(relative) ? immutableCacheControl : 'no-cache')
1248
+ const immutable = immutableAssetPath(relative) && !publicAssets.includes(relative)
1249
+ headers.set('cache-control', immutable ? immutableCacheControl : 'no-cache')
1223
1250
  headers.set('etag', etag)
1224
1251
  if (requestHeaders?.get('if-none-match') === etag) {
1225
1252
  return new Response(null, { status: 304, headers })
@@ -1344,40 +1371,11 @@ function cachedGzip(key: string, body: Buffer) {
1344
1371
  return zipped
1345
1372
  }
1346
1373
 
1347
- export const immutableCacheControl = 'public, max-age=31536000, immutable'
1348
-
1349
- /**
1350
- * Everything the build emits under `assets/` (served at `/_next/static/*` in
1351
- * compat) is immutable, which is the promise Next makes for that whole
1352
- * namespace. It holds because every one of those names carries a content hash:
1353
- * esbuild's for chunks and fonts, assetContentHash for the route entries and the
1354
- * stylesheets (see fingerprintClientEntries / fingerprintAsset), and a build id
1355
- * for `_next/static/<id>/_*Manifest.js`. An UNHASHED name must never reach here —
1356
- * the same URL would answer different bytes after a deploy, and every browser
1357
- * that saw the old ones would keep them for a year.
1358
- *
1359
- * Route outputs (prerendered html, handler bodies) live outside both prefixes
1360
- * and stay revalidating; the public/ tree the app ships is likewise untouched.
1361
- */
1362
- export function immutableAssetPath(relativePath: string) {
1363
- return immutableAssetPrefixes().some(prefix => relativePath.startsWith(prefix))
1364
- }
1365
-
1366
- /** The public-relative prefixes `immutableAssetPath` covers. */
1367
- export function immutableAssetPrefixes() {
1368
- return [
1369
- 'assets/',
1370
- '_next/static/',
1371
- ...getAssetExtensions()
1372
- .staticAssetPublicPrefixes()
1373
- .map(prefix => prefix.replace(/^\/+/, '')),
1374
- ]
1375
- }
1376
-
1377
- async function firstFile(root: string, files: string[]) {
1374
+ async function firstFile(root: string, files: string[], exactNames?: ExactNames) {
1378
1375
  for (const file of files) {
1379
1376
  if (!isInside(root, file)) continue
1380
1377
  if (!existsSync(file)) continue
1378
+ if (exactNames && !hasExactName(exactNames, root, path.relative(root, file))) continue
1381
1379
  if ((await stat(file)).isFile()) return file
1382
1380
  }
1383
1381
  return null
package/src/cli/start.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * `pnext start`: the listen path only. Everything a request needs — renderer,
3
3
  * routing, server runtime — lives in `./serve/pipeline` and is imported
4
4
  * dynamically once the port is bound, so neither the listen syscall nor the
5
- * ready banner waits on parsing it (it is ~700 KB of the prebundled entry).
5
+ * ready banner waits on parsing it.
6
6
  */
7
7
  import { readFile } from 'node:fs/promises'
8
8
  import path from 'node:path'
@@ -13,6 +13,7 @@ import { getBuildExtensions } from '../extensions'
13
13
  import { drainWorkUnits } from '../request/context'
14
14
  import { markErrorLogged } from '../utils/error-log'
15
15
  import { isPostpone } from '../render/postpone'
16
+ import { registerPrebundleResolve } from '../runtime/prebundle'
16
17
  import { browserHost, ensurePortFree, openBrowser, printServerReady } from './serve/ui'
17
18
  import type { BuildManifest } from '../types'
18
19
  import type { PeerAddressSource } from '../routing/forwarded'
@@ -33,6 +34,7 @@ type RequestHandler = (request: Request, server?: PeerAddressSource) => Promise<
33
34
  export async function createRequestHandler(
34
35
  options: { root?: string; config?: ResolvedConfig; manifest?: BuildManifest } = {},
35
36
  ): Promise<RequestHandler> {
37
+ registerPrebundleResolve()
36
38
  const { createRequestHandler: create } = await import('./serve/pipeline')
37
39
  return create(options)
38
40
  }
@@ -91,8 +91,15 @@ async function foldGroup(
91
91
  const memberNames = members.map(output => path.basename(output))
92
92
  if (memberNames.some(name => !existsSync(path.join(chunksDir, name)))) return metafile
93
93
 
94
- const sources = new Map<string, string>()
95
- for (const name of memberNames) sources.set(name, await readText(path.join(chunksDir, name)))
94
+ // The state holds every output's current text, in step with what earlier groups wrote.
95
+ const sources = new Map(
96
+ await Promise.all(
97
+ memberNames.map(async name => {
98
+ const file = path.join(chunksDir, name)
99
+ return [name, state.outputs.get(file)?.text ?? (await readText(file))] as const
100
+ }),
101
+ ),
102
+ )
96
103
 
97
104
  const aliases = memberAliases(memberNames, sources)
98
105
  if (!aliases) return metafile
@@ -503,14 +510,20 @@ async function createFoldState(outDir: string, metafile: Metafile): Promise<Fold
503
510
  }
504
511
  }
505
512
 
513
+ const files = new Set<string>()
506
514
  for (const name of Object.keys(metafile.outputs)) {
507
515
  if (!name.endsWith('.js')) continue
508
516
  const resolved = path.resolve(name)
509
517
  const local = existsSync(resolved) ? resolved : path.join(outDir, path.basename(name))
510
- if (outputs.has(local) || !existsSync(local)) continue
511
- const output = foldOutput(await readText(local))
512
- outputs.set(local, output)
513
- index(local, output, true)
518
+ if (existsSync(local)) files.add(local)
519
+ }
520
+ // Read concurrently, indexed in metafile order.
521
+ const list = [...files]
522
+ const texts = await Promise.all(list.map(file => readText(file)))
523
+ for (const [at, file] of list.entries()) {
524
+ const output = foldOutput(texts[at]!)
525
+ outputs.set(file, output)
526
+ index(file, output, true)
514
527
  }
515
528
 
516
529
  return {
@@ -1,5 +1,6 @@
1
- import { existsSync, readFileSync, statSync } from 'node:fs'
1
+ import { existsSync, statSync } from 'node:fs'
2
2
  import path from 'node:path'
3
+ import { readSourceSync } from '../resolve/source-text'
3
4
 
4
5
  /**
5
6
  * Conservative static scan of a compat app's client graph deciding whether the client bundle can ship
@@ -87,7 +88,7 @@ export function clientSuspenseFree(seeds: Iterable<string>): boolean {
87
88
  if (!SOURCE_EXTENSION.test(file) || !existsSync(file)) return false
88
89
  let source: string
89
90
  try {
90
- source = readFileSync(file, 'utf8')
91
+ source = readSourceSync(file)
91
92
  } catch {
92
93
  return false
93
94
  }
@@ -22,6 +22,12 @@ export interface ClientReferenceModuleOptions {
22
22
  * inlined lookup is the same symbol the renderer tests for.
23
23
  */
24
24
  inlineSymbol?: boolean
25
+ /**
26
+ * For a release: the reference names its source relative to the stub (`from`), at `target` - the
27
+ * source itself, or its path through the app's node_modules (`real`: resolved to the installed file).
28
+ * A moved build then still identifies the module its release indexed.
29
+ */
30
+ portable?: { from: string; target: string; real: boolean }
25
31
  }
26
32
 
27
33
  export function clientReferenceModuleSource(
@@ -29,8 +35,17 @@ export function clientReferenceModuleSource(
29
35
  exportNames: string[],
30
36
  options: ClientReferenceModuleOptions = {},
31
37
  ) {
38
+ const portable = options.portable
39
+ const located = portable
40
+ ? `decodeURIComponent(new URL(${JSON.stringify(path.relative(path.dirname(portable.from), portable.target).split(path.sep).join('/'))}, import.meta.url).pathname)`
41
+ : undefined
42
+ const file = !located
43
+ ? JSON.stringify(sourceFile)
44
+ : portable?.real
45
+ ? `__pnextRealpath(${located})`
46
+ : located
32
47
  const reference = (exportName: string) =>
33
- `createReference({ id: ${JSON.stringify(`c-${clientReferenceId(sourceFile, exportName)}`)}, file: ${JSON.stringify(sourceFile)}, exportName: ${JSON.stringify(exportName)} })`
48
+ `createReference({ id: ${JSON.stringify(`c-${clientReferenceId(sourceFile, exportName)}`)}, file: ${file}, exportName: ${JSON.stringify(exportName)} })`
34
49
  const defaultExport = exportNames.includes('default')
35
50
  ? `export default ${reference('default')};`
36
51
  : ''
@@ -41,7 +56,11 @@ export function clientReferenceModuleSource(
41
56
  ? `const clientReferenceSymbol = Symbol.for('pnext.clientReference');`
42
57
  : `import { clientReferenceSymbol } from ${JSON.stringify(pathToFileHref(clientReferenceRuntimeFile))};`
43
58
 
44
- return `${symbol}
59
+ const realpath = portable?.real
60
+ ? `import { realpathSync as __pnextRealpath } from 'node:fs';\n`
61
+ : ''
62
+
63
+ return `${realpath}${symbol}
45
64
 
46
65
  function createReference(reference) {
47
66
  function ClientReference({ children }) {
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path'
2
2
  import { realpathSync } from 'node:fs'
3
3
  import type { Plugin } from 'esbuild'
4
- import { readText } from '../../utils/fs'
4
+ import { readText, toPosixPath } from '../../utils/fs'
5
5
  import { escapeRegex } from '../../utils/code'
6
6
  import { actionId } from './ids'
7
7
  import { moduleActionExports, moduleLevelUseCache, moduleLevelUseServer } from './detect'
@@ -125,7 +125,9 @@ export function stubSourceFromSource(file: string, source: string, root?: string
125
125
  const exports = moduleActionExports(source)
126
126
  const actionIds: Record<string, string> = {}
127
127
  for (const name of exports) actionIds[name] = canonicalActionId(file, name, root)
128
- return clientStubSource({ modulePath: file, exports, actionIds })
128
+ // Root-relative: the stub ships in client bundles and release artifacts.
129
+ const modulePath = root ? toPosixPath(path.relative(root, file)) : file
130
+ return clientStubSource({ modulePath, exports, actionIds })
129
131
  }
130
132
 
131
133
  export async function loadClientActionSource(file: string, root?: string) {
@@ -3,6 +3,7 @@ import { createRequire } from 'node:module'
3
3
  import path from 'node:path'
4
4
  import { pathToFileHref } from '../../config'
5
5
  import { DEFAULT_BODY_LIMIT_BYTES } from './endpoint'
6
+ import { getNextConfig, nextConfigReleased } from '../next/config-loader'
6
7
 
7
8
  /**
8
9
  * Server-actions options read from the app's next.config in compat mode:
@@ -39,7 +40,7 @@ export async function loadServerActionsConfig(root: string): Promise<ServerActio
39
40
  }
40
41
 
41
42
  export async function loadResolvedNextConfig(root: string): Promise<NextConfigShape | undefined> {
42
- return (await loadNextConfigFromStore()) ?? (await loadNextConfig(root))
43
+ return loadNextConfigFromStore() ?? (await loadNextConfig(root))
43
44
  }
44
45
 
45
46
  /**
@@ -50,9 +51,8 @@ export async function loadResolvedNextConfig(root: string): Promise<NextConfigSh
50
51
  * silently dropped the configured bodySizeLimit. Returns undefined when the store is empty so the
51
52
  * caller falls back to a direct file read.
52
53
  */
53
- async function loadNextConfigFromStore(): Promise<NextConfigShape | undefined> {
54
+ function loadNextConfigFromStore(): NextConfigShape | undefined {
54
55
  try {
55
- const { getNextConfig } = await import('../next/config-loader')
56
56
  const store: NextConfigShape = getNextConfig()
57
57
  return store && Object.keys(store).length > 0 ? store : undefined
58
58
  } catch {
@@ -61,6 +61,7 @@ async function loadNextConfigFromStore(): Promise<NextConfigShape | undefined> {
61
61
  }
62
62
 
63
63
  export async function loadNextConfig(root: string): Promise<NextConfigShape | undefined> {
64
+ if (nextConfigReleased()) return getNextConfig()
64
65
  for (const name of ['next.config.js', 'next.config.mjs', 'next.config.cjs']) {
65
66
  const file = path.join(root, name)
66
67
  if (!existsSync(file)) continue
@@ -109,9 +110,9 @@ export async function loadNextConfig(root: string): Promise<NextConfigShape | un
109
110
  * skipped here - the lazy per-request path still validates.
110
111
  */
111
112
  export function validateServerActionsConfigSync(root: string): void {
112
- let config: NextConfigShape | undefined
113
+ let config: NextConfigShape | undefined = nextConfigReleased() ? getNextConfig() : undefined
113
114
  const requireFrom = createRequire(path.join(root, 'noop.js'))
114
- for (const name of ['next.config.js', 'next.config.cjs']) {
115
+ for (const name of config ? [] : ['next.config.js', 'next.config.cjs']) {
115
116
  const file = path.join(root, name)
116
117
  if (!existsSync(file)) continue
117
118
  try {
@@ -21,8 +21,7 @@ import {
21
21
  import { getRequestRuntime, type RequestRuntime } from '../../routing/request-environment'
22
22
  import { toPosixPath } from '../../utils/fs'
23
23
  import type { ActionManifestEntry, BuildManifest, RouteManifestEntry } from '../../types'
24
- import { devServerModuleHref } from '../../runtime/modules'
25
- import { serverBundleTargetForRuntime } from '../../runtime/loader'
24
+ import { devServerModuleHref, serverBundleTargetForRuntime } from '../../runtime/load'
26
25
  import {
27
26
  renderActionReturnElement,
28
27
  renderGlobalNotFoundResponse,
@@ -31,7 +30,7 @@ import {
31
30
  renderPageResponse,
32
31
  } from '../../render/renderer'
33
32
  import { routeParamsFromPath } from '../../routing/handler'
34
- import { selectRouteForRequest } from '../../routing/routes'
33
+ import { selectRouteForRequest } from '../../routing/match'
35
34
  import { discoverActions, registerDiscoveredActions } from './discovery'
36
35
  import { clearActions, lookupActionSource, registerActionModule } from './registry'
37
36
  import {
@@ -1,4 +1,6 @@
1
1
  import path from 'node:path'
2
+ import { isReleaseCompile } from '../runtime/load'
3
+ import { toPosixPath } from '../utils/fs'
2
4
  import { createRequire } from 'node:module'
3
5
  import type { Plugin } from 'esbuild'
4
6
  import { frameworkRuntimeAliasEntries, pnextAliases, type CompatAliasTarget } from '../config'
@@ -329,7 +331,12 @@ export function rewriteNextFontSource(
329
331
  let next = rewriteNextGoogleFontImports(source, runtimePath)
330
332
  const localFontNames = nextLocalFontImportNames(next)
331
333
  if (localFontNames.size === 0) return next
332
- const callerFile = localFontCallerFile(file, root)
334
+ // A release names the caller root-relative, so its font identity survives moving the build.
335
+ const absoluteCaller = localFontCallerFile(file, root)
336
+ const callerFile =
337
+ isReleaseCompile() && root && path.isAbsolute(absoluteCaller)
338
+ ? toPosixPath(path.relative(root, absoluteCaller))
339
+ : absoluteCaller
333
340
  // Rewrite each `NAME(...)` call to `NAME.withFile(<file>)(...)` so the runtime
334
341
  // gets the caller path (for `src` resolution + a stable per-caller hash). The
335
342
  // client runtime only uses `callerFile` for the hash (which must match the