@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
@@ -26,27 +26,45 @@ import { resolveManifest } from '../../utils/fs'
26
26
  * go-ahead to finish the rest once the manifest is written.
27
27
  */
28
28
  import { existsSync } from 'node:fs'
29
- import { readFile } from 'node:fs/promises'
29
+ import { mkdir, readFile, rm } from 'node:fs/promises'
30
30
  import path from 'node:path'
31
31
  import { fileURLToPath } from 'node:url'
32
- import { loadConfig, pathToFileHref, type ResolvedConfig } from '../../config'
32
+ import { DEFAULT_OUT_DIR, loadConfig, pathToFileHref, type ResolvedConfig } from '../../config'
33
33
  import { bootstrapCompat } from '../../compat-bootstrap'
34
34
  import { compiledClientReferenceFiles, ssrClientReference } from '../../client/reference'
35
+ import { hasUseClientDirective } from '../../client/reference-stub'
36
+ import { globalCssSources } from '../../css/build'
35
37
  import {
36
38
  devClientModuleHref,
39
+ devModuleGraph,
37
40
  devServerModuleHref,
38
41
  setEmitCompiledSpecifiersManifest,
42
+ setReleaseCompile,
39
43
  } from '../../runtime/modules'
40
44
  import { getCompatModeExtensions } from '../../extensions'
41
- import { getFontExtensions } from '../../render/hooks'
45
+ import { getFontExtensions, type ReleasedFont } from '../../render/hooks'
46
+ import { beginSourceScope, readSourceSync } from '../../resolve/source-text'
47
+ import { releasedProxy } from '../../routing/proxy-config'
42
48
  import { findConventionFiles, findLayouts } from '../../routing/routes'
43
49
  import {
44
- prewarmServerTransforms,
50
+ pagesApiBundleTargetForRuntime,
45
51
  registerServerRuntime,
46
52
  serverBundleTargetForRuntime,
53
+ type ServerBundleTarget,
47
54
  } from '../../runtime/loader'
48
- import { cacheRoot } from '../../runtime/module-cache'
49
- import { listFiles } from '../../utils/fs'
55
+ import {
56
+ BUILD_INDEX_VERSION,
57
+ type CompatRelease,
58
+ type ReleaseLayer,
59
+ captureConventions,
60
+ releaseModuleKey,
61
+ releaseSourceKey,
62
+ serializeReleaseConfig,
63
+ writeBuildIndex,
64
+ } from '../../runtime/production'
65
+ import { frameworkFingerprint } from '../../runtime/fingerprint'
66
+ import { releaseDependencyLog } from '../../runtime/vendor-build'
67
+ import { linkReleaseLayer, pruneReleaseVendor } from '../../runtime/release-graph'
50
68
  import { namedBunBinary } from '../boot/named-bin'
51
69
  import type { VerboseLogger } from '../../utils/verbose'
52
70
  import type { BuildManifest } from '../../types'
@@ -69,6 +87,11 @@ const COMPILED_MARKER = 'pnext-warm-compiled'
69
87
  interface WarmRequest {
70
88
  /** Files a previous attempt already finished — or died on. */
71
89
  skip: string[]
90
+ /** Release modules a previous attempt compiled, so the release this attempt writes is whole. */
91
+ compiled: Record<string, string>
92
+ /** Facts the parent already holds: the root layout's stylesheet closure and its own compiled client references. */
93
+ globalCss?: string[]
94
+ clientReferences: string[]
72
95
  }
73
96
  interface PrewarmRequest {
74
97
  /** Page route sources, known from the route scan long before the manifest. */
@@ -106,7 +129,11 @@ export interface WarmChild {
106
129
  * which is already the final set: the caller can start tracing the node_modules closure while the
107
130
  * child runs handlers concurrently.
108
131
  */
109
- finish(log: VerboseLogger, onCompiled?: (modules: string[]) => void): Promise<string[]>
132
+ finish(
133
+ log: VerboseLogger,
134
+ onCompiled?: (modules: string[]) => void,
135
+ facts?: Pick<WarmRequest, 'globalCss' | 'clientReferences'>,
136
+ ): Promise<string[]>
110
137
  /** Stop every attempt owned by this build. Safe to call after `finish` or more than once. */
111
138
  kill(): void
112
139
  }
@@ -150,8 +177,8 @@ export function startWarmChild(config: ResolvedConfig, mode: WarmMode = 'full'):
150
177
  // broken pipe: the child is gone; `finish` reports why
151
178
  }
