@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.
- package/dist/server/_chunks/{aliases-j47a10ce.js → aliases-fhv4dt06.js} +7 -5
- package/dist/server/_chunks/{analyze-arswqe6s.js → analyze-09kx9q6r.js} +17 -13
- package/dist/server/_chunks/{boot-af0mv3dy.js → boot-8aj7efqk.js} +13 -11
- package/dist/server/_chunks/{build-spy3dxp4.js → build-jda155c9.js} +7 -5
- package/dist/server/_chunks/{build-tier-m7yvqz61.js → build-tier-qrkpfsk1.js} +59 -75
- package/dist/server/_chunks/{build-t9h0hec3.js → build-wspv5h60.js} +1004 -1191
- package/dist/server/_chunks/{compile-53j02j27.js → compile-040r79gj.js} +2 -2
- package/dist/server/_chunks/{config-n2z7yxps.js → config-7h84p6q8.js} +6 -4
- package/dist/server/_chunks/{config-1yzwexq6.js → config-d4hqyygy.js} +12 -3
- package/dist/server/_chunks/{create-meec9hs6.js → create-skj8wzt5.js} +4 -3
- package/dist/server/_chunks/{dev-fjmqg6en.js → dev-pennd36n.js} +2 -2
- package/dist/server/_chunks/{generate-n9sh6hzt.js → generate-d8vb1d21.js} +5 -4
- package/dist/server/_chunks/{index-eeaanp2e.js → index-0qt2vapb.js} +3 -3
- package/dist/server/_chunks/{index-91x12ykq.js → index-0r5eqfc7.js} +6 -1
- package/dist/server/_chunks/{index-9ych9ma8.js → index-0wm2p3ks.js} +2 -2
- package/dist/server/_chunks/{index-357na4a8.js → index-141vcwk6.js} +1 -1
- package/dist/server/_chunks/{index-2dv4y4wd.js → index-1y0cesgn.js} +16 -10
- package/dist/server/_chunks/{index-ytjvpbm2.js → index-26gwrm07.js} +3 -3
- package/dist/server/_chunks/{index-8k7pfejn.js → index-3r6qpe8a.js} +7 -7
- package/dist/server/_chunks/{index-rn8dyr1f.js → index-42fef2rv.js} +8 -48
- package/dist/server/_chunks/{index-ncnes8c6.js → index-47gx7trn.js} +2 -2
- package/dist/server/_chunks/{index-20ppawv7.js → index-4qsce64w.js} +3 -3
- package/dist/server/_chunks/{index-1011cscr.js → index-4vf121ws.js} +61 -29
- package/dist/server/_chunks/{index-cf4rvxv6.js → index-52k54ykj.js} +1 -1
- package/dist/server/_chunks/{index-nyrba2kr.js → index-53fnn598.js} +11 -11
- package/dist/server/_chunks/{index-4hgjrqh7.js → index-6tb725m8.js} +2 -2
- package/dist/server/_chunks/{index-3xbr4eyv.js → index-912z4mfx.js} +3 -3
- package/dist/server/_chunks/{index-sjpckxqn.js → index-9f49w76j.js} +1 -1
- package/dist/server/_chunks/{index-jepjvcrf.js → index-aarf1brn.js} +1 -1
- package/dist/server/_chunks/{index-9n2914ww.js → index-akkrvjn6.js} +1 -1
- package/dist/server/_chunks/index-bzd2ef7t.js +10 -0
- package/dist/server/_chunks/{index-sv8m6789.js → index-cqcwwxfp.js} +5 -5
- package/dist/server/_chunks/{index-yz54pxrh.js → index-d1jsmhhk.js} +4 -9
- package/dist/server/_chunks/{index-vvmmknm1.js → index-da0fphj0.js} +19 -15
- package/dist/server/_chunks/{index-sctcgyvv.js → index-drwv61cc.js} +2 -2
- package/dist/server/_chunks/{index-z84ab1w0.js → index-e176wk6x.js} +3 -3
- package/dist/server/_chunks/{index-9hx2641q.js → index-entm8bmz.js} +1 -1
- package/dist/server/_chunks/index-fpghsgb4.js +352 -0
- package/dist/server/_chunks/{index-jx7bqvw1.js → index-hr63fvzn.js} +1 -1
- package/dist/server/_chunks/{index-eajaspjk.js → index-j0m1jxqa.js} +1 -1
- package/dist/server/_chunks/index-jbj7ehef.js +50 -0
- package/dist/server/_chunks/{index-egykcqg3.js → index-jexsy9a8.js} +1 -1
- package/dist/server/_chunks/{index-fkp000p1.js → index-jjppzw0s.js} +2 -2
- package/dist/server/_chunks/index-jt8e1pje.js +12 -0
- package/dist/server/_chunks/{index-ggk2j965.js → index-kpdph69z.js} +56 -50
- package/dist/server/_chunks/{index-6e4fqv30.js → index-m63czgq5.js} +2 -0
- package/dist/server/_chunks/{index-c0g2wf3z.js → index-md5jchzy.js} +1 -1
- package/dist/server/_chunks/{index-tvqkq6e6.js → index-n814hcky.js} +1 -1
- package/dist/server/_chunks/{index-06nyqntx.js → index-q3r9z8mq.js} +1 -1
- package/dist/server/_chunks/{index-4q2gbfwk.js → index-qjrh7w2g.js} +2 -2
- package/dist/server/_chunks/{index-3b3at80h.js → index-s61bx2aj.js} +6 -3
- package/dist/server/_chunks/{index-ym67zqxp.js → index-tf4j19ge.js} +1 -1
- package/dist/server/_chunks/{index-qn4z5s3c.js → index-typcbcsv.js} +3 -3
- package/dist/server/_chunks/{index-p77b4kcx.js → index-veycp46e.js} +1 -1
- package/dist/server/_chunks/{index-11sfk4hb.js → index-vmr35jjw.js} +1 -1
- package/dist/server/_chunks/{index-kq8kpzye.js → index-vqs3rebe.js} +3 -3
- package/dist/server/_chunks/{index-danncfhy.js → index-wm36rj4v.js} +1 -1
- package/dist/server/_chunks/{index-z4z9zv3b.js → index-x9c55pzy.js} +141 -3
- package/dist/server/_chunks/{index-y2jr2n72.js → index-xrsg0041.js} +4 -4
- package/dist/server/_chunks/{index-k1g3epw0.js → index-xs3411qh.js} +10 -10
- package/dist/server/_chunks/{index-0374j2b9.js → index-y4d02znn.js} +1 -1
- package/dist/server/_chunks/{index-wpfhfbs4.js → index-y71a76dn.js} +4 -4
- package/dist/server/_chunks/{index-qm6kmhqs.js → index-y7mzvq2q.js} +1 -1
- package/dist/server/_chunks/{index-hkdfj58q.js → index-y9bygr95.js} +1 -1
- package/dist/server/_chunks/{index-3tf1xjsp.js → index-yghskk8w.js} +11 -11
- package/dist/server/_chunks/{index-5gyr4emz.js → index-yzcpr3yw.js} +4 -4
- package/dist/server/_chunks/{index-x93hv0sc.js → index-zedjt25v.js} +23 -10
- package/dist/server/_chunks/{index-tq0pc7eg.js → index-zfrwq472.js} +3 -3
- package/dist/server/_chunks/{loader-7yw0j98z.js → loader-w1e0n5sm.js} +12 -10
- package/dist/server/_chunks/{modules-jn8bmbn8.js → modules-730j14cm.js} +14 -12
- package/dist/server/_chunks/{pipeline-yy9jhydf.js → pipeline-yjdnwbhm.js} +25 -21
- package/dist/server/_chunks/{production-jar9ztm3.js → production-1xe9b7wd.js} +14 -3
- package/dist/server/_chunks/{proxy-config-j84dgksn.js → proxy-config-9r9e0jvn.js} +7 -5
- package/dist/server/_chunks/{proxy-w1d0wmsn.js → proxy-pnevsbfd.js} +12 -10
- package/dist/server/_chunks/{router-k1reahfn.js → router-rzge0vz8.js} +10 -7
- package/dist/server/_chunks/{routes-2s277fc6.js → routes-0x8wjvcj.js} +12 -10
- package/dist/server/_chunks/{run-pvd8bs1t.js → run-tk90r3ac.js} +5 -4
- package/dist/server/_chunks/{server-mt4a994c.js → server-gev78ejc.js} +38 -34
- package/dist/server/_chunks/{tsconfig-defaults-1nb3308g.js → tsconfig-defaults-qe9wd6ne.js} +5 -4
- package/dist/server/_chunks/{typegen-0qr0459b.js → typegen-0yw8sry8.js} +15 -13
- package/dist/server/cli/index.js +12 -15
- package/dist/server/cli/start.js +35 -14
- package/dist/server/compat/next/cache.js +5 -5
- package/dist/server/compat/next/config-headers.js +8 -6
- package/dist/server/compat/next/config-loader.js +1 -1
- package/dist/server/compat/next/dist/server/web/spec-extension/revalidate.js +5 -5
- package/dist/server/compat/next/dist/server/web/spec-extension/unstable-cache.js +5 -5
- package/dist/server/compat/next/dist/server/web/spec-extension/unstable-no-store.js +5 -5
- package/dist/server/compat/next/dynamic.js +3 -14
- package/dist/server/compat/next/font/cache.js +6 -4
- package/dist/server/compat/next/font/local.js +7 -5
- package/dist/server/compat/next/font/runtime.js +7 -5
- package/dist/server/compat/next/headers.js +4 -4
- package/dist/server/compat/next/image/config.js +2 -2
- package/dist/server/compat/next/image/optimizer.js +3 -3
- package/dist/server/compat/next/image/static-metadata.js +4 -4
- package/dist/server/compat/next/legacy-request-apis.js +3 -3
- package/dist/server/compat/next/link-transform.js +4 -3
- package/dist/server/compat/next/navigation.js +5 -4
- package/dist/server/compat/next/redirects.js +8 -6
- package/dist/server/compat/next/resource-hints.js +2 -2
- package/dist/server/compat/next/rewrites.js +7 -5
- package/dist/server/compat/next/root-params.js +3 -3
- package/dist/server/compat/next/route-state.js +2 -2
- package/dist/server/compat/next/script.js +2 -2
- package/dist/server/compat/next/server.js +5 -5
- package/dist/server/generation.json +1 -1
- package/package.json +1 -1
- package/reference/compat.md +1 -1
- package/reference/config.md +2 -2
- package/reference/dev.md +1 -1
- package/reference/getting-started.md +1 -1
- package/reference/rendering.md +4 -4
- package/src/api/dynamic.tsx +84 -4
- package/src/cli/adapters/vercel-warm.ts +40 -29
- package/src/cli/adapters/vercel.ts +101 -1265
- package/src/cli/analyze.ts +3 -2
- package/src/cli/build/cache.ts +6 -6
- package/src/cli/build.ts +33 -33
- package/src/cli/index.ts +4 -6
- package/src/cli/serve/pipeline.ts +16 -10
- package/src/cli/serve/standalone-worker.ts +8 -0
- package/src/cli/serve/standalone.ts +727 -0
- package/src/cli/start.ts +29 -8
- package/src/client/build.ts +1 -1
- package/src/client/reference-stub.ts +2 -34
- package/src/compat/actions/extensions.ts +3 -2
- package/src/compat/bundler/require-context.ts +2 -1
- package/src/compat/bundler/webpack-loaders.ts +3 -2
- package/src/compat/bundler/worker.ts +2 -2
- package/src/compat/css/inline-css.ts +1 -1
- package/src/compat/export/build-complete.ts +1 -1
- package/src/compat/export/emit.ts +4 -4
- package/src/compat/export/standalone.ts +30 -65
- package/src/compat/image-optimizer/optimize.ts +1 -1
- package/src/compat/lifecycle/instrumentation-client.ts +4 -3
- package/src/compat/metadata-artifacts.ts +1 -1
- package/src/compat/next/config-loader.ts +3 -0
- package/src/compat/next/dynamic.tsx +10 -23
- package/src/compat/next/font/cache.ts +2 -1
- package/src/compat/next/font/runtime.ts +1 -1
- package/src/compat/register/image.ts +1 -1
- package/src/compat/typecheck/check.ts +6 -4
- package/src/config.ts +28 -5
- package/src/css/assets.ts +1 -1
- package/src/css/build.ts +16 -9
- package/src/dev/client-chunk-store.ts +2 -1
- package/src/dev/restart/client-key.ts +2 -1
- package/src/dev/restart/global-css.ts +2 -1
- package/src/dev/restart/route-bundle-key.ts +2 -1
- package/src/dev/restart/route-facts.ts +2 -1
- package/src/dev/server.ts +8 -7
- package/src/out-paths.ts +10 -0
- package/src/render/renderer.ts +1 -1
- package/src/resolve/dynamic.ts +4 -0
- package/src/resolve/engine.ts +2 -12
- package/src/resolve/scan-facts.ts +185 -1
- package/src/routing/metadata-files.ts +1 -1
- package/src/runtime/loader.ts +5 -3
- package/src/runtime/module-cache.ts +2 -1
- package/src/runtime/modules.ts +50 -16
- package/src/runtime/prebundle.ts +23 -3
- package/src/runtime/production.ts +105 -40
- package/src/runtime/release-graph.ts +21 -13
- package/src/runtime/vendor-build.ts +45 -23
- package/src/types.ts +2 -3
- package/src/utils/directive.ts +40 -0
- package/src/utils/fs.ts +7 -2
- package/src/utils/resource-query.ts +12 -0
- package/dist/server/_chunks/index-tqn2qnnn.js +0 -241
- package/dist/server/_chunks/index-y36a0ybw.js +0 -57
- package/src/cli/serve/entry.ts +0 -52
package/src/cli/start.ts
CHANGED
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* dynamically once the port is bound, so neither the listen syscall nor the
|
|
5
5
|
* ready banner waits on parsing it.
|
|
6
6
|
*/
|
|
7
|
+
import { existsSync } from 'node:fs'
|
|
7
8
|
import { readFile } from 'node:fs/promises'
|
|
8
9
|
import path from 'node:path'
|
|
10
|
+
import { pathToFileURL } from 'node:url'
|
|
9
11
|
import { loadConfig } from '../config'
|
|
10
12
|
import type { ResolvedConfig } from '../config'
|
|
11
13
|
import { bootstrapCompat } from '../compat-bootstrap'
|
|
@@ -17,6 +19,7 @@ import { registerPrebundleResolve } from '../runtime/prebundle'
|
|
|
17
19
|
import { browserHost, ensurePortFree, openBrowser, printServerReady } from './serve/ui'
|
|
18
20
|
import type { BuildManifest } from '../types'
|
|
19
21
|
import type { PeerAddressSource } from '../routing/forwarded'
|
|
22
|
+
import { buildIndexFile, buildManifestFile, linkStandaloneOrigins } from '../runtime/production'
|
|
20
23
|
|
|
21
24
|
interface StartOptions {
|
|
22
25
|
root?: string
|
|
@@ -35,8 +38,24 @@ export async function createRequestHandler(
|
|
|
35
38
|
options: { root?: string; config?: ResolvedConfig; manifest?: BuildManifest } = {},
|
|
36
39
|
): Promise<RequestHandler> {
|
|
37
40
|
registerPrebundleResolve()
|
|
41
|
+
const config = options.config ?? (await loadConfig(options.root, { serve: true }))
|
|
42
|
+
// A release this copy cannot serve in place runs on the framework copy it ships.
|
|
43
|
+
if (shipsElsewhere(config)) {
|
|
44
|
+
const shipped = await shippedStart(config)
|
|
45
|
+
return shipped.createRequestHandler({ root: options.root, manifest: options.manifest })
|
|
46
|
+
}
|
|
38
47
|
const { createRequestHandler: create } = await import('./serve/pipeline')
|
|
39
|
-
return create(options)
|
|
48
|
+
return create({ ...options, config })
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** A built release this copy cannot serve in place; a missing build falls through to its error. */
|
|
52
|
+
function shipsElsewhere(config: ResolvedConfig) {
|
|
53
|
+
return existsSync(buildIndexFile(config.outPath)) && !linkStandaloneOrigins(config.outPath)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function shippedStart(config: ResolvedConfig) {
|
|
57
|
+
const entry = pathToFileURL(path.join(config.outPath, 'server', 'entry.js')).href
|
|
58
|
+
return import(entry) as Promise<typeof import('./start')>
|
|
40
59
|
}
|
|
41
60
|
|
|
42
61
|
export async function maybeBuiltFile(
|
|
@@ -51,8 +70,14 @@ export async function start(options: StartOptions = {}) {
|
|
|
51
70
|
const port = options.port ?? 3000
|
|
52
71
|
// Next's documented default. Bun resolves 'localhost' to ::1 only, refusing IPv4 clients.
|
|
53
72
|
const hostname = options.hostname ?? '0.0.0.0'
|
|
73
|
+
const config = await loadConfig(options.root, { serve: true })
|
|
74
|
+
// Delegate before compat bootstraps here, so only the shipped copy patches process globals.
|
|
75
|
+
if (shipsElsewhere(config)) {
|
|
76
|
+
await (await shippedStart(config)).start(options)
|
|
77
|
+
return
|
|
78
|
+
}
|
|
54
79
|
// Export builds are not served; pnext serves its standalone output directly.
|
|
55
|
-
|
|
80
|
+
await guardUnservableOutputMode(config)
|
|
56
81
|
const manifest = await readProductionManifest(config)
|
|
57
82
|
await ensurePortFree(port, hostname)
|
|
58
83
|
|
|
@@ -110,9 +135,7 @@ function installProcessErrorHandlers(): void {
|
|
|
110
135
|
|
|
111
136
|
export async function readProductionManifest(config: ResolvedConfig): Promise<BuildManifest> {
|
|
112
137
|
try {
|
|
113
|
-
return JSON.parse(
|
|
114
|
-
await readFile(path.join(config.outPath, 'manifest.json'), 'utf8'),
|
|
115
|
-
) as BuildManifest
|
|
138
|
+
return JSON.parse(await readFile(buildManifestFile(config.outPath), 'utf8')) as BuildManifest
|
|
116
139
|
} catch (error) {
|
|
117
140
|
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
118
141
|
throw new Error("No production build found. Run 'pnext build' first.")
|
|
@@ -122,8 +145,7 @@ export async function readProductionManifest(config: ResolvedConfig): Promise<Bu
|
|
|
122
145
|
}
|
|
123
146
|
|
|
124
147
|
// Export output is unservable; pnext production output remains serveable for standalone apps.
|
|
125
|
-
async function guardUnservableOutputMode(
|
|
126
|
-
const config = await loadConfig(root, { serve: true })
|
|
148
|
+
async function guardUnservableOutputMode(config: ResolvedConfig) {
|
|
127
149
|
await bootstrapCompat(config)
|
|
128
150
|
const mode = getBuildExtensions().compat.nextOutputMode()
|
|
129
151
|
if (mode === 'export') {
|
|
@@ -142,7 +164,6 @@ async function guardUnservableOutputMode(root?: string): Promise<ResolvedConfig>
|
|
|
142
164
|
'Use "node .next/standalone/server.js" instead.',
|
|
143
165
|
)
|
|
144
166
|
}
|
|
145
|
-
return config
|
|
146
167
|
}
|
|
147
168
|
|
|
148
169
|
// Graceful stop: quit accepting connections, wait for in-flight after() flushes (bounded), then exit
|
package/src/client/build.ts
CHANGED
|
@@ -1438,7 +1438,7 @@ async function staticImageModuleSource(config: ResolvedConfig, file: string) {
|
|
|
1438
1438
|
const compat = await getAssetExtensions().staticAssetModule({ sourcePath, bytes, emit })
|
|
1439
1439
|
const source = compat ?? coreStaticAssetModule(sourcePath, bytes, emit)
|
|
1440
1440
|
for (const relative of emitted) {
|
|
1441
|
-
const target = path.join(config.outPath, '
|
|
1441
|
+
const target = path.join(config.outPath, 'static', ...relative.split('/'))
|
|
1442
1442
|
await mkdir(path.dirname(target), { recursive: true })
|
|
1443
1443
|
if (!existsSync(target)) await copyFile(sourcePath, target)
|
|
1444
1444
|
}
|
|
@@ -11,6 +11,7 @@ import type { ResolvedConfig } from '../config'
|
|
|
11
11
|
import { resolveImport } from '../resolve/imports'
|
|
12
12
|
import { moduleExportNames, moduleExportStars } from '../resolve/scan-facts'
|
|
13
13
|
import { readText } from '../utils/fs'
|
|
14
|
+
import { hasModuleDirective } from '../utils/directive'
|
|
14
15
|
|
|
15
16
|
export const clientReferenceRuntimeFile = path.resolve(import.meta.dirname, 'reference.ts')
|
|
16
17
|
|
|
@@ -122,40 +123,7 @@ export async function clientReferenceExportNames(
|
|
|
122
123
|
* linear and allocation-free.
|
|
123
124
|
*/
|
|
124
125
|
export function hasUseClientDirective(source: string) {
|
|
125
|
-
|
|
126
|
-
const code = source.charCodeAt(index)
|
|
127
|
-
return code === 32 || (code >= 9 && code <= 13) || (code > 127 && /\s/.test(source[index]!))
|
|
128
|
-
}
|
|
129
|
-
let i = 0
|
|
130
|
-
for (;;) {
|
|
131
|
-
while (i < source.length && isSpace(i)) i += 1
|
|
132
|
-
if (source.startsWith('//', i)) {
|
|
133
|
-
const newline = source.indexOf('\n', i)
|
|
134
|
-
if (newline === -1) return false
|
|
135
|
-
i = newline + 1
|
|
136
|
-
continue
|
|
137
|
-
}
|
|
138
|
-
if (source.startsWith('/*', i)) {
|
|
139
|
-
const end = source.indexOf('*/', i + 2)
|
|
140
|
-
if (end === -1) return false
|
|
141
|
-
i = end + 2
|
|
142
|
-
continue
|
|
143
|
-
}
|
|
144
|
-
// Anything that is not a string literal ends the prologue.
|
|
145
|
-
const quote = source[i]
|
|
146
|
-
if (quote !== '"' && quote !== "'") return false
|
|
147
|
-
let end = i + 1
|
|
148
|
-
while (end < source.length) {
|
|
149
|
-
const char = source[end]!
|
|
150
|
-
if (char === quote || char === '\n' || char === '\\') break
|
|
151
|
-
end += 1
|
|
152
|
-
}
|
|
153
|
-
if (source[end] !== quote) return false
|
|
154
|
-
if (source.slice(i + 1, end) === 'use client') return true
|
|
155
|
-
i = end + 1
|
|
156
|
-
while (i < source.length && isSpace(i)) i += 1
|
|
157
|
-
if (source[i] === ';') i += 1
|
|
158
|
-
}
|
|
126
|
+
return hasModuleDirective(source, 'use client')
|
|
159
127
|
}
|
|
160
128
|
|
|
161
129
|
function isInside(root: string, file: string) {
|
|
@@ -70,6 +70,7 @@ import { serverActionId, tagServerAction } from './server-tag'
|
|
|
70
70
|
import { opensWithUseServerDirective } from './detect'
|
|
71
71
|
import { inlineActionModuleKey, isInlineActionId } from './rewrite'
|
|
72
72
|
import { reportActionErrorToUser } from '../lifecycle/error-funnel'
|
|
73
|
+
import { buildManifestFile } from '../../runtime/production'
|
|
73
74
|
|
|
74
75
|
// ---------------------------------------------------------------------------
|
|
75
76
|
// Build step: action discovery/bundling + server-reference manifest.
|
|
@@ -541,7 +542,7 @@ export async function ensureActionsRegistered(runtime: RequestRuntime): Promise<
|
|
|
541
542
|
// client-action module set (normally armed by the build): render-time form/prop
|
|
542
543
|
// tagging reads it to give module-level actions their stable wire ids.
|
|
543
544
|
async function registerManifestActions(config: ResolvedConfig): Promise<void> {
|
|
544
|
-
const manifestPath =
|
|
545
|
+
const manifestPath = buildManifestFile(config.outPath)
|
|
545
546
|
let manifest: BuildManifest
|
|
546
547
|
try {
|
|
547
548
|
manifest = JSON.parse(await readFile(manifestPath, 'utf8')) as BuildManifest
|
|
@@ -700,7 +701,7 @@ function requestWouldMiss(config: ResolvedConfig, pathname: string): boolean {
|
|
|
700
701
|
}
|
|
701
702
|
|
|
702
703
|
function servableFile(config: ResolvedConfig, pathname: string): boolean {
|
|
703
|
-
const publicRoot = path.join(config.outPath, '
|
|
704
|
+
const publicRoot = path.join(config.outPath, 'static')
|
|
704
705
|
const trimmed = pathname.replace(/^\/+|\/+$/g, '')
|
|
705
706
|
const file = trimmed ? path.join(publicRoot, trimmed) : publicRoot
|
|
706
707
|
// Never let a traversal-shaped path claim to be servable (it is not).
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
import { existsSync, readdirSync, statSync } from 'node:fs'
|
|
14
14
|
import path from 'node:path'
|
|
15
|
+
import { outCachePath } from '../../out-paths'
|
|
15
16
|
|
|
16
17
|
/** Extensions whose files also get an extension-less request key (webpack resolves both). */
|
|
17
18
|
const RESOLVABLE_EXTENSIONS = ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs', '.json']
|
|
@@ -210,7 +211,7 @@ function resolveContextDir(
|
|
|
210
211
|
const direct = path.resolve(path.dirname(file), specifier)
|
|
211
212
|
if (existsSync(direct)) return direct
|
|
212
213
|
if (paths?.outPath && paths.workspaceRoot) {
|
|
213
|
-
const cacheRoot = path.join(paths.outPath, '
|
|
214
|
+
const cacheRoot = path.join(outCachePath(paths.outPath), 'server')
|
|
214
215
|
const relative = path.relative(cacheRoot, file)
|
|
215
216
|
if (relative && !relative.startsWith('..') && !path.isAbsolute(relative)) {
|
|
216
217
|
const segments = relative.split(path.sep)
|
|
@@ -25,6 +25,7 @@ import type { Plugin } from 'esbuild'
|
|
|
25
25
|
import type { ResolvedConfig } from '../../config'
|
|
26
26
|
import { rewriteSpecifierLiterals } from '../../resolve/scan-facts'
|
|
27
27
|
import { turbopackLoaderRules, turbopackResolveAlias, type WebpackLoaderRule } from './config'
|
|
28
|
+
import { outCachePath } from '../../out-paths'
|
|
28
29
|
|
|
29
30
|
interface LoaderFn {
|
|
30
31
|
(this: LoaderContext, content: string | Buffer): unknown
|
|
@@ -293,7 +294,7 @@ function resolveLoaderRequest(root: string, context: string, request: string): P
|
|
|
293
294
|
*/
|
|
294
295
|
function originalResourcePath(resourcePath: string, config: ResolvedConfig | undefined): string {
|
|
295
296
|
if (config) {
|
|
296
|
-
const cacheRoot = path.join(config.outPath, '
|
|
297
|
+
const cacheRoot = path.join(outCachePath(config.outPath), 'server')
|
|
297
298
|
const rel = path.relative(cacheRoot, resourcePath)
|
|
298
299
|
if (rel && !rel.startsWith('..') && !path.isAbsolute(rel)) {
|
|
299
300
|
const segments = rel.split(path.sep)
|
|
@@ -451,7 +452,7 @@ async function emitAssetResourceModule(
|
|
|
451
452
|
.basename(resourcePath, path.extname(resourcePath))
|
|
452
453
|
.replace(/[^A-Za-z0-9_-]+/g, '-')
|
|
453
454
|
const relative = path.posix.join('_next', 'static', 'media', `${base}.${hash}${ext}`)
|
|
454
|
-
const target = path.join(config.outPath, '
|
|
455
|
+
const target = path.join(config.outPath, 'static', ...relative.split('/'))
|
|
455
456
|
await mkdir(path.dirname(target), { recursive: true })
|
|
456
457
|
if (!existsSync(target)) await writeFile(target, bytes)
|
|
457
458
|
const src = `/${relative}`
|
|
@@ -128,7 +128,7 @@ async function workerAssetModuleSource(config: ResolvedConfig, file: string): Pr
|
|
|
128
128
|
source = `const src = ${JSON.stringify(src)};\nexport default { src };\nexport { src };\n`
|
|
129
129
|
}
|
|
130
130
|
for (const relative of emitted) {
|
|
131
|
-
const target = path.join(config.outPath, '
|
|
131
|
+
const target = path.join(config.outPath, 'static', ...relative.split('/'))
|
|
132
132
|
await mkdir(path.dirname(target), { recursive: true })
|
|
133
133
|
if (!existsSync(target)) await copyFile(sourcePath, target)
|
|
134
134
|
}
|
|
@@ -208,7 +208,7 @@ async function bundleWorkerEntry(config: ResolvedConfig, entry: string): Promise
|
|
|
208
208
|
const hash = createHash('sha256').update(output.contents).digest('hex').slice(0, 8)
|
|
209
209
|
const base = path.basename(entry, path.extname(entry)).replace(/[^A-Za-z0-9_-]+/g, '-')
|
|
210
210
|
const relative = path.posix.join('assets', 'workers', `${base}.${hash}.js`)
|
|
211
|
-
const target = path.join(config.outPath, '
|
|
211
|
+
const target = path.join(config.outPath, 'static', ...relative.split('/'))
|
|
212
212
|
await mkdir(path.dirname(target), { recursive: true })
|
|
213
213
|
await writeFile(target, output.contents)
|
|
214
214
|
return `/${relative}`
|
|
@@ -65,7 +65,7 @@ export function inlineCssStylesheets(
|
|
|
65
65
|
): string[] | undefined {
|
|
66
66
|
if (options.dev || suppressed.getStore() === true || !inlineCssEnabled(config)) return undefined
|
|
67
67
|
const assets = options.assetNames.map(asset =>
|
|
68
|
-
readCss(`${config.outPath}/
|
|
68
|
+
readCss(`${config.outPath}/static/assets/${asset}`),
|
|
69
69
|
)
|
|
70
70
|
if (assets.some(css => css === undefined)) return undefined
|
|
71
71
|
const css = [options.prependCss, ...assets].filter(Boolean).join('\n')
|
|
@@ -130,7 +130,7 @@ function collectOutputs(config: ResolvedConfig, manifest: BuildManifest): Adapte
|
|
|
130
130
|
const prerenderedRoutes = new Set<string>()
|
|
131
131
|
|
|
132
132
|
for (const [relative, metadata] of Object.entries(manifest.staticFiles ?? {})) {
|
|
133
|
-
const filePath = path.join(config.outPath, '
|
|
133
|
+
const filePath = path.join(config.outPath, 'static', relative)
|
|
134
134
|
// The manifest also records prerenders that produced no body on disk
|
|
135
135
|
// (an empty response, `_not-found` / `_global-error`). Those are not
|
|
136
136
|
// deployable artifacts: leave them out, and leave the owning route as a
|
|
@@ -42,7 +42,7 @@ export async function emitStaticExport({ config, manifest, log }: EmitStaticExpo
|
|
|
42
42
|
// the running server - client runtime code fetches it unconditionally, and Next's own asset-404 tests
|
|
43
43
|
// probe it as "a known valid asset path". Export mode additionally snapshots a standalone `out/` tree
|
|
44
44
|
// below; the manifest files it needs are the same bytes, so write the server-served copy first.
|
|
45
|
-
await log.step('build manifest', () => writeBuildManifests(path.join(config.outPath, '
|
|
45
|
+
await log.step('build manifest', () => writeBuildManifests(path.join(config.outPath, 'static')))
|
|
46
46
|
const output = getNextConfig().output
|
|
47
47
|
if (output === 'standalone') {
|
|
48
48
|
await emitStandalone({ config, manifest, log })
|
|
@@ -74,7 +74,7 @@ async function writeExportTree(config: ResolvedConfig, manifest: BuildManifest):
|
|
|
74
74
|
* can be pointed at their new location.
|
|
75
75
|
*/
|
|
76
76
|
async function copyRuntimeAssets(config: ResolvedConfig, outDir: string): Promise<Set<string>> {
|
|
77
|
-
const assetsDir = path.join(config.outPath, '
|
|
77
|
+
const assetsDir = path.join(config.outPath, 'static', 'assets')
|
|
78
78
|
const assets = new Set<string>()
|
|
79
79
|
for (const file of await listFiles(assetsDir)) {
|
|
80
80
|
const relative = toPosixPath(path.relative(assetsDir, file))
|
|
@@ -91,7 +91,7 @@ async function copyPublicTree(
|
|
|
91
91
|
outDir: string,
|
|
92
92
|
assets: ReadonlySet<string>,
|
|
93
93
|
): Promise<void> {
|
|
94
|
-
const publicDir = path.join(config.outPath, '
|
|
94
|
+
const publicDir = path.join(config.outPath, 'static')
|
|
95
95
|
for (const file of await listFiles(publicDir)) {
|
|
96
96
|
const relative = toPosixPath(path.relative(publicDir, file))
|
|
97
97
|
if (relative.startsWith('assets/')) continue
|
|
@@ -159,7 +159,7 @@ function exportPages(config: ResolvedConfig, manifest: BuildManifest): ExportPag
|
|
|
159
159
|
if (metadata.kind !== 'page' || !relative.endsWith('.html')) continue
|
|
160
160
|
const route = metadata.routeId ? routeById.get(metadata.routeId) : undefined
|
|
161
161
|
if (route?.kind !== 'page') continue
|
|
162
|
-
const htmlFile = path.join(config.outPath, '
|
|
162
|
+
const htmlFile = path.join(config.outPath, 'static', ...relative.split('/'))
|
|
163
163
|
pages.push({
|
|
164
164
|
route,
|
|
165
165
|
htmlFile,
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
// `output: 'standalone'` emitter (COMPAT).
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// emitted `server.js` is a thin Node launcher that re-execs the real pnext server via Bun, pointed back
|
|
10
|
-
// at the original build root. The child prints the `- Local:` banner itself, which the launcher inherits
|
|
11
|
-
// straight onto its own stdout, so the harness's readiness regex fires without a proxy hop. The original
|
|
12
|
-
// build tree outlives the moved standalone folder for the duration of the test, so absolute references
|
|
13
|
-
// back into it are safe.
|
|
3
|
+
// Every pnext build writes `<outDir>/standalone/`, the self-contained server; with `output:
|
|
4
|
+
// 'standalone'` the out dir defaults to `.next` (compat/next/config-loader), so it lands where Next's
|
|
5
|
+
// does. Next's contract on top: a `server.js` that boots on PORT/HOSTNAME under `node server.js`, and
|
|
6
|
+
// the `.nft.json` traces its suites read. The e2e suites MOVE the folder to a fresh tmp dir, run
|
|
7
|
+
// `node server.js` and wait for the `- Local:` banner; `server.js` hands over to Bun, which serves the
|
|
8
|
+
// folder's own `server/entry.js`.
|
|
14
9
|
import { existsSync, readFileSync } from 'node:fs'
|
|
15
|
-
import { mkdir,
|
|
10
|
+
import { mkdir, writeFile } from 'node:fs/promises'
|
|
16
11
|
import path from 'node:path'
|
|
17
12
|
import type { ResolvedConfig } from '../../config'
|
|
18
13
|
import type { BuildManifest, RouteManifestEntry } from '../../types'
|
|
@@ -37,68 +32,38 @@ export async function emitStandalone({
|
|
|
37
32
|
}
|
|
38
33
|
|
|
39
34
|
async function writeStandalone(config: ResolvedConfig, manifest: BuildManifest): Promise<void> {
|
|
40
|
-
const standaloneDir =
|
|
41
|
-
await
|
|
42
|
-
await mkdir(standaloneDir, { recursive: true })
|
|
43
|
-
await writeServerEntry(config, standaloneDir)
|
|
35
|
+
const standaloneDir = config.outPath
|
|
36
|
+
await writeFile(path.join(standaloneDir, 'server.js'), standaloneServerSource())
|
|
44
37
|
await writeTraceFiles(config, standaloneDir)
|
|
45
38
|
await writeMiddlewareManifest(manifest, standaloneDir)
|
|
46
39
|
}
|
|
47
40
|
|
|
48
41
|
/**
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
42
|
+
* Starts `server/entry.js` under Bun on the PORT/HOSTNAME the standalone contract passes through the
|
|
43
|
+
* environment. The child's `- Local:` banner is inherited onto this process's stdout, so the harness's
|
|
44
|
+
* readiness regex fires directly. Signals are forwarded so the harness's `killApp` (SIGTERM) tears the
|
|
45
|
+
* whole tree down and lets pending after() callbacks drain.
|
|
53
46
|
*/
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
`${JSON.stringify({ name: 'pnext-standalone', version: '0.0.0', type: 'commonjs', private: true }, null, 2)}\n`,
|
|
58
|
-
)
|
|
59
|
-
await writeFile(path.join(standaloneDir, 'server.js'), standaloneServerSource(config))
|
|
60
|
-
}
|
|
47
|
+
function standaloneServerSource(): string {
|
|
48
|
+
return `// pnext standalone launcher, generated by pnext build (src/compat/export/standalone.ts).
|
|
49
|
+
import { spawn } from 'node:child_process';
|
|
61
50
|
|
|
62
|
-
|
|
63
|
-
* Boots `pnext start` under Bun against the original build root, on the
|
|
64
|
-
* PORT/HOSTNAME the standalone contract passes through the environment. The
|
|
65
|
-
* child's `- Local:` banner is inherited onto this process's stdout, so the
|
|
66
|
-
* harness's readiness regex fires directly. Signals are forwarded so the
|
|
67
|
-
* harness's `killApp` (SIGTERM) tears the whole tree down and lets pending
|
|
68
|
-
* after() callbacks drain.
|
|
69
|
-
*/
|
|
70
|
-
function standaloneServerSource(config: ResolvedConfig): string {
|
|
71
|
-
const cliPath = path.resolve(import.meta.dirname, '..', '..', 'cli', 'index.ts')
|
|
72
|
-
return `'use strict';
|
|
73
|
-
// pnext standalone launcher. Generated by pnext build; see
|
|
74
|
-
// src/compat/export/standalone.ts. Spawned as \`node server.js\` from the moved
|
|
75
|
-
// standalone directory; re-execs the real pnext server under Bun.
|
|
76
|
-
const { spawn } = require('node:child_process');
|
|
77
|
-
|
|
78
|
-
const PNEXT_CLI = ${JSON.stringify(cliPath)};
|
|
79
|
-
const PNEXT_ROOT = ${JSON.stringify(config.root)};
|
|
80
|
-
const port = String(process.env.PORT || '3000');
|
|
51
|
+
const port = Number(process.env.PORT || '3000');
|
|
81
52
|
const hostname = process.env.HOSTNAME || '0.0.0.0';
|
|
53
|
+
const entry = new URL('./server/entry.js', import.meta.url).href;
|
|
54
|
+
const boot = \`const { start } = await import(\${JSON.stringify(entry)}); await start(\${JSON.stringify({ port, hostname })});\`;
|
|
82
55
|
|
|
83
|
-
const child = spawn(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
BROWSER: 'none',
|
|
95
|
-
NODE_ENV: 'production',
|
|
96
|
-
PORT: port,
|
|
97
|
-
HOSTNAME: hostname,
|
|
98
|
-
},
|
|
99
|
-
stdio: ['ignore', 'inherit', 'inherit'],
|
|
100
|
-
}
|
|
101
|
-
);
|
|
56
|
+
const child = spawn('bun', ['--conditions=react-server', '-e', boot], {
|
|
57
|
+
env: {
|
|
58
|
+
...process.env,
|
|
59
|
+
// Suppresses \`pnext start\`'s "output: standalone" warning (Next gates the
|
|
60
|
+
// same warning on this private env being set by its standalone server).
|
|
61
|
+
__NEXT_PRIVATE_STANDALONE_CONFIG: '1',
|
|
62
|
+
BROWSER: 'none',
|
|
63
|
+
NODE_ENV: 'production',
|
|
64
|
+
},
|
|
65
|
+
stdio: ['ignore', 'inherit', 'inherit'],
|
|
66
|
+
});
|
|
102
67
|
|
|
103
68
|
child.on('error', (error) => {
|
|
104
69
|
console.error('pnext standalone: failed to start the pnext server:', error);
|
|
@@ -378,7 +378,7 @@ async function fetchUpstream(
|
|
|
378
378
|
}
|
|
379
379
|
const publicFile = await readPublicFile(
|
|
380
380
|
[
|
|
381
|
-
path.join(coreConfig.outPath, '
|
|
381
|
+
path.join(coreConfig.outPath, 'static'),
|
|
382
382
|
coreConfig.publicPath,
|
|
383
383
|
path.join(coreConfig.root, 'public'),
|
|
384
384
|
],
|
|
@@ -23,6 +23,7 @@ import { build } from '../../utils/esbuild'
|
|
|
23
23
|
import type { ResolvedConfig } from '../../config'
|
|
24
24
|
import { getNextConfig } from '../next/config-loader'
|
|
25
25
|
import { instrumentationLookupRoots } from './instrumentation'
|
|
26
|
+
import { outCachePath } from '../../out-paths'
|
|
26
27
|
|
|
27
28
|
const CLIENT_BASENAMES = [
|
|
28
29
|
'instrumentation-client.ts',
|
|
@@ -90,10 +91,10 @@ export async function buildInstrumentationClient(config: ResolvedConfig): Promis
|
|
|
90
91
|
const userFile = findInstrumentationClient(config)
|
|
91
92
|
if (!userFile) return
|
|
92
93
|
const modules = [...injectEntries(config), userFile]
|
|
93
|
-
const workDir = path.join(config.outPath, '
|
|
94
|
+
const workDir = path.join(outCachePath(config.outPath), 'instrumentation-client')
|
|
94
95
|
mkdirSync(workDir, { recursive: true })
|
|
95
96
|
const entryFile = path.join(workDir, 'entry.ts')
|
|
96
|
-
const outfile = path.join(config.outPath, '
|
|
97
|
+
const outfile = path.join(config.outPath, 'static', INSTRUMENTATION_CLIENT_ASSET)
|
|
97
98
|
mkdirSync(path.dirname(outfile), { recursive: true })
|
|
98
99
|
await Bun.write(entryFile, entrySource(modules))
|
|
99
100
|
const tsconfig = path.join(config.root, 'tsconfig.json')
|
|
@@ -116,7 +117,7 @@ let bundlePresence: boolean | undefined
|
|
|
116
117
|
|
|
117
118
|
/** Whether the built instrumentation-client bundle exists (cached). */
|
|
118
119
|
function hasInstrumentationClientBundle(config: ResolvedConfig): boolean {
|
|
119
|
-
bundlePresence ??= existsSync(path.join(config.outPath, '
|
|
120
|
+
bundlePresence ??= existsSync(path.join(config.outPath, 'static', INSTRUMENTATION_CLIENT_ASSET))
|
|
120
121
|
return bundlePresence
|
|
121
122
|
}
|
|
122
123
|
|
|
@@ -329,7 +329,7 @@ async function writeStaticMetadataArtifacts(
|
|
|
329
329
|
metadata: StaticFileMetadata | undefined,
|
|
330
330
|
): Promise<void> {
|
|
331
331
|
if (!metadata) return
|
|
332
|
-
const source = path.join(outPath, '
|
|
332
|
+
const source = path.join(outPath, 'static', relative)
|
|
333
333
|
const outputBase = path.join(root, 'server', 'app', toPosixPath(relative))
|
|
334
334
|
await mkdir(path.dirname(outputBase), { recursive: true })
|
|
335
335
|
const routeMeta = JSON.stringify(toRouteMeta(metadata))
|
|
@@ -488,6 +488,9 @@ function mapOverrides(config: NextConfigObject): NextConfigCoreOverrides {
|
|
|
488
488
|
config.output !== 'export'
|
|
489
489
|
) {
|
|
490
490
|
overrides.outDir = config.distDir
|
|
491
|
+
} else if (config.output === 'standalone') {
|
|
492
|
+
// Next's `.next/standalone`: the folder its standalone contract names.
|
|
493
|
+
overrides.outDir = '.next'
|
|
491
494
|
}
|
|
492
495
|
return overrides
|
|
493
496
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/** @jsxImportSource preact */
|
|
2
2
|
import { h, type ComponentType } from 'preact'
|
|
3
|
-
import { lazy, Suspense } from 'preact/compat'
|
|
4
3
|
import {
|
|
5
4
|
dynamic as pnextDynamic,
|
|
6
5
|
dynamicReferenceSymbol,
|
|
@@ -19,25 +18,17 @@ export default function dynamic<Props extends object = object>(
|
|
|
19
18
|
// Injected by the server compile; see rewriteDynamicCallTargets.
|
|
20
19
|
target?: DynamicTarget,
|
|
21
20
|
) {
|
|
22
|
-
if (typeof loader === 'string') return pnextDynamic(loader, options, target)
|
|
23
|
-
|
|
24
21
|
const coreDynamic = pnextDynamic(loader, options, target) as DynamicWithReference<Props>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
{ style: { display: 'contents' } },
|
|
36
|
-
!process.browser && typeof window === 'undefined' ? null : h(coreDynamic, props),
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
return h(Suspense, { fallback: Loading ? h(Loading, props) : null }, h(Lazy, props))
|
|
40
|
-
}) as DynamicWithReference<Props>
|
|
22
|
+
// Core's component server-renders and hydrates like Next, waiting for a chunk still loading.
|
|
23
|
+
if (typeof loader === 'string' || options.ssr !== false) return coreDynamic
|
|
24
|
+
|
|
25
|
+
// ssr:false renders nothing on the server; the client renders `loading`, then the component.
|
|
26
|
+
const DynamicComponent = ((props: Props) =>
|
|
27
|
+
h(
|
|
28
|
+
'pnext-dynamic',
|
|
29
|
+
{ style: { display: 'contents' } },
|
|
30
|
+
!process.browser && typeof window === 'undefined' ? null : h(coreDynamic, props),
|
|
31
|
+
)) as DynamicWithReference<Props>
|
|
41
32
|
|
|
42
33
|
DynamicComponent[dynamicReferenceSymbol] = coreDynamic[dynamicReferenceSymbol]
|
|
43
34
|
return DynamicComponent
|
|
@@ -48,7 +39,3 @@ export { dynamic }
|
|
|
48
39
|
type DynamicWithReference<Props extends object> = ComponentType<Props> & {
|
|
49
40
|
[dynamicReferenceSymbol]?: DynamicReference<Props>
|
|
50
41
|
}
|
|
51
|
-
|
|
52
|
-
function componentFromModule<Props>(module: DynamicModule<Props>) {
|
|
53
|
-
return typeof module === 'function' ? module : module.default
|
|
54
|
-
}
|
|
@@ -15,6 +15,7 @@ import { restartCacheEnabled } from '../../../dev/restart/enabled'
|
|
|
15
15
|
import { frameworkFingerprint } from '../../../runtime/fingerprint'
|
|
16
16
|
import { writeFileAtomic } from '../../../utils/fs'
|
|
17
17
|
import type { MetadataLink } from '../../../types'
|
|
18
|
+
import { outCachePath } from '../../../out-paths'
|
|
18
19
|
|
|
19
20
|
export interface PersistableFont {
|
|
20
21
|
css: string
|
|
@@ -54,7 +55,7 @@ interface FontIndex {
|
|
|
54
55
|
const indexes = new Map<string, FontIndex>()
|
|
55
56
|
|
|
56
57
|
function fontIndex(config: ResolvedConfig): FontIndex {
|
|
57
|
-
const file = path.join(config.outPath, '
|
|
58
|
+
const file = path.join(outCachePath(config.outPath), 'fonts', 'index.json')
|
|
58
59
|
const existing = indexes.get(file)
|
|
59
60
|
if (existing) return existing
|
|
60
61
|
const created: FontIndex = { file, fonts: readIndex(file), dirty: false }
|
|
@@ -805,7 +805,7 @@ async function emitFontBytes(
|
|
|
805
805
|
// Served from `/_next/static/media/` — files under the out dir's public/ map 1:1 to the URL path,
|
|
806
806
|
// which is the only place dev and build both look them up.
|
|
807
807
|
const mediaSegments = ['_next', 'static', 'media']
|
|
808
|
-
const outDir = path.join(context.config.outPath, '
|
|
808
|
+
const outDir = path.join(context.config.outPath, 'static', ...mediaSegments)
|
|
809
809
|
const file = path.join(outDir, filename)
|
|
810
810
|
const asset = {
|
|
811
811
|
ext,
|
|
@@ -122,7 +122,7 @@ async function writeImagesManifestStep(ctx: BuildStepContext): Promise<void> {
|
|
|
122
122
|
async function mirrorStaticMedia(config: ResolvedConfig): Promise<void> {
|
|
123
123
|
const { cp } = await import('node:fs/promises')
|
|
124
124
|
for (const dir of ['media', 'immutable/media']) {
|
|
125
|
-
const source = path.join(config.outPath, '
|
|
125
|
+
const source = path.join(config.outPath, 'static', '_next', 'static', dir)
|
|
126
126
|
const target = path.join(config.root, '.next', 'static', dir)
|
|
127
127
|
try {
|
|
128
128
|
await cp(source, target, { recursive: true, force: true })
|
|
@@ -42,6 +42,7 @@ export function typecheckDisabled(): boolean {
|
|
|
42
42
|
export interface TypecheckWorkerInput {
|
|
43
43
|
root: string
|
|
44
44
|
outPath: string
|
|
45
|
+
outRootPath: string
|
|
45
46
|
compat: ResolvedConfig['compat']
|
|
46
47
|
nextConfig: NextConfigObject
|
|
47
48
|
}
|
|
@@ -64,6 +65,7 @@ export async function validateTypesOffThread(config: ResolvedConfig): Promise<vo
|
|
|
64
65
|
const input: TypecheckWorkerInput = {
|
|
65
66
|
root: config.root,
|
|
66
67
|
outPath: config.outPath,
|
|
68
|
+
outRootPath: config.outRootPath,
|
|
67
69
|
compat: config.compat,
|
|
68
70
|
nextConfig: cloneable({
|
|
69
71
|
typescript: next.typescript,
|
|
@@ -210,12 +212,12 @@ function appDiagnostic(file: string | undefined, config: ResolvedConfig): boolea
|
|
|
210
212
|
if (resolved === generatedProjectPath(config)) return true
|
|
211
213
|
if (!resolved.startsWith(config.root + path.sep)) return false
|
|
212
214
|
if (resolved.includes(`${path.sep}node_modules${path.sep}`)) return false
|
|
213
|
-
if (resolved.startsWith(path.resolve(config.
|
|
215
|
+
if (resolved.startsWith(path.resolve(config.outRootPath) + path.sep)) return false
|
|
214
216
|
return true
|
|
215
217
|
}
|
|
216
218
|
|
|
217
219
|
function generatedProjectPath(config: ResolvedConfig): string {
|
|
218
|
-
return path.resolve(config.
|
|
220
|
+
return path.resolve(config.outRootPath, 'typecheck', 'tsconfig.json')
|
|
219
221
|
}
|
|
220
222
|
|
|
221
223
|
/**
|
|
@@ -292,7 +294,7 @@ async function writeTypecheckProject(
|
|
|
292
294
|
config: ResolvedConfig,
|
|
293
295
|
native: string | undefined,
|
|
294
296
|
): Promise<string> {
|
|
295
|
-
const dir = path.join(config.
|
|
297
|
+
const dir = path.join(config.outRootPath, 'typecheck')
|
|
296
298
|
await mkdir(dir, { recursive: true })
|
|
297
299
|
const reactTypes = resolveTypesDir('react', config.root)
|
|
298
300
|
const hasReactTypes = reactTypes !== undefined
|
|
@@ -420,7 +422,7 @@ async function writeTypecheckProject(
|
|
|
420
422
|
}
|
|
421
423
|
|
|
422
424
|
function preactTypeShimPath(config: ResolvedConfig): string {
|
|
423
|
-
return path.join(config.
|
|
425
|
+
return path.join(config.outRootPath, 'typecheck', 'preact-compat.d.ts')
|
|
424
426
|
}
|
|
425
427
|
|
|
426
428
|
function preactTypeShim(preact: string, react: string): string {
|