@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
package/src/cli/build.ts CHANGED
@@ -25,13 +25,15 @@ import { beginSourceScope, endSourceScope, sourceCacheStats } from '../resolve/s
25
25
  import { flushDevModuleCaches } from '../runtime/module-cache'
26
26
  import { scanFactsStats } from '../resolve/scan-facts'
27
27
  import { clientEntryName } from '../client/chunk-name'
28
+ import { compiledClientReferenceFiles } from '../client/reference'
29
+ import { buildIndexFile } from '../runtime/production'
28
30
  import { registerServerRuntime, serverBundleTargetForRuntime } from '../runtime/loader'
29
31
  import {
30
- buildClientReferenceCss,
31
32
  buildGlobalCss,
32
33
  buildNotFoundCss,
33
- buildRouteCss,
34
+ buildRouteStylesheets,
34
35
  emittedAssetNames,
36
+ globalCssSources,
35
37
  prepareRouteCssChunks,
36
38
  registerCssRuntime,
37
39
  warmCssPipeline,
@@ -72,6 +74,7 @@ import {
72
74
  devServerModuleHref,
73
75
  resetModuleGraphFailure,
74
76
  setEmitCompiledSpecifiersManifest,
77
+ setReleaseCompile,
75
78
  throwIfModuleGraphFailed,
76
79
  } from '../runtime/modules'
77
80
  import {
@@ -91,6 +94,8 @@ import {
91
94
  import { interceptionMarkerLevels } from '../routing/slots'
92
95
  import { writeTypegen } from './typegen'
93
96
  import { lookupBuildCache, writeBuildCache } from './build/cache'
97
+ import { emitServerEntry } from './serve/entry'
98
+ import { immutableAssetPath } from './serve/immutable'
94
99
  import { createVerboseLogger, type VerboseLogger } from '../utils/verbose'
95
100
  import { bold, cyan, dim, green } from '../utils/ansi'
96
101
  import type {
@@ -164,6 +169,7 @@ export async function buildProject(root?: string, options: BuildOptions = {}) {
164
169
  // Only the vercel adapter's trace step reads the per-artifact specifier
165
170
  // sidecars; every other build path pays nothing for them.
166
171
  const restoreSpecifiersManifest = setEmitCompiledSpecifiersManifest(options.adapter === 'vercel')
172
+ const restoreReleaseCompile = setReleaseCompile(true)
167
173
  const lifecycle: { warm?: WarmChild } = {}
168
174
  try {
169
175
  return await runBuild(root, options, lifecycle)
@@ -176,6 +182,7 @@ export async function buildProject(root?: string, options: BuildOptions = {}) {
176
182
  lifecycle.warm?.kill()
177
183
  endSourceScope()
178
184
  restoreSpecifiersManifest()
185
+ restoreReleaseCompile()
179
186
  flushDevModuleCaches()
180
187
  }
181
188
  }
@@ -224,21 +231,13 @@ async function runBuild(
224
231
  const warmMode = options.adapter === 'vercel' ? 'full' : 'compile'
225
232
  const warm = startWarmChild(config, warmMode)
226
233
  lifecycle.warm = warm
227
- await log.step('prepare output directory', async () => {
234
+ const publicFiles = await log.step('prepare output directory', async () => {
228
235
  // Build-owned outputs only: `<outRoot>/dev` belongs to a possibly-running
229
236
  // dev server and must survive.
230
- await ensureEmptyDir(config.outPath, [devOutSegment])
231
- await copyPublicDir(config.publicPath, path.join(config.outPath, 'public'))
237
+ // Materialized pages sources too: this build's config already resolved into them.
238
+ await ensureEmptyDir(config.outPath, [devOutSegment, 'pnext-pages-compat'])
239
+ return copyPublicDir(config.publicPath, path.join(config.outPath, 'public'))
232
240
  })
233
- // Prebundled server entry for `pnext start`: framework-only, independent of the
234
- // app build, so it runs in a child process for the whole build — its bundling
235
- // heap never stacks on the build's peak RSS and its wall hides under the build.
236
- // Best-effort — a failure only costs start time. Awaited before the summary.
237
- const serverEntryDone = import('./serve/entry')
238
- .then(entry => entry.emitServerEntryChild(config.outPath))
239
- .catch((error: Error) => {
240
- console.warn(`pnext build: server entry bundling skipped — ${error.message}`)
241
- })
242
241
  // The document-level stylesheets run their postcss/Tailwind pass on the CSS
243
242
  // worker, so they overlap with the route scan below instead of serializing
244
243
  // ahead of it. Awaited before prepareRouteCssChunks — route CSS still builds
@@ -313,6 +312,14 @@ async function runBuild(
313
312
  // - those are awaited just before the first route stylesheet is emitted, which lets a Tailwind
314
313
  // pass run under the build steps and the client bundles instead of ahead of them.
315
314
  prepareRouteCssChunks(routes)
315
+ // Route stylesheets bundle all at once under the client stage; the loop below publishes each
316
+ // route's names right before its prerender, after the document ones.
317
+ const routeStylesheets = buildRouteStylesheets(
318
+ config,
319
+ routes.filter(route => route.kind !== 'handler' && !route.dynamicErrorApi),
320
+ documentCss,
321
+ { verbose },
322
+ )
316
323
  // output:'export' with trailingSlash:false lays prerendered pages out flat
317
324
  // (`/a.html` rather than `/a/index.html`). Only meaningful under compat (the
318
325
  // Next config carries `output`); pure-core apps always use the dir layout.
@@ -361,9 +368,11 @@ async function runBuild(
361
368
  )
362
369
  : undefined
363
370
  metadataWarnings?.catch(() => undefined)
364
- const staticModuleMetadata = await log.step('core module metadata', () =>
371
+ // Imports the route modules; the client stage needs none of it, so both run at once.
372
+ const moduleMetadata = log.step('core module metadata', () =>
365
373
  collectStaticModuleMetadata(config, routes),
366
374
  )
375
+ moduleMetadata.catch(() => undefined)
367
376
 
368
377
  const actionSources = buildState.actionSources ?? buildState.actions.map(a => a.sourceKey)
369
378
  // realpath, not resolve: a hybrid app's routes are scanned through the pages-compat mirror, whose
@@ -374,13 +383,18 @@ async function runBuild(
374
383
  // A node_modules action module never lands in route.sourceFiles itself (that walk stops at the
375
384
  // package boundary), so a route reaching one only through a first-party importer is matched here.
376
385
  const actionImporters = new Set((buildState.actionImporters ?? []).map(realFilePath))
386
+ // Routes share most of their files; resolve each once.
387
+ const realFiles = new Map<string, string>()
388
+ const reachesAction = (file: string) => {
389
+ let real = realFiles.get(file)
390
+ if (real === undefined) realFiles.set(file, (real = realFilePath(file)))
391
+ return actionFiles.has(real) || actionImporters.has(real)
392
+ }
377
393
  for (const route of routes) {
378
394
  if (
379
395
  route.kind === 'page' &&
380
- route.sourceFiles.some(file => {
381
- const real = realFilePath(file)
382
- return actionFiles.has(real) || actionImporters.has(real)
383
- })
396
+ (actionFiles.size > 0 || actionImporters.size > 0) &&
397
+ route.sourceFiles.some(reachesAction)
384
398
  ) {
385
399
  addClientEntryReason(route, 'actions')
386
400
  }
@@ -408,14 +422,14 @@ async function runBuild(
408
422
  // other document does, and those names are only final once the client stage has
409
423
  // fingerprinted them — so this render follows the bundle rather than racing it.
410
424
  // Result is consumed after the prerender pass, where it always was.
411
- const notFoundDocuments = clientBundles.then(() =>
425
+ const notFoundDocuments = clientBundles.then(async () =>
412
426
  renderNotFoundDocuments({
413
427
  config,
414
428
  log,
415
429
  skip: options.buildMode === 'compile',
416
430
  documentCss,
417
431
  staticMetadataFiles,
418
- staticModuleMetadata,
432
+ staticModuleMetadata: await moduleMetadata,
419
433
  }),
420
434
  )
421
435
  notFoundDocuments.catch(() => undefined)
@@ -428,6 +442,7 @@ async function runBuild(
428
442
  ).then(() => log.step('typegen', () => writeTypegen(config, routes)))
429
443
  remainingSteps.catch(() => undefined)
430
444
  await remainingSteps
445
+ const staticModuleMetadata = await moduleMetadata
431
446
  await clientBundles
432
447
  const proxyModule = await proxyBuild
433
448
  await partytownLib
@@ -480,8 +495,7 @@ async function runBuild(
480
495
  const generateFailures: { route: string; omitErrorLine: boolean }[] = []
481
496
  if (isGenerate) console.log(' Collecting page data ...')
482
497
 
483
- // Route stylesheets build strictly after the document ones; this is the first
484
- // point that needs them, so everything above ran alongside the CSS worker.
498
+ // The first point that needs the stylesheets, so everything above ran alongside them.
485
499
  await documentCss
486
500
 
487
501
  for (const route of routes) {
@@ -523,10 +537,7 @@ async function runBuild(
523
537
  continue
524
538
  }
525
539
 
526
- await buildRouteCss(config, route, { verbose })
527
- for (const reference of route.clientReferences) {
528
- await buildClientReferenceCss(config, reference, { verbose })
529
- }
540
+ await routeStylesheets.get(route)?.()
530
541
 
531
542
  // Compile mode bundles only — every prerender/export step is generate's.
532
543
  if (isCompile) continue
@@ -914,6 +925,7 @@ async function runBuild(
914
925
  // carries its entries, so this is where it has to have landed.
915
926
  await deferredSteps
916
927
  const actions = buildState.actions
928
+ const publicAssets = publicFiles.filter(relative => immutableAssetPath(relative))
917
929
  const manifest: BuildManifest = {
918
930
  version: 0,
919
931
  root: config.root,
@@ -924,6 +936,7 @@ async function runBuild(
924
936
  // The serving process re-publishes these so a render resolves the same
925
937
  // content-hashed names the build emitted.
926
938
  assetNames: emittedAssetNames(config.outPath),
939
+ ...(publicAssets.length > 0 ? { publicAssets } : {}),
927
940
  staticMetadataFiles,
928
941
  ...(Object.keys(staticModuleMetadata).length > 0 ? { staticModuleMetadata } : {}),
929
942
  ...(!config.compat?.next
@@ -938,7 +951,7 @@ async function runBuild(
938
951
  }
939
952
  await writeBuildManifest(config.outPath, manifest)
940
953
  log.log(`wrote manifest.json (${routes.length} route${routes.length === 1 ? '' : 's'})`)
941
- await log.step('server entry', () => serverEntryDone)
954
+ await log.step('server entry', () => emitServerEntry(config.outPath))
942
955
  for (const hook of getBuildExtensions().completeHooks) {
943
956
  await hook({ config, manifest, log })
944
957
  }
@@ -949,7 +962,19 @@ async function runBuild(
949
962
  // Plain build: the adapter owns the child in the branch above. Compiling the
950
963
  // rest of the app's modules is build work, so it counts toward the build's own
951
964
  // duration rather than hiding after it.
952
- else await log.step('warm module cache', () => warm.finish(log))
965
+ else {
966
+ await log.step('warm module cache', () =>
967
+ warm.finish(log, undefined, {
968
+ globalCss: globalCssSources(config),
969
+ clientReferences: [...compiledClientReferenceFiles()],
970
+ }),
971
+ )
972
+ }
973
+ // The release names every module production imports; a server compile that did not finish
974
+ // fails the build here rather than a request later.
975
+ if (!existsSync(buildIndexFile(config.outPath))) {
976
+ throw new Error('pnext build: the server compile did not complete (see the error above).')
977
+ }
953
978
 
954
979
  // Also cover module loads performed by completion hooks or the warm pass.
955
980
  throwIfModuleGraphFailed()
@@ -3202,11 +3227,11 @@ function resolvePartytownLibDir(root: string): string | null {
3202
3227
  }
3203
3228
 
3204
3229
  async function copyPublicDir(from: string, to: string) {
3205
- const files = await listFiles(from)
3206
- for (const file of files) {
3207
- const relative = toPosixPath(path.relative(from, file))
3230
+ const files = (await listFiles(from)).map(file => toPosixPath(path.relative(from, file)))
3231
+ for (const relative of files) {
3208
3232
  const target = path.join(to, relative)
3209
3233
  await mkdir(path.dirname(target), { recursive: true })
3210
- await copyFile(file, target)
3234
+ await copyFile(path.join(from, relative), target)
3211
3235
  }
3236
+ return files
3212
3237
  }
package/src/cli/index.ts CHANGED
@@ -50,8 +50,8 @@ markBoot('cli:entry')
50
50
  namedBunBinary(commandBinaryName(command))
51
51
 
52
52
  // Before any command lazily imports esbuild, which captures the binary path on
53
- // module load.
54
- nameEsbuildProcess()
53
+ // module load. `start` serves a finished build and never loads it.
54
+ if (command !== 'start') nameEsbuildProcess()
55
55
  markBoot('cli:naming')
56
56
 
57
57
  try {
@@ -90,14 +90,10 @@ try {
90
90
  } else if (command === 'start') {
91
91
  warnUnknownFlags(command, args)
92
92
  const root = positionalRoot(args)
93
- // The build emits src/cli/start.ts prebundled into one file; parsing that
94
- // instead of walking the framework's source graph is most of `start`'s
95
- // spawn→first-200. Absent (no build yet, custom outDir) → source path.
96
- const { prebuiltServerEntry } = await import('./serve/entry')
97
- const prebuilt = prebuiltServerEntry(root)
98
- const { start } = prebuilt
99
- ? ((await import(prebuilt)) as typeof import('./start'))
100
- : await import('./start')
93
+ // A build of other source than this prebundle's is served from that source.
94
+ const { start } = (await prebundleServes(root))
95
+ ? await import('./start')
96
+ : ((await import(new URL('./start.ts', import.meta.url).href)) as typeof import('./start'))
101
97
  await start({
102
98
  root,
103
99
  port: optionNumber(args, '--port'),
@@ -167,6 +163,23 @@ function formatCliError(error: unknown) {
167
163
  }
168
164
  }
169
165
 
166
+ declare const PNEXT_PREBUNDLE: { version: string; fingerprint: string } | undefined
167
+
168
+ /** Whether this process's prebundle may serve `root`'s build: one made from its source and version. */
169
+ async function prebundleServes(root = process.cwd()) {
170
+ if (typeof PNEXT_PREBUNDLE !== 'object') return true
171
+ const [{ DEFAULT_OUT_DIR }, { locateRelease, readBuildIndex }] = await Promise.all([
172
+ import('../config'),
173
+ import('../runtime/production'),
174
+ ])
175
+ const outPath = locateRelease(path.resolve(root), DEFAULT_OUT_DIR)
176
+ return (
177
+ !outPath ||
178
+ (readBuildIndex(outPath).framework === PNEXT_PREBUNDLE.fingerprint &&
179
+ VERSION === PNEXT_PREBUNDLE.version)
180
+ )
181
+ }
182
+
170
183
  function positionalRoot(args: string[]) {
171
184
  return positionals(args)[0]
172
185
  }
@@ -1,13 +1,13 @@
1
1
  /**
2
- * Prebundled production server entry: `pnext build` bundles the framework's server graph into one JS
3
- * file (entry point IS src/cli/start.ts, so the identical `start()` runs) and `pnext start` parses
4
- * that instead of walking hundreds of source modules - the dominant share of spawn->first-200.
2
+ * Server entry for hosts that serve a build through `createRequestHandler`: a thin loader that
3
+ * resolves `@wular/pnext` from the output's own location (as `.next/server` loads `next`), so the
4
+ * output carries no framework code and no build-machine paths.
5
5
  */
6
- import { existsSync, readFileSync } from 'node:fs'
6
+ import { readFileSync } from 'node:fs'
7
+ import { mkdir, writeFile } from 'node:fs/promises'
7
8
  import path from 'node:path'
8
- import { pathToFileURL } from 'node:url'
9
- import type { Plugin as EsbuildPlugin } from 'esbuild'
10
9
  import { frameworkFingerprint } from '../../runtime/fingerprint'
10
+ import { readPrebundleStamp } from '../../runtime/prebundle'
11
11
 
12
12
  const frameworkRoot = path.resolve(import.meta.dirname, '..', '..', '..')
13
13
 
@@ -28,163 +28,25 @@ function frameworkVersion(): string {
28
28
  * cache-root record so a restart pays one stat per file rather than re-reading the tree.
29
29
  */
30
30
  export function serverEntryDir(outPath: string): string {
31
- // Cache root spelled inline, not imported: this module is parsed before anything else on the
32
- // start path, and pulling in the module cache for one path.join would drag its whole graph along.
33
31
  const generation = frameworkFingerprint(path.join(outPath, 'cache', 'server'))
34
32
  return path.join(outPath, 'server', `bundle-${frameworkVersion()}-${generation}`)
35
33
  }
36
34
 
37
- function serverEntryFile(outPath: string): string {
38
- return path.join(serverEntryDir(outPath), 'entry.js')
39
- }
40
-
41
- /**
42
- * The prebuilt entry for a project root, or undefined when there is none to
43
- * use (no build, a custom `outDir`, a version or source-generation mismatch, or the opt-out). The
44
- * caller then falls back to importing src/cli/start.ts directly, so a miss only
45
- * costs speed. Deliberately cheap: one existsSync and one package.json read,
46
- * because it runs before anything else on the start path.
47
- */
48
- export function prebuiltServerEntry(root = process.cwd()): string | undefined {
49
- // eslint-disable-next-line turbo/no-undeclared-env-vars
50
- if (process.env.PNEXT_NO_SERVER_BUNDLE === '1') return undefined
51
- const file = serverEntryFile(path.resolve(root, '.pnext'))
52
- return existsSync(file) ? pathToFileURL(file).href : undefined
53
- }
54
-
55
- /**
56
- * Bundle src/cli/start.ts under `<outPath>/server/bundle-<version>-<fingerprint>/`. Bare
57
- * specifiers stay external (the framework's deps are already plain JS), so only
58
- * the framework's own source is inlined. Splitting is on so the graph behind a
59
- * dynamic import (compat, dev, build) stays in its own chunk — folding it into
60
- * the entry would evaluate eagerly what the source graph never even reads.
61
- * Returns the emitted entry, or undefined when bundling failed — the build must
62
- * not fail over a start-time optimization.
63
- */
64
- export async function emitServerEntry(outPath: string): Promise<string | undefined> {
65
- const { build } = await import('../../utils/esbuild')
66
- try {
67
- await build({
68
- entryPoints: [path.join(import.meta.dirname, '..', 'start.ts')],
69
- outdir: serverEntryDir(outPath),
70
- entryNames: 'entry',
71
- chunkNames: '[name]-[hash]',
72
- bundle: true,
73
- splitting: true,
74
- format: 'esm',
75
- platform: 'node',
76
- target: 'esnext',
77
- sourcemap: false,
78
- tsconfig: path.join(frameworkRoot, 'tsconfig.json'),
79
- logLevel: 'silent',
80
- // esbuild's ESM `require` shim throws for anything it did not bundle; the
81
- // framework's lazy `require('esbuild' | 'oxc-*')` facades need a real one,
82
- // anchored at the framework so they load ITS copy, not the app's.
83
- banner: {
84
- js:
85
- 'import { createRequire as __pnextCreateRequire } from "node:module";\n' +
86
- `const require = __pnextCreateRequire(${JSON.stringify(
87
- pathToFileURL(path.join(frameworkRoot, 'package.json')).href,
88
- )});`,
89
- },
90
- plugins: [await serverEntryPlugin(outPath)],
91
- })
92
- return serverEntryFile(outPath)
93
- } catch (error) {
94
- console.warn(`pnext build: server entry bundling skipped — ${(error as Error).message}`)
95
- return undefined
96
- }
97
- }
98
-
99
35
  /**
100
- * Emit in a short-lived child process: the bundle's source strings and parse
101
- * allocations land in the child's heap (well under the build's own peak), not
102
- * on top of it. Falls back to in-process emission if the spawn fails.
36
+ * Write `<outPath>/server/bundle-<version>-<fingerprint>/entry.js`, re-exporting the published
37
+ * prebundle's cli/start.js when it was built from this source, else src/cli/start.ts.
103
38
  */
104
- export async function emitServerEntryChild(outPath: string): Promise<void> {
105
- try {
106
- const child = Bun.spawn([process.execPath, import.meta.filename, outPath], {
107
- stdout: 'ignore',
108
- stderr: 'inherit',
109
- })
110
- if ((await child.exited) === 0) return
111
- } catch {
112
- // fall through to in-process emission
113
- }
114
- await emitServerEntry(outPath)
115
- }
116
-
117
- async function serverEntryPlugin(outPath: string): Promise<EsbuildPlugin> {
118
- const { rewriteFacts } = await import('../../resolve/scan-facts')
119
- const { spliceSource } = await import('../../runtime/module-transform')
120
- return {
121
- name: 'pnext-server-entry',
122
- setup(build) {
123
- // Bare specifiers (and node builtins) stay out of the bundle. They must
124
- // still resolve to the SAME file the framework's own source graph would
125
- // reach: keep the specifier bare when the output directory resolves it
126
- // identically (portable), otherwise pin the absolute path.
127
- build.onResolve({ filter: /^[^./]/ }, args => {
128
- if (args.path.startsWith('node:')) return { path: args.path, external: true }
129
- const target = resolveFrom(args.path, frameworkRoot)
130
- if (!target) return { path: args.path, external: true }
131
- const fromOutput = resolveFrom(args.path, serverEntryDir(outPath))
132
- return { path: fromOutput === target ? args.path : target, external: true }
133
- })
134
- // `import.meta` in a bundled module still means the ORIGINAL source file
135
- // (the framework locates its own runtime shims that way). oxc's exact
136
- // spans keep occurrences in strings and comments untouched.
137
- build.onLoad({ filter: /\.[cm]?[jt]sx?$/ }, async args => {
138
- const source = await Bun.file(args.path).text()
139
- if (!source.includes('import.meta')) return undefined
140
- const facts = rewriteFacts(args.path, source)
141
- if (facts.unreliable) return undefined
142
- const edits = facts.importMetas.flatMap(meta => {
143
- const value = importMetaValue(source.slice(meta.end, meta.end + 16), args.path)
144
- return value
145
- ? [{ start: meta.start, end: meta.end + value.length, value: value.code }]
146
- : []
147
- })
148
- if (edits.length === 0) return undefined
149
- return { contents: spliceSource(source, edits), loader: loaderFor(args.path) }
150
- })
151
- },
152
- }
153
- }
154
-
155
- const importMetaProperties = ['dirname', 'filename', 'resolve', 'url', 'dir'] as const
156
-
157
- /** The literal a bundled `import.meta.<prop>` must become, given the tail after `import.meta`. */
158
- function importMetaValue(tail: string, file: string): { code: string; length: number } | undefined {
159
- const property = importMetaProperties.find(name => new RegExp(`^\\.${name}\\b`).test(tail))
160
- if (!property) return undefined
161
- const length = property.length + 1
162
- const dir = path.dirname(file)
163
- if (property === 'dirname' || property === 'dir') return { code: JSON.stringify(dir), length }
164
- if (property === 'filename') return { code: JSON.stringify(file), length }
165
- if (property === 'url') return { code: JSON.stringify(pathToFileURL(file).href), length }
166
- return {
167
- code: `(specifier => Bun.pathToFileURL(Bun.resolveSync(specifier, ${JSON.stringify(dir)})).href)`,
168
- length,
169
- }
170
- }
171
-
172
- function loaderFor(file: string): 'ts' | 'tsx' | 'js' | 'jsx' {
173
- if (file.endsWith('.tsx')) return 'tsx'
174
- if (file.endsWith('.jsx')) return 'jsx'
175
- return /\.[cm]?ts$/.test(file) ? 'ts' : 'js'
176
- }
177
-
178
- function resolveFrom(specifier: string, dir: string): string | undefined {
179
- try {
180
- return Bun.resolveSync(specifier, dir)
181
- } catch {
182
- return undefined
183
- }
184
- }
185
-
186
- // Child-process entry for emitServerEntryChild; last so every binding above is initialized.
187
- if (import.meta.main && process.argv[2]) {
188
- const emitted = await emitServerEntry(process.argv[2])
189
- process.exit(emitted ? 0 : 1)
39
+ export async function emitServerEntry(outPath: string): Promise<void> {
40
+ const start = await Bun.file(path.join(import.meta.dirname, '..', 'start.ts')).text()
41
+ const names = new Bun.Transpiler({ loader: 'ts' }).scan(start).exports
42
+ const dir = serverEntryDir(outPath)
43
+ const target = readPrebundleStamp(frameworkRoot, frameworkFingerprint())
44
+ ? '../dist/server/cli/start.js'
45
+ : './cli/start.ts'
46
+ await mkdir(dir, { recursive: true })
47
+ await writeFile(
48
+ path.join(dir, 'entry.js'),
49
+ `const pnext = await import(new URL('${target}', import.meta.resolve('@wular/pnext')).href)\n` +
50
+ `export const { ${names.join(', ')} } = pnext\n`,
51
+ )
190
52
  }
@@ -0,0 +1,31 @@
1
+ import { getAssetExtensions } from '../../extensions'
2
+
3
+ export const immutableCacheControl = 'public, max-age=31536000, immutable'
4
+
5
+ /**
6
+ * Everything the build emits under `assets/` (served at `/_next/static/*` in
7
+ * compat) is immutable, which is the promise Next makes for that whole
8
+ * namespace. It holds because every one of those names carries a content hash:
9
+ * esbuild's for chunks and fonts, assetContentHash for the route entries and the
10
+ * stylesheets (see fingerprintClientEntries / fingerprintAsset), and a build id
11
+ * for `_next/static/<id>/_*Manifest.js`. An UNHASHED name must never reach here —
12
+ * the same URL would answer different bytes after a deploy, and every browser
13
+ * that saw the old ones would keep them for a year.
14
+ *
15
+ * Route outputs (prerendered html, handler bodies) live outside both prefixes
16
+ * and stay revalidating; so do the app's own public/ files (manifest.publicAssets).
17
+ */
18
+ export function immutableAssetPath(relativePath: string) {
19
+ return immutableAssetPrefixes().some(prefix => relativePath.startsWith(prefix))
20
+ }
21
+
22
+ /** The public-relative prefixes `immutableAssetPath` covers. */
23
+ export function immutableAssetPrefixes() {
24
+ return [
25
+ 'assets/',
26
+ '_next/static/',
27
+ ...getAssetExtensions()
28
+ .staticAssetPublicPrefixes()
29
+ .map(prefix => prefix.replace(/^\/+/, '')),
30
+ ]
31
+ }