@wular/pnext 0.1.7 → 0.1.9

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 (172) hide show
  1. package/dist/server/_chunks/{aliases-j47a10ce.js → aliases-fhv4dt06.js} +7 -5
  2. package/dist/server/_chunks/{analyze-arswqe6s.js → analyze-09kx9q6r.js} +17 -13
  3. package/dist/server/_chunks/{boot-af0mv3dy.js → boot-8aj7efqk.js} +13 -11
  4. package/dist/server/_chunks/{build-spy3dxp4.js → build-jda155c9.js} +7 -5
  5. package/dist/server/_chunks/{build-tier-m7yvqz61.js → build-tier-qrkpfsk1.js} +59 -75
  6. package/dist/server/_chunks/{build-t9h0hec3.js → build-wspv5h60.js} +1004 -1191
  7. package/dist/server/_chunks/{compile-53j02j27.js → compile-040r79gj.js} +2 -2
  8. package/dist/server/_chunks/{config-n2z7yxps.js → config-7h84p6q8.js} +6 -4
  9. package/dist/server/_chunks/{config-1yzwexq6.js → config-d4hqyygy.js} +12 -3
  10. package/dist/server/_chunks/{create-meec9hs6.js → create-skj8wzt5.js} +4 -3
  11. package/dist/server/_chunks/{dev-fjmqg6en.js → dev-pennd36n.js} +2 -2
  12. package/dist/server/_chunks/{generate-n9sh6hzt.js → generate-d8vb1d21.js} +5 -4
  13. package/dist/server/_chunks/{index-eeaanp2e.js → index-0qt2vapb.js} +3 -3
  14. package/dist/server/_chunks/{index-91x12ykq.js → index-0r5eqfc7.js} +6 -1
  15. package/dist/server/_chunks/{index-9ych9ma8.js → index-0wm2p3ks.js} +2 -2
  16. package/dist/server/_chunks/{index-357na4a8.js → index-141vcwk6.js} +1 -1
  17. package/dist/server/_chunks/{index-2dv4y4wd.js → index-1y0cesgn.js} +16 -10
  18. package/dist/server/_chunks/{index-ytjvpbm2.js → index-26gwrm07.js} +3 -3
  19. package/dist/server/_chunks/{index-8k7pfejn.js → index-3r6qpe8a.js} +7 -7
  20. package/dist/server/_chunks/{index-rn8dyr1f.js → index-42fef2rv.js} +8 -48
  21. package/dist/server/_chunks/{index-ncnes8c6.js → index-47gx7trn.js} +2 -2
  22. package/dist/server/_chunks/{index-20ppawv7.js → index-4qsce64w.js} +3 -3
  23. package/dist/server/_chunks/{index-1011cscr.js → index-4vf121ws.js} +61 -29
  24. package/dist/server/_chunks/{index-cf4rvxv6.js → index-52k54ykj.js} +1 -1
  25. package/dist/server/_chunks/{index-nyrba2kr.js → index-53fnn598.js} +11 -11
  26. package/dist/server/_chunks/{index-4hgjrqh7.js → index-6tb725m8.js} +2 -2
  27. package/dist/server/_chunks/{index-3xbr4eyv.js → index-912z4mfx.js} +3 -3
  28. package/dist/server/_chunks/{index-sjpckxqn.js → index-9f49w76j.js} +1 -1
  29. package/dist/server/_chunks/{index-jepjvcrf.js → index-aarf1brn.js} +1 -1
  30. package/dist/server/_chunks/{index-9n2914ww.js → index-akkrvjn6.js} +1 -1
  31. package/dist/server/_chunks/index-bzd2ef7t.js +10 -0
  32. package/dist/server/_chunks/{index-sv8m6789.js → index-cqcwwxfp.js} +5 -5
  33. package/dist/server/_chunks/{index-yz54pxrh.js → index-d1jsmhhk.js} +4 -9
  34. package/dist/server/_chunks/{index-vvmmknm1.js → index-da0fphj0.js} +19 -15
  35. package/dist/server/_chunks/{index-sctcgyvv.js → index-drwv61cc.js} +2 -2
  36. package/dist/server/_chunks/{index-z84ab1w0.js → index-e176wk6x.js} +3 -3
  37. package/dist/server/_chunks/{index-9hx2641q.js → index-entm8bmz.js} +1 -1
  38. package/dist/server/_chunks/index-fpghsgb4.js +352 -0
  39. package/dist/server/_chunks/{index-jx7bqvw1.js → index-hr63fvzn.js} +1 -1
  40. package/dist/server/_chunks/{index-eajaspjk.js → index-j0m1jxqa.js} +1 -1
  41. package/dist/server/_chunks/index-jbj7ehef.js +50 -0
  42. package/dist/server/_chunks/{index-egykcqg3.js → index-jexsy9a8.js} +1 -1
  43. package/dist/server/_chunks/{index-fkp000p1.js → index-jjppzw0s.js} +2 -2
  44. package/dist/server/_chunks/index-jt8e1pje.js +12 -0
  45. package/dist/server/_chunks/{index-ggk2j965.js → index-kpdph69z.js} +56 -50
  46. package/dist/server/_chunks/{index-6e4fqv30.js → index-m63czgq5.js} +2 -0
  47. package/dist/server/_chunks/{index-c0g2wf3z.js → index-md5jchzy.js} +1 -1
  48. package/dist/server/_chunks/{index-tvqkq6e6.js → index-n814hcky.js} +1 -1
  49. package/dist/server/_chunks/{index-06nyqntx.js → index-q3r9z8mq.js} +1 -1
  50. package/dist/server/_chunks/{index-4q2gbfwk.js → index-qjrh7w2g.js} +2 -2
  51. package/dist/server/_chunks/{index-3b3at80h.js → index-s61bx2aj.js} +6 -3
  52. package/dist/server/_chunks/{index-ym67zqxp.js → index-tf4j19ge.js} +1 -1
  53. package/dist/server/_chunks/{index-qn4z5s3c.js → index-typcbcsv.js} +3 -3
  54. package/dist/server/_chunks/{index-p77b4kcx.js → index-veycp46e.js} +1 -1
  55. package/dist/server/_chunks/{index-11sfk4hb.js → index-vmr35jjw.js} +1 -1
  56. package/dist/server/_chunks/{index-kq8kpzye.js → index-vqs3rebe.js} +3 -3
  57. package/dist/server/_chunks/{index-danncfhy.js → index-wm36rj4v.js} +1 -1
  58. package/dist/server/_chunks/{index-z4z9zv3b.js → index-x9c55pzy.js} +141 -3
  59. package/dist/server/_chunks/{index-y2jr2n72.js → index-xrsg0041.js} +4 -4
  60. package/dist/server/_chunks/{index-k1g3epw0.js → index-xs3411qh.js} +10 -10
  61. package/dist/server/_chunks/{index-0374j2b9.js → index-y4d02znn.js} +1 -1
  62. package/dist/server/_chunks/{index-wpfhfbs4.js → index-y71a76dn.js} +4 -4
  63. package/dist/server/_chunks/{index-qm6kmhqs.js → index-y7mzvq2q.js} +1 -1
  64. package/dist/server/_chunks/{index-hkdfj58q.js → index-y9bygr95.js} +1 -1
  65. package/dist/server/_chunks/{index-3tf1xjsp.js → index-yghskk8w.js} +11 -11
  66. package/dist/server/_chunks/{index-5gyr4emz.js → index-yzcpr3yw.js} +4 -4
  67. package/dist/server/_chunks/{index-x93hv0sc.js → index-zedjt25v.js} +23 -10
  68. package/dist/server/_chunks/{index-tq0pc7eg.js → index-zfrwq472.js} +3 -3
  69. package/dist/server/_chunks/{loader-7yw0j98z.js → loader-w1e0n5sm.js} +12 -10
  70. package/dist/server/_chunks/{modules-jn8bmbn8.js → modules-730j14cm.js} +14 -12
  71. package/dist/server/_chunks/{pipeline-yy9jhydf.js → pipeline-yjdnwbhm.js} +25 -21
  72. package/dist/server/_chunks/{production-jar9ztm3.js → production-1xe9b7wd.js} +14 -3
  73. package/dist/server/_chunks/{proxy-config-j84dgksn.js → proxy-config-9r9e0jvn.js} +7 -5
  74. package/dist/server/_chunks/{proxy-w1d0wmsn.js → proxy-pnevsbfd.js} +12 -10
  75. package/dist/server/_chunks/{router-k1reahfn.js → router-rzge0vz8.js} +10 -7
  76. package/dist/server/_chunks/{routes-2s277fc6.js → routes-0x8wjvcj.js} +12 -10
  77. package/dist/server/_chunks/{run-pvd8bs1t.js → run-tk90r3ac.js} +5 -4
  78. package/dist/server/_chunks/{server-mt4a994c.js → server-gev78ejc.js} +38 -34
  79. package/dist/server/_chunks/{tsconfig-defaults-1nb3308g.js → tsconfig-defaults-qe9wd6ne.js} +5 -4
  80. package/dist/server/_chunks/{typegen-0qr0459b.js → typegen-0yw8sry8.js} +15 -13
  81. package/dist/server/cli/index.js +12 -15
  82. package/dist/server/cli/start.js +35 -14
  83. package/dist/server/compat/next/cache.js +5 -5
  84. package/dist/server/compat/next/config-headers.js +8 -6
  85. package/dist/server/compat/next/config-loader.js +1 -1
  86. package/dist/server/compat/next/dist/server/web/spec-extension/revalidate.js +5 -5
  87. package/dist/server/compat/next/dist/server/web/spec-extension/unstable-cache.js +5 -5
  88. package/dist/server/compat/next/dist/server/web/spec-extension/unstable-no-store.js +5 -5
  89. package/dist/server/compat/next/dynamic.js +3 -14
  90. package/dist/server/compat/next/font/cache.js +6 -4
  91. package/dist/server/compat/next/font/local.js +7 -5
  92. package/dist/server/compat/next/font/runtime.js +7 -5
  93. package/dist/server/compat/next/headers.js +4 -4
  94. package/dist/server/compat/next/image/config.js +2 -2
  95. package/dist/server/compat/next/image/optimizer.js +3 -3
  96. package/dist/server/compat/next/image/static-metadata.js +4 -4
  97. package/dist/server/compat/next/legacy-request-apis.js +3 -3
  98. package/dist/server/compat/next/link-transform.js +4 -3
  99. package/dist/server/compat/next/navigation.js +5 -4
  100. package/dist/server/compat/next/redirects.js +8 -6
  101. package/dist/server/compat/next/resource-hints.js +2 -2
  102. package/dist/server/compat/next/rewrites.js +7 -5
  103. package/dist/server/compat/next/root-params.js +3 -3
  104. package/dist/server/compat/next/route-state.js +2 -2
  105. package/dist/server/compat/next/script.js +2 -2
  106. package/dist/server/compat/next/server.js +5 -5
  107. package/dist/server/generation.json +1 -1
  108. package/package.json +1 -1
  109. package/reference/compat.md +1 -1
  110. package/reference/config.md +2 -2
  111. package/reference/dev.md +1 -1
  112. package/reference/getting-started.md +1 -1
  113. package/reference/rendering.md +4 -4
  114. package/src/api/dynamic.tsx +84 -4
  115. package/src/cli/adapters/vercel-warm.ts +40 -29
  116. package/src/cli/adapters/vercel.ts +101 -1265
  117. package/src/cli/analyze.ts +3 -2
  118. package/src/cli/build/cache.ts +6 -6
  119. package/src/cli/build.ts +33 -33
  120. package/src/cli/index.ts +4 -6
  121. package/src/cli/serve/pipeline.ts +16 -10
  122. package/src/cli/serve/standalone-worker.ts +8 -0
  123. package/src/cli/serve/standalone.ts +727 -0
  124. package/src/cli/start.ts +29 -8
  125. package/src/client/build.ts +1 -1
  126. package/src/client/reference-stub.ts +2 -34
  127. package/src/compat/actions/extensions.ts +3 -2
  128. package/src/compat/bundler/require-context.ts +2 -1
  129. package/src/compat/bundler/webpack-loaders.ts +3 -2
  130. package/src/compat/bundler/worker.ts +2 -2
  131. package/src/compat/css/inline-css.ts +1 -1
  132. package/src/compat/export/build-complete.ts +1 -1
  133. package/src/compat/export/emit.ts +4 -4
  134. package/src/compat/export/standalone.ts +30 -65
  135. package/src/compat/image-optimizer/optimize.ts +1 -1
  136. package/src/compat/lifecycle/instrumentation-client.ts +4 -3
  137. package/src/compat/metadata-artifacts.ts +1 -1
  138. package/src/compat/next/config-loader.ts +3 -0
  139. package/src/compat/next/dynamic.tsx +10 -23
  140. package/src/compat/next/font/cache.ts +2 -1
  141. package/src/compat/next/font/runtime.ts +1 -1
  142. package/src/compat/register/image.ts +1 -1
  143. package/src/compat/typecheck/check.ts +6 -4
  144. package/src/config.ts +28 -5
  145. package/src/css/assets.ts +1 -1
  146. package/src/css/build.ts +16 -9
  147. package/src/dev/client-chunk-store.ts +2 -1
  148. package/src/dev/restart/client-key.ts +2 -1
  149. package/src/dev/restart/global-css.ts +2 -1
  150. package/src/dev/restart/route-bundle-key.ts +2 -1
  151. package/src/dev/restart/route-facts.ts +2 -1
  152. package/src/dev/server.ts +8 -7
  153. package/src/out-paths.ts +10 -0
  154. package/src/render/renderer.ts +1 -1
  155. package/src/resolve/dynamic.ts +4 -0
  156. package/src/resolve/engine.ts +2 -12
  157. package/src/resolve/scan-facts.ts +185 -1
  158. package/src/routing/metadata-files.ts +1 -1
  159. package/src/runtime/loader.ts +5 -3
  160. package/src/runtime/module-cache.ts +2 -1
  161. package/src/runtime/modules.ts +50 -16
  162. package/src/runtime/prebundle.ts +23 -3
  163. package/src/runtime/production.ts +105 -40
  164. package/src/runtime/release-graph.ts +21 -13
  165. package/src/runtime/vendor-build.ts +45 -23
  166. package/src/types.ts +2 -3
  167. package/src/utils/directive.ts +40 -0
  168. package/src/utils/fs.ts +7 -2
  169. package/src/utils/resource-query.ts +12 -0
  170. package/dist/server/_chunks/index-tqn2qnnn.js +0 -241
  171. package/dist/server/_chunks/index-y36a0ybw.js +0 -57
  172. package/src/cli/serve/entry.ts +0 -52