152
179
  },
153
- finish: (log, onCompiled) =>
154
- warmWithRestarts(first, spawn, mode, log, onCompiled).finally(kill),
180
+ finish: (log, onCompiled, facts = { clientReferences: [] }) =>
181
+ warmWithRestarts(first, spawn, mode, log, facts, onCompiled).finally(kill),
155
182
  kill,
156
183
  }
157
184
  }
@@ -191,10 +218,11 @@ async function warmWithRestarts(
191
218
  spawn: () => WarmProcess | undefined,
192
219
  mode: WarmMode,
193
220
  log: VerboseLogger,
221
+ facts: Pick<WarmRequest, 'globalCss' | 'clientReferences'>,
194
222
  onCompiled?: (modules: string[]) => void,
195
223
  ) {
196
- // Source file -> compiled artifact. Handlers map to nothing but still count as
197
- // finished, so a restart does not import them a second time.
224
+ // Release module key (or a handler's source file) -> compiled artifact. Handlers map to nothing
225
+ // but still count as finished, so a restart does not import them a second time.
198
226
  const finished = new Map<string, string | undefined>()
199
227
  const compiled = () => [...finished.values()].filter((file): file is string => Boolean(file))
200
228
  // The marker can only mean "compiled set final" the first time it fires —
@@ -212,7 +240,13 @@ async function warmWithRestarts(
212
240
  const before = finished.size
213
241
  const failure = await runAttempt(
214
242
  child,
215
- { skip: [...finished.keys()] },
243
+ {
244
+ skip: [...finished.keys()],
245
+ compiled: Object.fromEntries(
246
+ [...finished].filter((entry): entry is [string, string] => Boolean(entry[1])),
247
+ ),
248
+ ...facts,
249
+ },
216
250
  finished,
217
251
  fireOnCompiled,
218
252
  )
@@ -317,8 +351,87 @@ function pageServerFiles(config: ResolvedConfig, routeFiles: Iterable<string>) {
317
351
  return files
318
352
  }
319
353
 
320
- const compileServer = (config: ResolvedConfig, file: string) =>
321
- devServerModuleHref(config, file, 'build').then(href => report(file, fileURLToPath(href)))
354
+ interface ReleaseEntry {
355
+ layer: ReleaseLayer
356
+ target: ServerBundleTarget
357
+ file: string
358
+ }
359
+
360
+ /** Compile one release module, reporting it under its release key. */
361
+ async function compileEntry(
362
+ config: ResolvedConfig,
363
+ entry: ReleaseEntry,
364
+ compiled: Map<string, string>,
365
+ ) {
366
+ const href =
367
+ entry.layer === 'client'
368
+ ? await devClientModuleHref(config, entry.file, 'build', entry.target)
369
+ : await devServerModuleHref(config, entry.file, 'build', { conditionTarget: entry.target })
370
+ const key = releaseModuleKey(entry.layer, entry.target, entry.file)
371
+ compiled.set(key, fileURLToPath(href))
372
+ report(key, fileURLToPath(href))
373
+ }
374
+
375
+ /**
376
+ * Every module a production server can import, by layer and target: each convention file of the app
377
+ * tree, each handler, and each client reference the render marks or SSRs.
378
+ */
379
+ function releaseEntries(
380
+ config: ResolvedConfig,
381
+ routes: BuildManifest['routes'],
382
+ conventionFiles: string[],
383
+ clientReferences: Iterable<string>,
384
+ ) {
385
+ const compat = getCompatModeExtensions().reactEnabled(config)
386
+ const entries = new Map<string, ReleaseEntry>()
387
+ const add = (layer: ReleaseLayer, target: ServerBundleTarget, file: string) =>
388
+ entries.set(releaseModuleKey(layer, target, file), { layer, target, file })
389
+ const addConvention = (target: ServerBundleTarget, file: string) => {
390
+ add('server', target, file)
391
+ if (compat && hasUseClientDirective(readSourceSync(file))) add('client', target, file)
392
+ }
393
+ const pageFiles = conventionFiles.filter(file => !path.basename(file).startsWith('route.'))
394
+ for (const file of pageFiles) addConvention('server', file)
395
+ const targets = new Set<ServerBundleTarget>(['server'])
396
+ for (const route of routes) {
397
+ const target = serverBundleTargetForRuntime(route.segmentConfig?.runtime)
398
+ targets.add(target)
399
+ if (route.kind === 'handler') {
400
+ add('server', target, route.file)
401
+ continue
402
+ }
403
+ if (target !== 'server') {
404
+ const dirs = [path.dirname(route.file), ...(route.slotDirs ?? [])]
405
+ for (const file of pageFiles) {
406
+ const dir = path.dirname(file)
407
+ if (dirs.some(owner => isInsideDir(dir, owner) || isInsideDir(owner, dir))) {
408
+ addConvention(target, file)
409
+ }
410
+ }
411
+ }
412
+ if (compat && route.client && existsSync(route.file)) add('client', target, route.file)
413
+ // Inline actions recover cold by importing their owning module by source key, helpers included.
414
+ if (compat) {
415
+ for (const file of route.sourceFiles) {
416
+ if (/\.[cm]?[jt]sx?$/.test(file) && readSourceSync(file).includes('use server')) {
417
+ add('server', 'server', file)
418
+ add('server', target, file)
419
+ }
420
+ }
421
+ }
422
+ for (const reference of route.clientReferences) {
423
+ if (ssrClientReference(reference)) add(compat ? 'client' : 'server', target, reference.file)
424
+ }
425
+ }
426
+ if (compat) {
427
+ for (const file of clientReferences) for (const target of targets) add('client', target, file)
428
+ }
429
+ return [...entries.values()]
430
+ }
431
+
432
+ function isInsideDir(dir: string, file: string) {
433
+ return file === dir || file.startsWith(`${dir}${path.sep}`)
434
+ }
322
435
 
323
436
  /**
324
437
  * Compile the page routes' server modules from the build's route scan, long before the manifest
@@ -326,29 +439,49 @@ const compileServer = (config: ResolvedConfig, file: string) =>
326
439
  * pass below - the point is to spend this CPU under the build's client stage. Nothing here runs app
327
440
  * code, so it is safe to overlap (see the handler note below).
328
441
  */
329
- export async function prewarmPageModules(config: ResolvedConfig, routeFiles: string[]) {
330
- if (!getCompatModeExtensions().reactEnabled(config)) return
442
+ export async function prewarmPageModules(
443
+ config: ResolvedConfig,
444
+ routeFiles: string[],
445
+ compiled = new Map<string, string>(),
446
+ ) {
447
+ const { files } = captureConventions(config.root, config.appPath)
448
+ const entries = [
449
+ ...new Set([...files.filter(file => !path.basename(file).startsWith('route.')), ...routeFiles]),
450
+ ].filter(file => existsSync(file))
451
+ const compile = (layer: ReleaseLayer, file: string) =>
452
+ compileEntry(config, { layer, target: 'server', file }, compiled).catch(() => undefined)
453
+ await Promise.all(entries.map(file => compile('server', file)))
454
+ // The client components those entries reach are core's client references: publish them now, under
455
+ // the build, rather than after the manifest. Compat's client layer stays after the build's own
456
+ // prerender, whose vendor plan it must share.
457
+ if (getCompatModeExtensions().reactEnabled(config)) return
458
+ const graph = devModuleGraph(config)
459
+ const sources = await graph.graphSources(entries).catch(() => [])
331
460
  await Promise.all(
332
- [...pageServerFiles(config, routeFiles)].map(file =>
333
- compileServer(config, file).catch(() => undefined),
334
- ),
461
+ sources.map(async ([file]) => {
462
+ if (/\.[cm]?[jt]sx?$/.test(file) && (await graph.isClientSource(file))) {
463
+ await compile('server', file)
464
+ }
465
+ }),
335
466
  )
336
467
  }
337
468
 
338
469
  /**
339
- * The warm pass itself, in the child. Reports every file it finishes as it
340
- * lands, so a parent restart can step over one that takes the process down.
470
+ * The warm pass itself, in the child. Compiles every release module, reporting each as it lands so a
471
+ * parent restart can step over one that takes the process down, then publishes the build index.
341
472
  */
342
473
  export async function warmRouteModules(
343
474
  config: ResolvedConfig,
344
475
  manifest: BuildManifest,
345
- skip: ReadonlySet<string> = new Set(),
476
+ request: Pick<WarmRequest, 'skip' | 'compiled' | 'globalCss' | 'clientReferences'>,
346
477
  mode: WarmMode = 'full',
478
+ compiled = new Map<string, string>(),
347
479
  ) {
480
+ const skip = new Set(request.skip)
481
+ for (const [key, artifact] of Object.entries(request.compiled)) compiled.set(key, artifact)
348
482
  const clientFiles = new Set<string>()
349
483
  const handlers: BuildManifest['routes'] = []
350
484
  const pages: BuildManifest['routes'] = []
351
- const pageRoutes: string[] = []
352
485
 
353
486
  for (const route of manifest.routes) {
354
487
  if (route.kind === 'handler') {
@@ -356,7 +489,6 @@ export async function warmRouteModules(
356
489
  continue
357
490
  }
358
491
  pages.push(route)
359
- pageRoutes.push(route.file)
360
492
  for (const reference of route.clientReferences) {
361
493
  if (ssrClientReference(reference) && existsSync(reference.file)) {
362
494
  clientFiles.add(reference.file)
@@ -364,41 +496,61 @@ export async function warmRouteModules(
364
496
  }
365
497
  }
366
498
 
367
- // Without react compat the runtime imports page sources directly (Bun
368
- // transforms in memory); the compiled build cache is only used with compat.
369
- if (getCompatModeExtensions().reactEnabled(config)) {
370
- await Promise.all([
371
- ...[...pageServerFiles(config, pageRoutes)]
372
- .filter(file => !skip.has(file))
373
- .map(file => compileServer(config, file)),
374
- ...[...clientFiles]
375
- .filter(file => !skip.has(file))
376
- .map(file =>
377
- devClientModuleHref(config, file, 'build').then(href =>
378
- report(file, fileURLToPath(href)),
379
- ),
380
- ),
381
- // Handler artifacts are otherwise only written by the import below, which
382
- // `compile` mode does not run: compiling them here is what keeps a handler
383
- // route's first served request off the compile pipeline too.
384
- ...(mode === 'compile'
385
- ? handlers.map(async route => {
386
- registerServerRuntime(config, route.sourceFiles)
387
- report(route.file, fileURLToPath(await handlerModuleHref(config, route)))
388
- })
389
- : []),
390
- ])
499
+ const { conventions, files } = captureConventions(config.root, config.appPath)
500
+ const serverDir = path.join(config.outPath, 'server')
501
+ await mkdir(serverDir, { recursive: true })
502
+ // Compat's release facts (compiled config, handlers, instrumentation) build beside the module compile.
503
+ const compat = config.compat?.next
504
+ ? import('../../compat/release').then(release => release.compatReleaseFacts(config, serverDir))
505
+ : Promise.resolve(undefined)
506
+ compat.catch(() => undefined)
507
+ const compileAll = (entries: ReleaseEntry[]) =>
508
+ Promise.all(
509
+ entries
510
+ .filter(entry => !compiled.has(releaseModuleKey(entry.layer, entry.target, entry.file)))
511
+ .map(entry => compileEntry(config, entry, compiled)),
512
+ )
513
+ await compileAll(releaseEntries(config, manifest.routes, files, request.clientReferences))
514
+ // Client references only a server compile discovers (a 'use client' module inside a package).
515
+ await compileAll(releaseEntries(config, manifest.routes, files, compiledClientReferenceFiles()))
516
+ const compatFacts = await compat
517
+ await compileAll(
518
+ Object.entries(compatFacts?.compat?.pagesApi ?? {}).map(([file, runtime]) => ({
519
+ layer: 'server',
520
+ target: pagesApiBundleTargetForRuntime(runtime),
521
+ file: path.resolve(config.root, file),
522
+ })),
523
+ )
524
+ const fonts = await releaseFonts(config, manifest.routes, compiled)
525
+ // One graph per App Router layer for the server dependencies the release imports.
526
+ const layerSources = new Map<string, string>()
527
+ const rsc = await linkReleaseLayer(config, 'server:server', [...compiled.values()], layerSources)
528
+ // The server graph can reach a package's 'use client' file no compile saw.
529
+ await compileAll(releaseEntries(config, manifest.routes, files, compiledClientReferenceFiles()))
530
+ const ssr = await linkReleaseLayer(config, 'client:client', [...compiled.values()], layerSources)
531
+ for (const [key, artifact] of compiled) {
532
+ const layer = key.startsWith('server:server:')
533
+ ? rsc
534
+ : key.startsWith('client:server:')
535
+ ? ssr
536
+ : undefined
537
+ const moved = layer?.moved.get(artifact)
538
+ if (moved) compiled.set(key, moved)
391
539
  }
540
+ if (rsc || ssr) await pruneReleaseVendor(config, layerSources)
541
+ await rm(releaseDependencyLog(config), { force: true })
542
+ await writeRelease(
543
+ config,
544
+ compiled,
545
+ conventions,
546
+ files,
547
+ compatFacts ?? {},
548
+ fonts,
549
+ [...(rsc?.files ?? []), ...(ssr?.files ?? [])],
550
+ request.globalCss,
551
+ )
392
552
  console.log(COMPILED_MARKER)
393
- if (mode === 'compile') {
394
- // Transform is the tail of the compile pipeline: an artifact is transformed when it is first
395
- // imported, so a server that skipped every compile would still start esbuild for this alone.
396
- // The import pass below covers it in `full` mode; here it runs standalone, without app code.
397
- for (const route of [...pages, ...handlers]) registerServerRuntime(config, route.sourceFiles)
398
- const modules = cacheRoot(config.outPath)
399
- await prewarmServerTransforms(modules, await listFiles(modules))
400
- return
401
- }
553
+ if (mode === 'compile') return
402
554
  // Everything below runs the app's own code to capture what only an import
403
555
  // writes (vendor bundles, next/font bytes). A normal build serves from a
404
556
  // writable disk and creates those on demand; only a read-only deployment
@@ -506,11 +658,101 @@ async function importPageModules(
506
658
  }
507
659
  }
508
660
 
661
+ /**
662
+ * Resolve the app's next/font declarations for the release. A declaration only exists once its module
663
+ * evaluates, so the modules that call a font loader are imported here, as `next build` does.
664
+ */
665
+ async function releaseFonts(
666
+ config: ResolvedConfig,
667
+ routes: BuildManifest['routes'],
668
+ compiled: Map<string, string>,
669
+ ) {
670
+ if (!config.compat?.next) return undefined
671
+ const files = new Set(
672
+ routes
673
+ .flatMap(route => route.sourceFiles)
674
+ .filter(file => /\.(?:[cm]?[jt]sx?|mdx?)$/.test(file))
675
+ .filter(file => readSourceSync(file).includes('next/font/')),
676
+ )
677
+ if (files.size === 0) return undefined
678
+ for (const file of files) {
679
+ const entry = { layer: 'server', target: 'server', file } as const
680
+ await compileEntry(config, entry, compiled)
681
+ try {
682
+ await import(pathToFileHref(compiled.get(releaseModuleKey('server', 'server', file))!))
683
+ } catch (error) {
684
+ console.warn(`pnext build: importing ${file} for its fonts failed:`, error)
685
+ }
686
+ }
687
+ const fonts = await getFontExtensions().releaseFonts(config)
688
+ return Object.fromEntries(
689
+ Object.entries(fonts).map(([key, font]) => [
690
+ key,
691
+ { ...font, files: font.files.map(file => path.relative(config.outPath, file)) },
692
+ ]),
693
+ )
694
+ }
695
+
696
+ /** Publish the build index: every compiled module plus the source facts production reads instead of source. */
697
+ async function writeRelease(
698
+ config: ResolvedConfig,
699
+ compiled: ReadonlyMap<string, string>,
700
+ conventions: Record<string, string[]>,
701
+ conventionFiles: string[],
702
+ compat: CompatRelease,
703
+ fonts: Record<string, ReleasedFont> | undefined,
704
+ dependencies: string[],
705
+ globalCss = globalCssSources(config),
706
+ ) {
707
+ const toPosix = (file: string) => file.split(path.sep).join('/')
708
+ const fromRoot = (file: string) => toPosix(path.relative(config.root, file))
709
+ const modules: Record<string, string> = {}
710
+ // Sorted: compiles land in completion order, and an unchanged build must publish identical bytes.
711
+ for (const [key, artifact] of [...compiled].sort(([a], [b]) => (a < b ? -1 : 1))) {
712
+ const match = /^((?:server|client):[^:]+:)(.*)$/s.exec(key)
713
+ if (!match) continue
714
+ modules[`${match[1]}${releaseSourceKey(match[2]!, config.root, config.workspaceRoot)}`] =
715
+ toPosix(path.relative(config.outPath, artifact))
716
+ }
717
+ const source = (file: string) => readSourceSync(file)
718
+ const proxy = releasedProxy(config)
719
+ await writeBuildIndex(
720
+ config,
721
+ {
722
+ version: BUILD_INDEX_VERSION,
723
+ framework: frameworkFingerprint(),
724
+ config: serializeReleaseConfig(config),
725
+ ...compat,
726
+ modules,
727
+ conventions,
728
+ clientConventions: conventionFiles
729
+ .filter(file => hasUseClientDirective(source(file)))
730
+ .map(fromRoot),
731
+ documentLayouts: conventionFiles
732
+ .filter(
733
+ file =>
734
+ path.basename(file).startsWith('layout.') && /\bexport\s+default\b/.test(source(file)),
735
+ )
736
+ .map(fromRoot),
737
+ globalCss: globalCss.map(fromRoot),
738
+ ...(proxy ? { proxy: { ...proxy, file: fromRoot(proxy.file) } } : {}),
739
+ ...(fonts ? { fonts } : {}),
740
+ ...(dependencies.length > 0
741
+ ? { dependencies: dependencies.map(file => toPosix(path.relative(config.outPath, file))) }
742
+ : {}),
743
+ },
744
+ DEFAULT_OUT_DIR,
745
+ )
746
+ }
747
+
509
748
  /**
510
749
  * Read the parent's line-delimited requests until the `skip` message, running
511
750
  * each prewarm batch as it arrives. Returns the final request.
512
751
  */
513
- async function readWarmRequests(config: ResolvedConfig): Promise<Partial<WarmRequest>> {
752
+ async function readWarmRequests(
753
+ config: ResolvedConfig,
754
+ prewarmed: Map<string, string>,
755
+ ): Promise<Partial<WarmRequest>> {
514
756
  let buffer = ''
515
757
  const decoder = new TextDecoder()
516
758
  const reader = Bun.stdin.stream().getReader()
@@ -525,7 +767,7 @@ async function readWarmRequests(config: ResolvedConfig): Promise<Partial<WarmReq
525
767
  if (!line) continue
526
768
  const message = JSON.parse(line) as Partial<WarmRequest & PrewarmRequest>
527
769
  if (message.skip) return message
528
- if (message.prewarm) await prewarmPageModules(config, message.prewarm)
770
+ if (message.prewarm) await prewarmPageModules(config, message.prewarm, prewarmed)
529
771
  }
530
772
  }
531
773
  const rest = buffer.trim()
@@ -542,9 +784,15 @@ if (import.meta.main) {
542
784
  // Only the vercel adapter reads the specifier manifests back (its trace step);
543
785
  // a plain build would write them for nothing.
544
786
  setEmitCompiledSpecifiersManifest(mode === 'full')
787
+ setReleaseCompile(true)
788
+ // Idle until the route scan arrives: read the framework generation every compile keys on now.
789
+ frameworkFingerprint()
790
+ // One read per source for the child's life: its release facts re-read what the compile read.
791
+ beginSourceScope()
545
792
  // Blocks until the parent sends the go-ahead, i.e. until the manifest is
546
793
  // written; a prewarm batch may arrive and run before that.
547
- const request = await readWarmRequests(config)
794
+ const prewarmed = new Map<string, string>()
795
+ const request = await readWarmRequests(config, prewarmed)
548
796
  // A build that fails closes stdin without a go-ahead and never writes the manifest. There is
549
797
  // nothing to warm and nothing to report: exiting quietly keeps the failed build's own error the
550
798
  // only thing on stderr.
@@ -555,7 +803,13 @@ if (import.meta.main) {
555
803
  config.outPath,
556
804
  config.root,
557
805
  )
558
- await warmRouteModules(config, manifest, new Set(request.skip ?? []), mode)
806
+ await warmRouteModules(
807
+ config,
808
+ manifest,
809
+ { skip: [], compiled: {}, clientReferences: [], ...request },
810
+ mode,
811
+ prewarmed,
812
+ )
559
813
  // App code reached through a route handler can leave the loop alive (a db
560
814
  // pool, a stray interval); the warm pass is done either way.
561
815
  process.exit(0)