@@ -8,6 +8,7 @@ import { matchRoute } from '../routing/routes'
8
8
  import { bold, cyan, dim } from '../utils/ansi'
9
9
  import { listFiles } from '../utils/fs'
10
10
  import type { BuildManifest, RouteManifestEntry } from '../types'
11
+ import { buildManifestFile } from '../runtime/production'
11
12
 
12
13
  export interface AnalyzeResult {
13
14
  root: string
@@ -109,7 +110,7 @@ async function analyzeRouteBundles(
109
110
  files: AnalyzeFile[],
110
111
  routeFilter?: string,
111
112
  ) {
112
- const manifestPath = path.join(outPath, 'manifest.json')
113
+ const manifestPath = buildManifestFile(outPath)
113
114
  if (!existsSync(manifestPath)) return []
114
115
 
115
116
  const manifest = JSON.parse(await readFile(manifestPath, 'utf8')) as BuildManifest
@@ -374,7 +375,7 @@ function prerenderedPathname(route: RouteManifestEntry) {
374
375
  function analyzeTarget(outPath: string) {
375
376
  // PPR shells live in `.pnext/ppr`, outside `public`: they are resumed
376
377
  // server-side and never downloaded, so they are not shipped weight.
377
- const publicPath = path.join(outPath, 'public')
378
+ const publicPath = path.join(outPath, 'static')
378
379
  return existsSync(publicPath) ? { root: publicPath } : null
379
380
  }
380
381
 
@@ -7,9 +7,11 @@ import type { ResolvedConfig } from '../../config'
7
7
  import { frameworkFingerprint } from '../../runtime/fingerprint'
8
8
  import type { BuildManifest } from '../../types'
9
9
  import { writeFileAtomic } from '../../utils/fs'
10
+ import { buildManifestFile } from '../../runtime/production'
11
+ import { outCachePath } from '../../out-paths'
10
12
 
11
13
  const CACHE_VERSION = 2
12
- const CACHE_SEGMENTS = ['cache', 'build'] as const
14
+ const CACHE_SEGMENTS = ['build'] as const
13
15
  const SKIP_INPUT_DIRS = new Set([
14
16
  '.claude',
15
17
  '.git',
@@ -75,9 +77,7 @@ export async function lookupBuildCache(
75
77
  }
76
78
  try {
77
79
  const manifest = resolveManifest(
78
- JSON.parse(
79
- await readFile(path.join(config.outPath, 'manifest.json'), 'utf8'),
80
- ) as BuildManifest,
80
+ JSON.parse(await readFile(buildManifestFile(config.outPath), 'utf8')) as BuildManifest,
81
81
  config.outPath,
82
82
  config.root,
83
83
  )
@@ -121,7 +121,7 @@ function cacheEnabled(options: BuildCacheOptions) {
121
121
  }
122
122
 
123
123
  function cacheDir(outPath: string) {
124
- return path.join(outPath, ...CACHE_SEGMENTS)
124
+ return path.join(outCachePath(outPath), ...CACHE_SEGMENTS)
125
125
  }
126
126
 
127
127
  function recordFile(outPath: string) {
@@ -220,7 +220,7 @@ async function collectModuleGraphInputs(config: ResolvedConfig, files: Map<strin
220
220
  let parsed: ModuleGraphIndex
221
221
  try {
222
222
  parsed = JSON.parse(
223
- await readFile(path.join(config.outPath, 'cache', 'server', 'graph.json'), 'utf8'),
223
+ await readFile(path.join(outCachePath(config.outPath), 'server', 'graph.json'), 'utf8'),
224
224
  ) as ModuleGraphIndex
225
225
  } catch {
226
226
  return
package/src/cli/build.ts CHANGED
@@ -26,7 +26,7 @@ import { flushDevModuleCaches } from '../runtime/module-cache'
26
26
  import { scanFactsStats } from '../resolve/scan-facts'
27
27
  import { clientEntryName } from '../client/chunk-name'
28
28
  import { compiledClientReferenceFiles } from '../client/reference'
29
- import { buildIndexFile } from '../runtime/production'
29
+ import { buildIndexFile, buildManifestFile } from '../runtime/production'
30
30
  import { registerServerRuntime, serverBundleTargetForRuntime } from '../runtime/loader'
31
31
  import {
32
32
  buildGlobalCss,
@@ -94,7 +94,7 @@ import {
94
94
  import { interceptionMarkerLevels } from '../routing/slots'
95
95
  import { writeTypegen } from './typegen'
96
96
  import { lookupBuildCache, writeBuildCache } from './build/cache'
97
- import { emitServerEntry } from './serve/entry'
97
+ import { startStandalone, writeStandalone } from './serve/standalone'
98
98
  import { immutableAssetPath } from './serve/immutable'
99
99
  import { createVerboseLogger, type VerboseLogger } from '../utils/verbose'
100
100
  import { bold, cyan, dim, green } from '../utils/ansi'
@@ -231,12 +231,14 @@ async function runBuild(
231
231
  const warmMode = options.adapter === 'vercel' ? 'full' : 'compile'
232
232
  const warm = startWarmChild(config, warmMode)
233
233
  lifecycle.warm = warm
234
+ // The framework's half of the standalone trace needs no build output; it overlaps the bundling.
235
+ const standalone = startStandalone(config)
234
236
  const publicFiles = await log.step('prepare output directory', async () => {
235
237
  // Build-owned outputs only: `<outRoot>/dev` belongs to a possibly-running
236
238
  // dev server and must survive.
237
239
  // 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'))
240
+ await ensureEmptyDir(config.outRootPath, [devOutSegment, 'pnext-pages-compat'])
241
+ return copyPublicDir(config.publicPath, path.join(config.outPath, 'static'))
240
242
  })
241
243
  // The document-level stylesheets run their postcss/Tailwind pass on the CSS
242
244
  // worker, so they overlap with the route scan below instead of serializing
@@ -411,7 +413,7 @@ async function runBuild(
411
413
  buildClientEntries({
412
414
  config,
413
415
  routes: clientRoutes,
414
- outDir: path.join(config.outPath, 'public', 'assets'),
416
+ outDir: path.join(config.outPath, 'static', 'assets'),
415
417
  verbose,
416
418
  hasServerActions: actionSources.length > 0,
417
419
  pipeline: clientSources,
@@ -449,7 +451,7 @@ async function runBuild(
449
451
  // Standalone static chunks (compat: the no-module polyfills chunk) live
450
452
  // outside the esbuild entry graph, so emit them regardless of whether any
451
453
  // route produced a client bundle.
452
- await emitStaticClientChunks(config, path.join(config.outPath, 'public', 'assets'))
454
+ await emitStaticClientChunks(config, path.join(config.outPath, 'static', 'assets'))
453
455
  // All three source consumers have run by here; the split says how much of the
454
456
  // app was read once and shared rather than read per consumer.
455
457
  if (verbose) {
@@ -787,7 +789,7 @@ async function runBuild(
787
789
  html: rendered.value.html,
788
790
  status: rendered.value.status,
789
791
  })
790
- const relative = toPosixPath(path.relative(path.join(config.outPath, 'public'), file))
792
+ const relative = toPosixPath(path.relative(path.join(config.outPath, 'static'), file))
791
793
  const revalidateSeconds = combineRevalidate(
792
794
  segmentConfig?.revalidate,
793
795
  rendered.revalidateSeconds,
@@ -951,30 +953,25 @@ async function runBuild(
951
953
  }
952
954
  await writeBuildManifest(config.outPath, manifest)
953
955
  log.log(`wrote manifest.json (${routes.length} route${routes.length === 1 ? '' : 's'})`)
954
- await log.step('server entry', () => emitServerEntry(config.outPath))
955
956
  for (const hook of getBuildExtensions().completeHooks) {
956
957
  await hook({ config, manifest, log })
957
958
  }
958
- if (options.adapter === 'vercel')
959
- await log.step('vercel adapter output', () =>
960
- writeVercelOutput(config, manifest, { verbose, warm }),
961
- )
962
- // Plain build: the adapter owns the child in the branch above. Compiling the
963
- // rest of the app's modules is build work, so it counts toward the build's own
959
+ // Compiling the rest of the app's modules is build work, so it counts toward the build's own
964
960
  // duration rather than hiding after it.
965
- else {
966
- await log.step('warm module cache', () =>
967
- warm.finish(log, undefined, {
968
- globalCss: globalCssSources(config),
969
- clientReferences: [...compiledClientReferenceFiles()],
970
- }),
971
- )
972
- }
961
+ await log.step('warm module cache', () =>
962
+ warm.finish(log, undefined, {
963
+ globalCss: globalCssSources(config),
964
+ clientReferences: [...compiledClientReferenceFiles()],
965
+ }),
966
+ )
973
967
  // The release names every module production imports; a server compile that did not finish
974
968
  // fails the build here rather than a request later.
975
969
  if (!existsSync(buildIndexFile(config.outPath))) {
976
970
  throw new Error('pnext build: the server compile did not complete (see the error above).')
977
971
  }
972
+ await log.step('standalone output', () => writeStandalone(config, standalone))
973
+ if (options.adapter === 'vercel')
974
+ await log.step('vercel adapter output', () => writeVercelOutput(config, manifest, { verbose }))
978
975
 
979
976
  // Also cover module loads performed by completion hooks or the warm pass.
980
977
  throwIfModuleGraphFailed()
@@ -1079,8 +1076,9 @@ function interceptionDisplayRoute(route: RouteManifestEntry, filled?: string): s
1079
1076
 
1080
1077
  async function writeBuildManifest(outPath: string, manifest: BuildManifest) {
1081
1078
  assertManifestServerArtifacts(outPath, manifest)
1082
- const file = path.join(outPath, 'manifest.json')
1083
- const temporary = path.join(outPath, `.manifest-${process.pid}.tmp`)
1079
+ const file = buildManifestFile(outPath)
1080
+ const temporary = `${file}.${process.pid}.tmp`
1081
+ await mkdir(path.dirname(file), { recursive: true })
1084
1082
  await writeFile(temporary, serializeBuildManifest(manifest))
1085
1083
  await rename(temporary, file)
1086
1084
  }
@@ -1090,9 +1088,11 @@ function assertManifestServerArtifacts(outPath: string, manifest: BuildManifest)
1090
1088
  ...(manifest.proxyModule ? [manifest.proxyModule] : []),
1091
1089
  ...(manifest.actions?.map(action => action.modulePath) ?? []),
1092
1090
  ]
1091
+ // Compiled artifacts still sit in the build cache beside the release until writeStandalone moves them.
1092
+ const outRoot = path.dirname(outPath)
1093
1093
  for (const artifact of artifacts) {
1094
1094
  const file = path.resolve(outPath, artifact)
1095
- if (file !== outPath && !file.startsWith(`${outPath}${path.sep}`)) {
1095
+ if (!file.startsWith(`${outRoot}${path.sep}`)) {
1096
1096
  throw new Error(`Build manifest server artifact escapes output directory: ${artifact}`)
1097
1097
  }
1098
1098
  if (!existsSync(file)) {
@@ -2256,7 +2256,7 @@ async function renderNotFoundDocuments({
2256
2256
 
2257
2257
  if (await shouldBuildGlobalNotFound(config)) {
2258
2258
  await log.step('global not-found', async () =>
2259
- writeText(path.join(config.outPath, 'public', '404.html'), await render()),
2259
+ writeText(path.join(config.outPath, 'static', '404.html'), await render()),
2260
2260
  )
2261
2261
  }
2262
2262
  // Next always prerenders the built-in `/_not-found` document for a compat
@@ -2264,7 +2264,7 @@ async function renderNotFoundDocuments({
2264
2264
  // `.next/server/app/_not-found.html`). When public/404.html was written, the
2265
2265
  // .next artifacts are copied from it; otherwise they need a document here.
2266
2266
  if (!config.compat?.next) return undefined
2267
- if (existsSync(path.join(config.outPath, 'public', '404.html'))) return undefined
2267
+ if (existsSync(path.join(config.outPath, 'static', '404.html'))) return undefined
2268
2268
  // Nothing prerenderable to render into the document: either the app authored no not-found.* at
2269
2269
  // all, or it authored one and declared it force-dynamic, in which case Next leaves `/_not-found`
2270
2270
  // dynamic and prerenders no custom 404 either. Emit the standalone default rather than boot the
@@ -2322,7 +2322,7 @@ async function emitNextNotFoundArtifacts(
2322
2322
  fallback404?: string,
2323
2323
  ) {
2324
2324
  if (!config.compat?.next) return
2325
- const source = path.join(config.outPath, 'public', '404.html')
2325
+ const source = path.join(config.outPath, 'static', '404.html')
2326
2326
  const html = existsSync(source) ? readFileSync(source, 'utf8') : fallback404
2327
2327
  if (html === undefined) return
2328
2328
 
@@ -2539,7 +2539,7 @@ async function buildStaticRouteHandler(
2539
2539
  if (rendered.noStore && !staticRouteHandlerExplicitlyCached(route)) continue
2540
2540
  const body = await settleBeforeNextTask(response.clone().arrayBuffer())
2541
2541
  if (!body) continue
2542
- const relative = toPosixPath(path.relative(path.join(config.outPath, 'public'), file))
2542
+ const relative = toPosixPath(path.relative(path.join(config.outPath, 'static'), file))
2543
2543
  // Descendant handlers record their manifest entry (so the synthesized
2544
2544
  // prerender-manifest lists them) but skip the on-disk copy that would
2545
2545
  // collide with the ancestor's file; they serve dynamically at runtime.
@@ -2858,7 +2858,7 @@ async function copyStaticMetadataFiles(
2858
2858
  }
2859
2859
 
2860
2860
  export function staticHtmlPath(outPath: string, routePath: string, flatLayout = false) {
2861
- if (routePath === '/') return path.join(outPath, 'public', 'index.html')
2861
+ if (routePath === '/') return path.join(outPath, 'static', 'index.html')
2862
2862
  const normalized = routePath.replace(/^\/|\/$/g, '')
2863
2863
  // output:'export' with trailingSlash:false lays pages out flat (`/a.html`);
2864
2864
  // otherwise (and always for trailingSlash:true) each page gets its own dir
@@ -2957,7 +2957,7 @@ function staticRouteHandlerPath(outPath: string, routePath: string) {
2957
2957
  * route serves dynamically (start's static lookup only matches real files, then falls through).
2958
2958
  */
2959
2959
  function staticOutputCollision(outPath: string, file: string): string | null {
2960
- const publicPath = path.join(outPath, 'public')
2960
+ const publicPath = path.join(outPath, 'static')
2961
2961
  if (existsSync(file) && statSync(file).isDirectory()) {
2962
2962
  return `${toPosixPath(path.relative(publicPath, file))} already exists as a directory`
2963
2963
  }
@@ -3177,7 +3177,7 @@ function realFilePath(file: string): string {
3177
3177
  }
3178
3178
 
3179
3179
  function safePublicPath(outPath: string, ...segments: string[]) {
3180
- const publicPath = path.join(outPath, 'public')
3180
+ const publicPath = path.join(outPath, 'static')
3181
3181
  const file = path.join(publicPath, ...segments)
3182
3182
  const relative = path.relative(publicPath, file)
3183
3183
  if (relative.startsWith('..') || path.isAbsolute(relative)) {
@@ -3204,7 +3204,7 @@ async function copyPartytownLib(config: Awaited<ReturnType<typeof loadConfig>>)
3204
3204
  )
3205
3205
  return
3206
3206
  }
3207
- const target = path.join(config.outPath, 'public', '_next', 'static', '~partytown')
3207
+ const target = path.join(config.outPath, 'static', '_next', 'static', '~partytown')
3208
3208
  await mkdir(target, { recursive: true })
3209
3209
  await copyPublicDir(libDir, target)
3210
3210
  }
package/src/cli/index.ts CHANGED
@@ -168,13 +168,11 @@ declare const PNEXT_PREBUNDLE: { version: string; fingerprint: string } | undefi
168
168
  /** Whether this process's prebundle may serve `root`'s build: one made from its source and version. */
169
169
  async function prebundleServes(root = process.cwd()) {
170
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)
171
+ const [{ DEFAULT_OUT_DIR, standaloneOutSegment }, { buildIndexFile, readBuildIndex }] =
172
+ await Promise.all([import('../config'), import('../runtime/production')])
173
+ const outPath = path.resolve(root, DEFAULT_OUT_DIR, standaloneOutSegment)
176
174
  return (
177
- !outPath ||
175
+ !existsSync(buildIndexFile(outPath)) ||
178
176
  (readBuildIndex(outPath).framework === PNEXT_PREBUNDLE.fingerprint &&
179
177
  VERSION === PNEXT_PREBUNDLE.version)
180
178
  )
@@ -21,7 +21,12 @@ import {
21
21
  } from '../../runtime/load'
22
22
  import { abortUpstreamFetchOnDisconnect } from '../../runtime/fetch-host'
23
23
  import { applyProxyResponse, createProxyRunner, type ProxyRunnerOptions } from '../../routing/proxy'
24
- import { attachRelease, releaseModuleHref } from '../../runtime/production'
24
+ import {
25
+ attachRelease,
26
+ buildManifestFile,
27
+ releaseFrameworkRoot,
28
+ releaseModuleHref,
29
+ } from '../../runtime/production'
25
30
  import {
26
31
  isPprShellUpgradeEligible,
27
32
  renderGlobalNotFoundResponse,
@@ -91,13 +96,14 @@ export async function createRequestHandler(
91
96
  // extension registries when compat is enabled (no-op for pure-core apps).
92
97
  // A prod server answers the very next request, so it takes both tiers here.
93
98
  await bootstrapCompat(config)
94
- const manifestPath = path.join(config.outPath, 'manifest.json')
99
+ const manifestPath = buildManifestFile(config.outPath)
95
100
  // `start` reads the manifest before binding the port (a missing build must
96
101
  // still fail there, not on the first request) and hands it over.
97
102
  const manifest = resolveManifest(
98
103
  options.manifest ?? (JSON.parse(await readFile(manifestPath, 'utf8')) as BuildManifest),
99
104
  config.outPath,
100
105
  config.root,
106
+ releaseFrameworkRoot(config.outPath),
101
107
  )
102
108
  // Everything a request imports comes from the build's release; each handler resolves once, here.
103
109
  const release = attachRelease(config)
@@ -671,7 +677,7 @@ export async function createRequestHandler(
671
677
  await mkdir(path.dirname(file), { recursive: true })
672
678
  await writeFile(file, new Uint8Array(await handlerResponse.clone().arrayBuffer()))
673
679
  const relative = path
674
- .relative(path.join(config.outPath, 'public'), file)
680
+ .relative(path.join(config.outPath, 'static'), file)
675
681
  .split(path.sep)
676
682
  .join('/')
677
683
  const routeRevalidate = matched.route.segmentConfig?.revalidate
@@ -847,7 +853,7 @@ export async function createRequestHandler(
847
853
  await mkdir(path.dirname(file), { recursive: true })
848
854
  await writeFile(file, await pageResponse.clone().text())
849
855
  const relative = path
850
- .relative(path.join(config.outPath, 'public'), file)
856
+ .relative(path.join(config.outPath, 'static'), file)
851
857
  .split(path.sep)
852
858
  .join('/')
853
859
  manifest.staticFiles ??= {}
@@ -1091,12 +1097,12 @@ async function builtFileInfo(
1091
1097
  exactNames?: ExactNames,
1092
1098
  ): Promise<BuiltFileInfo | null> {
1093
1099
  const file = await firstFile(
1094
- path.join(outPath, 'public'),
1100
+ path.join(outPath, 'static'),
1095
1101
  builtFileCandidates(outPath, pathname, nextStaticFallback),
1096
1102
  exactNames,
1097
1103
  )
1098
1104
  if (!file) return null
1099
- const publicPath = path.join(outPath, 'public')
1105
+ const publicPath = path.join(outPath, 'static')
1100
1106
  const fileStat = await stat(file)
1101
1107
  const relative = path.relative(publicPath, file).split(path.sep).join('/')
1102
1108
  return { file, relative, mtimeMs: fileStat.mtimeMs, metadata: staticFiles[relative] }
@@ -1110,7 +1116,7 @@ function builtFileCandidates(
1110
1116
  pathname: string,
1111
1117
  nextStaticFallback = false,
1112
1118
  ): string[] {
1113
- const publicPath = path.join(outPath, 'public')
1119
+ const publicPath = path.join(outPath, 'static')
1114
1120
  const trimmed = pathname.replace(/^\/+/, '')
1115
1121
  if (pathname === '/') return [path.join(publicPath, 'index.html')]
1116
1122
  const candidates = [
@@ -1142,7 +1148,7 @@ function builtFileCandidates(
1142
1148
  // Where a lazily generated page for `pathname` is persisted (mirrors the
1143
1149
  // build's staticHtmlPath); null when the path would escape public/.
1144
1150
  function lazyStaticHtmlPath(outPath: string, pathname: string): string | null {
1145
- const publicPath = path.join(outPath, 'public')
1151
+ const publicPath = path.join(outPath, 'static')
1146
1152
  const file =
1147
1153
  pathname === '/'
1148
1154
  ? path.join(publicPath, 'index.html')
@@ -1154,7 +1160,7 @@ function lazyStaticHtmlPath(outPath: string, pathname: string): string | null {
1154
1160
 
1155
1161
  function lazyStaticHandlerPath(outPath: string, pathname: string): string | null {
1156
1162
  if (pathname === '/') return null
1157
- const publicPath = path.join(outPath, 'public')
1163
+ const publicPath = path.join(outPath, 'static')
1158
1164
  const file = path.join(publicPath, pathname.replace(/^\/+|\/+$/g, ''))
1159
1165
  const relative = path.relative(publicPath, file)
1160
1166
  if (relative.startsWith('..') || path.isAbsolute(relative)) return null
@@ -1224,7 +1230,7 @@ export async function maybeBuiltFile(
1224
1230
  const normalizedMethod = method.toUpperCase()
1225
1231
  if (normalizedMethod !== 'GET' && normalizedMethod !== 'HEAD') return null
1226
1232
 
1227
- const publicPath = path.join(outPath, 'public')
1233
+ const publicPath = path.join(outPath, 'static')
1228
1234
  const file = await firstFile(
1229
1235
  publicPath,
1230
1236
  builtFileCandidates(outPath, pathname, nextStaticFallback),
@@ -0,0 +1,8 @@
1
+ // Traces the framework's standalone closure off the build's main thread (see startStandalone).
2
+ import { traceFramework } from './standalone'
3
+
4
+ declare const self: Worker
5
+
6
+ self.onmessage = async (event: MessageEvent) => {
7
+ self.postMessage(await traceFramework(event.data as Parameters<typeof traceFramework>[0]))
8
+ }