@wular/pnext 0.1.8 → 0.1.10
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-pycbtjt1.js → aliases-s49gt0bb.js} +5 -5
- package/dist/server/_chunks/{analyze-4d9e00g9.js → analyze-c45xjea8.js} +8 -8
- package/dist/server/_chunks/{boot-bhemypxz.js → boot-exjk45ry.js} +8 -8
- package/dist/server/_chunks/{build-c991dv65.js → build-m49fem3j.js} +4 -4
- package/dist/server/_chunks/{build-kh5e3x48.js → build-ntq282xh.js} +82 -40
- package/dist/server/_chunks/{build-tier-0a96kmx3.js → build-tier-byqfyz34.js} +17 -17
- package/dist/server/_chunks/{config-27rj7830.js → config-1hdw96je.js} +2 -2
- package/dist/server/_chunks/{config-0tvz03a6.js → config-m2yaayer.js} +3 -3
- package/dist/server/_chunks/{create-9rvwshsp.js → create-k089tdt7.js} +3 -3
- package/dist/server/_chunks/{dev-ex9exynt.js → dev-kwp1t8b3.js} +2 -2
- package/dist/server/_chunks/{generate-myw9hef7.js → generate-ap2zs26g.js} +3 -3
- package/dist/server/_chunks/{index-x2m17v9c.js → index-0f5t5730.js} +16 -13
- package/dist/server/_chunks/{index-xh1nbk46.js → index-1q52cw31.js} +7 -7
- package/dist/server/_chunks/{index-nf3df4jy.js → index-1tmqkr6x.js} +3 -3
- package/dist/server/_chunks/index-1xrvw3zp.js +92 -0
- package/dist/server/_chunks/{index-yrjkqtfj.js → index-4g6amwtg.js} +2 -2
- package/dist/server/_chunks/{index-11xpbfej.js → index-4hspm5ez.js} +1 -1
- package/dist/server/_chunks/{index-qcrvt6er.js → index-56jw1658.js} +2 -2
- package/dist/server/_chunks/{index-d158y67j.js → index-6w807g31.js} +12 -4
- package/dist/server/_chunks/{index-29pq0kax.js → index-72wjyacg.js} +2 -2
- package/dist/server/_chunks/{index-3e075kny.js → index-81qnfmzz.js} +1 -1
- package/dist/server/_chunks/{index-3ycf5ckv.js → index-8hy8qskn.js} +3 -3
- package/dist/server/_chunks/{index-he6n2bvp.js → index-8y2yft9b.js} +1 -1
- package/dist/server/_chunks/{index-8ct7rqy3.js → index-a4asdd4j.js} +1 -1
- package/dist/server/_chunks/{index-1pzm1hdy.js → index-cqft8ae4.js} +7 -7
- package/dist/server/_chunks/{index-9hz3s0m8.js → index-dd4tb5vy.js} +1 -1
- package/dist/server/_chunks/{index-tq3b39a5.js → index-drfxdvvh.js} +4 -4
- package/dist/server/_chunks/{index-4da76t62.js → index-e63ma63t.js} +1 -1
- package/dist/server/_chunks/{index-rgj5mx84.js → index-ed6rwv1x.js} +1 -1
- package/dist/server/_chunks/{index-dgr390q7.js → index-f76517s5.js} +23 -23
- package/dist/server/_chunks/{index-b7j671dj.js → index-fdc7wz3a.js} +1 -1
- package/dist/server/_chunks/{index-0yjv5v47.js → index-g39z5s9d.js} +3 -3
- package/dist/server/_chunks/{index-cvr4z22m.js → index-hw5k2sgj.js} +1 -1
- package/dist/server/_chunks/{index-evhd413j.js → index-jh486fye.js} +1 -1
- package/dist/server/_chunks/{index-fjv96re1.js → index-mjvq5c7e.js} +8 -8
- package/dist/server/_chunks/{index-kdhxpwyq.js → index-mph0cmh9.js} +3 -3
- package/dist/server/_chunks/{index-gkndxkxf.js → index-nxg8k7cg.js} +2 -2
- package/dist/server/_chunks/{index-jn9rbhrx.js → index-p79ck9cd.js} +4 -4
- package/dist/server/_chunks/{index-hdbwtdv2.js → index-pshjr3qm.js} +1 -1
- package/dist/server/_chunks/{index-n629dy38.js → index-r1kzsnyp.js} +4 -4
- package/dist/server/_chunks/{index-cn86z041.js → index-ra6fsg5v.js} +1 -1
- package/dist/server/_chunks/{index-38xpdxwd.js → index-tgwt3kwf.js} +4 -4
- package/dist/server/_chunks/{index-71885zaq.js → index-x3cvacmf.js} +4 -4
- package/dist/server/_chunks/{index-j681c48a.js → index-zq077xjc.js} +1 -1
- package/dist/server/_chunks/{index-rjegyfx4.js → index-zvy5134a.js} +5 -5
- package/dist/server/_chunks/{loader-5en7wpt5.js → loader-5j9bjhw7.js} +6 -6
- package/dist/server/_chunks/{modules-t92favpj.js → modules-gy48pdw3.js} +8 -8
- package/dist/server/_chunks/{pipeline-4t9q43ht.js → pipeline-m8ac90dn.js} +11 -11
- package/dist/server/_chunks/{production-385bw8df.js → production-26vqtxvg.js} +1 -1
- package/dist/server/_chunks/{proxy-gfhmktbk.js → proxy-74a1mg4v.js} +7 -7
- package/dist/server/_chunks/{proxy-config-60gprphe.js → proxy-config-7hnexa7b.js} +5 -5
- package/dist/server/_chunks/{router-xnrva921.js → router-frkywyzb.js} +4 -4
- package/dist/server/_chunks/{routes-ht868pdc.js → routes-y7de16ja.js} +7 -7
- package/dist/server/_chunks/{run-d40d63ag.js → run-q8aq4cez.js} +4 -4
- package/dist/server/_chunks/{server-2p8fgqq2.js → server-21t1fzp7.js} +19 -19
- package/dist/server/_chunks/{tsconfig-defaults-bcn34eqb.js → tsconfig-defaults-bcq068bd.js} +3 -3
- package/dist/server/_chunks/{typegen-dvtcjtaw.js → typegen-wdqj67rx.js} +10 -10
- package/dist/server/cli/index.js +11 -11
- package/dist/server/cli/start.js +5 -5
- package/dist/server/compat/next/config-headers.js +4 -4
- package/dist/server/compat/next/font/cache.js +4 -4
- package/dist/server/compat/next/font/local.js +5 -5
- package/dist/server/compat/next/font/runtime.js +5 -5
- package/dist/server/compat/next/navigation.js +4 -4
- package/dist/server/compat/next/redirects.js +4 -4
- package/dist/server/compat/next/rewrites.js +3 -3
- package/dist/server/generation.json +1 -1
- package/package.json +1 -1
- package/src/cli/adapters/vercel-warm.ts +2 -1
- package/src/cli/adapters/vercel.ts +43 -4
- package/src/cli/serve/standalone.ts +49 -17
- package/src/css/assets.ts +9 -1
- package/src/render/renderer.ts +6 -3
- package/dist/server/_chunks/index-gcmj16xy.js +0 -92
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
currentLayoutSegments,
|
|
4
4
|
currentParamsSnapshot,
|
|
5
5
|
hasLayoutSegmentScope
|
|
6
|
-
} from "../../_chunks/index-
|
|
7
|
-
import"../../_chunks/index-
|
|
8
|
-
import"../../_chunks/index-
|
|
9
|
-
import"../../_chunks/index-
|
|
6
|
+
} from "../../_chunks/index-72wjyacg.js";
|
|
7
|
+
import"../../_chunks/index-ra6fsg5v.js";
|
|
8
|
+
import"../../_chunks/index-e63ma63t.js";
|
|
9
|
+
import"../../_chunks/index-pshjr3qm.js";
|
|
10
10
|
import {
|
|
11
11
|
canonicalUrlHref
|
|
12
12
|
} from "../../_chunks/index-en7n9f7m.js";
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
loadCompatRedirects,
|
|
4
4
|
resolveCompatRedirect
|
|
5
|
-
} from "../../_chunks/index-
|
|
6
|
-
import"../../_chunks/index-
|
|
5
|
+
} from "../../_chunks/index-hw5k2sgj.js";
|
|
6
|
+
import"../../_chunks/index-8y2yft9b.js";
|
|
7
7
|
import"../../_chunks/index-6q7zvrap.js";
|
|
8
8
|
import"../../_chunks/index-79ngvam8.js";
|
|
9
9
|
import"../../_chunks/index-akkrvjn6.js";
|
|
@@ -15,9 +15,9 @@ import"../../_chunks/index-6b009mt0.js";
|
|
|
15
15
|
import"../../_chunks/index-4zzebszd.js";
|
|
16
16
|
import"../../_chunks/index-sq3kvz3g.js";
|
|
17
17
|
import"../../_chunks/index-ckkdpht5.js";
|
|
18
|
-
import"../../_chunks/index-
|
|
18
|
+
import"../../_chunks/index-x3cvacmf.js";
|
|
19
19
|
import"../../_chunks/index-bzd2ef7t.js";
|
|
20
|
-
import"../../_chunks/index-
|
|
20
|
+
import"../../_chunks/index-pshjr3qm.js";
|
|
21
21
|
import"../../_chunks/index-grta8ap3.js";
|
|
22
22
|
import"../../_chunks/index-kresp2n8.js";
|
|
23
23
|
import"../../_chunks/index-e3a6yx84.js";
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
resolveCompatRewrite,
|
|
9
9
|
splitDestination,
|
|
10
10
|
substitute
|
|
11
|
-
} from "../../_chunks/index-
|
|
11
|
+
} from "../../_chunks/index-8y2yft9b.js";
|
|
12
12
|
import"../../_chunks/index-6q7zvrap.js";
|
|
13
13
|
import"../../_chunks/index-79ngvam8.js";
|
|
14
14
|
import"../../_chunks/index-akkrvjn6.js";
|
|
@@ -20,9 +20,9 @@ import"../../_chunks/index-6b009mt0.js";
|
|
|
20
20
|
import"../../_chunks/index-4zzebszd.js";
|
|
21
21
|
import"../../_chunks/index-sq3kvz3g.js";
|
|
22
22
|
import"../../_chunks/index-ckkdpht5.js";
|
|
23
|
-
import"../../_chunks/index-
|
|
23
|
+
import"../../_chunks/index-x3cvacmf.js";
|
|
24
24
|
import"../../_chunks/index-bzd2ef7t.js";
|
|
25
|
-
import"../../_chunks/index-
|
|
25
|
+
import"../../_chunks/index-pshjr3qm.js";
|
|
26
26
|
import"../../_chunks/index-grta8ap3.js";
|
|
27
27
|
import"../../_chunks/index-kresp2n8.js";
|
|
28
28
|
import"../../_chunks/index-e3a6yx84.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"0.1.
|
|
1
|
+
{"version":"0.1.10","fingerprint":"db18aac8a57bc886","source":["src/api/cache.ts","src/api/client-navigation.ts","src/api/dynamic.tsx","src/api/link.tsx","src/api/navigation.ts","src/api/server.ts","src/api/suspense.ts","src/client/router/events.ts","src/client/router/history.ts","src/client/router/hub.ts","src/client/router/index.ts","src/client/router/page-slot.ts","src/client/router/policies.ts","src/client/router/runtime.ts","src/index.ts","src/internal.ts","src/request/cache.ts","src/routing/href.ts","src/utils/decode.ts"]}
|
package/package.json
CHANGED
|
@@ -614,7 +614,8 @@ async function importClientModules(
|
|
|
614
614
|
) {
|
|
615
615
|
if (!getCompatModeExtensions().reactEnabled(config)) return
|
|
616
616
|
for (const file of clientFiles) {
|
|
617
|
-
|
|
617
|
+
// A package's client modules serve from the linked dependency graph; a vendor href is dev-only.
|
|
618
|
+
if (skip.has(file) || file.includes(`${path.sep}node_modules${path.sep}`)) continue
|
|
618
619
|
const href = await devClientModuleHref(config, file, 'build')
|
|
619
620
|
report(file, fileURLToPath(href))
|
|
620
621
|
try {
|
|
@@ -74,6 +74,16 @@ export async function writeVercelOutput(
|
|
|
74
74
|
),
|
|
75
75
|
)
|
|
76
76
|
const overrides = await staticOverrides(staticPath, staticFiles)
|
|
77
|
+
const proxy = await proxyRoutes(config)
|
|
78
|
+
await log.step('drop public files from the function', () =>
|
|
79
|
+
dropPublicFiles(
|
|
80
|
+
config.publicPath,
|
|
81
|
+
path.join(functionPath, 'static'),
|
|
82
|
+
staticFiles,
|
|
83
|
+
proxy.map(route => new RegExp(route.src)),
|
|
84
|
+
config.basePath,
|
|
85
|
+
),
|
|
86
|
+
)
|
|
77
87
|
|
|
78
88
|
const routes: NonNullable<VercelConfig['routes']> = [
|
|
79
89
|
// next-compat documents reference the build output under Next's static path (assetPathname),
|
|
@@ -85,7 +95,7 @@ export async function writeVercelOutput(
|
|
|
85
95
|
...(await immutableAssetRoutes(staticPath, manifest.publicAssets)),
|
|
86
96
|
// Proxy-matched paths go to the server function before the CDN filesystem
|
|
87
97
|
// check — `pnext start` runs the proxy ahead of static files too.
|
|
88
|
-
...
|
|
98
|
+
...proxy,
|
|
89
99
|
...staticHeaderRoutes(staticFiles),
|
|
90
100
|
{ handle: 'filesystem' },
|
|
91
101
|
{ src: '^/.*$', dest: `/${SERVER_FUNCTION}` },
|
|
@@ -448,6 +458,7 @@ async function staticOverrides(
|
|
|
448
458
|
}
|
|
449
459
|
|
|
450
460
|
// `important` lets route headers win over the CDN's own static-file cache-control, as Next's builder does.
|
|
461
|
+
// Vercel anchors every `src` at both ends, so a prefix must match the rest of the path.
|
|
451
462
|
async function immutableAssetRoutes(publicDir: string, publicAssets: string[] = []) {
|
|
452
463
|
const app = new Set(publicAssets)
|
|
453
464
|
const built =
|
|
@@ -457,7 +468,7 @@ async function immutableAssetRoutes(publicDir: string, publicAssets: string[] =
|
|
|
457
468
|
.filter(relative => !app.has(relative) && immutableAssetPath(relative))
|
|
458
469
|
: []
|
|
459
470
|
const patterns = immutableAssetPatterns(built, publicAssets)
|
|
460
|
-
return routeSources(patterns, source => `^/(?:${source})
|
|
471
|
+
return routeSources(patterns, source => `^/(?:${source})$`).map(src => ({
|
|
461
472
|
src,
|
|
462
473
|
headers: { 'cache-control': immutableCacheControl },
|
|
463
474
|
continue: true,
|
|
@@ -472,12 +483,14 @@ async function immutableAssetRoutes(publicDir: string, publicAssets: string[] =
|
|
|
472
483
|
function immutableAssetPatterns(built: string[], publicAssets: string[]) {
|
|
473
484
|
const appDirs = new Set(publicAssets.flatMap(ancestorDirs))
|
|
474
485
|
const prefixes = [...new Set(immutableAssetPrefixes())]
|
|
475
|
-
const patterns = prefixes
|
|
486
|
+
const patterns = prefixes
|
|
487
|
+
.filter(prefix => !appDirs.has(prefix))
|
|
488
|
+
.map(prefix => `${escapeRegex(prefix)}.+`)
|
|
476
489
|
for (const relative of built) {
|
|
477
490
|
const prefix = prefixes.find(prefix => relative.startsWith(prefix))
|
|
478
491
|
if (!prefix || !appDirs.has(prefix)) continue
|
|
479
492
|
const dir = ancestorDirs(relative).find(dir => dir.length > prefix.length && !appDirs.has(dir))
|
|
480
|
-
patterns.push(dir ? escapeRegex(requestPath(dir)) :
|
|
493
|
+
patterns.push(dir ? `${escapeRegex(requestPath(dir))}.+` : escapeRegex(requestPath(relative)))
|
|
481
494
|
}
|
|
482
495
|
return [...new Set(patterns)]
|
|
483
496
|
}
|
|
@@ -502,6 +515,32 @@ const functionOnlyHeaders = new Set([
|
|
|
502
515
|
'set-cookie',
|
|
503
516
|
])
|
|
504
517
|
|
|
518
|
+
/**
|
|
519
|
+
* The CDN answers the app's `public/` files, so the function drops them: all but pages, files the CDN
|
|
520
|
+
* cannot serve, and paths a proxy route or an encoded name sends to it. Build assets stay: a render
|
|
521
|
+
* reads them (font CSS, inlined CSS).
|
|
522
|
+
*/
|
|
523
|
+
async function dropPublicFiles(
|
|
524
|
+
publicDir: string,
|
|
525
|
+
dir: string,
|
|
526
|
+
staticFiles: Record<string, StaticFileMetadata>,
|
|
527
|
+
proxied: RegExp[],
|
|
528
|
+
basePath: string,
|
|
529
|
+
) {
|
|
530
|
+
const publicFiles = existsSync(publicDir) ? await listFiles(publicDir) : []
|
|
531
|
+
const dropped = publicFiles
|
|
532
|
+
.map(source => toPosixPath(path.relative(publicDir, source)))
|
|
533
|
+
.filter(relative => {
|
|
534
|
+
const metadata = staticFiles[relative]
|
|
535
|
+
if (relative.endsWith('.html') || (metadata && !canServeStaticOnVercel(metadata)))
|
|
536
|
+
return false
|
|
537
|
+
if (requestPath(relative) !== relative) return false
|
|
538
|
+
const paths = [`/${relative}`, `${basePath}/${relative}`]
|
|
539
|
+
return !proxied.some(src => paths.some(pathname => src.test(pathname)))
|
|
540
|
+
})
|
|
541
|
+
await Promise.all(dropped.map(relative => rm(path.join(dir, relative), { force: true })))
|
|
542
|
+
}
|
|
543
|
+
|
|
505
544
|
function canServeStaticOnVercel(metadata: StaticFileMetadata) {
|
|
506
545
|
if (metadata.status !== 200) return false
|
|
507
546
|
const headers = routeHeaders(metadata)
|
|
@@ -13,7 +13,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url'
|
|
|
13
13
|
import { frameworkRuntimeSpecifiers, type ResolvedConfig } from '../../config'
|
|
14
14
|
import { frameworkFingerprint } from '../../runtime/fingerprint'
|
|
15
15
|
import { cacheRoot, compiledSourceGraph, flushDevModuleCaches } from '../../runtime/module-cache'
|
|
16
|
-
import { PREBUNDLE_STAMP,
|
|
16
|
+
import { PREBUNDLE_STAMP, readPrebundleStamp } from '../../runtime/prebundle'
|
|
17
17
|
import {
|
|
18
18
|
buildIndexFile,
|
|
19
19
|
type BuildIndex,
|
|
@@ -40,9 +40,15 @@ const buildOnlyModule = /^(?:build|modules|loader|compile|esbuild|dev|run|typege
|
|
|
40
40
|
const builtins = new Set(builtinModules)
|
|
41
41
|
const scriptFile = /\.(?:[cm]?[jt]sx?)$/
|
|
42
42
|
|
|
43
|
+
let prebundled: boolean | undefined
|
|
44
|
+
/** Whether a release serves from the framework's prebundle: one matches this source. */
|
|
45
|
+
function servesPrebundle() {
|
|
46
|
+
return (prebundled ??= readPrebundleStamp(frameworkRoot, frameworkFingerprint()) !== undefined)
|
|
47
|
+
}
|
|
48
|
+
|
|
43
49
|
/** The framework module a release serves from: its prebundle when one matches this source. */
|
|
44
50
|
function frameworkStartEntry() {
|
|
45
|
-
return
|
|
51
|
+
return servesPrebundle()
|
|
46
52
|
? path.join(frameworkRoot, 'dist', 'server', 'cli', 'start.js')
|
|
47
53
|
: path.join(frameworkRoot, 'src', 'cli', 'start.ts')
|
|
48
54
|
}
|
|
@@ -299,7 +305,11 @@ function createTracer(config: TraceConfig, from?: TraceSnapshot, onReady?: (dest
|
|
|
299
305
|
release && !isInside(outPath, target) && !isInside(cache, target) && !shipped(target)
|
|
300
306
|
// An app source named by URL is its identity: it resolves to the app root, never read.
|
|
301
307
|
if (appFile && scriptFile.test(target)) continue
|
|
302
|
-
|
|
308
|
+
const stat = statSync(target, { throwIfNoEntry: false })
|
|
309
|
+
// A package directory it reads by URL (migrations, data) ships whole.
|
|
310
|
+
if (stat?.isDirectory() && !release && packageDataDir(target, file))
|
|
311
|
+
for (const asset of dataFiles(target)) setFile(trace, place(asset), asset)
|
|
312
|
+
if (!stat?.isFile()) continue
|
|
303
313
|
// A file it reads by URL (a font, data) ships, under the app's own path.
|
|
304
314
|
const at = appFile
|
|
305
315
|
? toPosixPath(
|
|
@@ -448,15 +458,8 @@ function createPlacer(outPath: string, cache: string, claims = new Map<string, s
|
|
|
448
458
|
const dir = packageDir(frameworkRoot, frameworkPackage.name)
|
|
449
459
|
return `${dir}/${toPosixPath(path.relative(frameworkRoot, file))}`
|
|
450
460
|
}
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
if (at !== -1) {
|
|
454
|
-
const rest = posix.slice(at + '/node_modules/'.length).split('/')
|
|
455
|
-
const length = rest[0]!.startsWith('@') ? 2 : 1
|
|
456
|
-
const name = rest.slice(0, length).join('/')
|
|
457
|
-
const root = `${posix.slice(0, at)}/node_modules/${name}`
|
|
458
|
-
return [packageDir(root, name), ...rest.slice(length)].join('/')
|
|
459
|
-
}
|
|
461
|
+
const owner = installedPackage(file)
|
|
462
|
+
if (owner) return [packageDir(owner.root, owner.name), ...owner.rest].join('/')
|
|
460
463
|
// Workspace source reached through a link: it ships under its package name.
|
|
461
464
|
const root = packageRoot(path.dirname(file))
|
|
462
465
|
const name = root && readPackageName(root)
|
|
@@ -498,6 +501,17 @@ function addTree(root: string, dest: string, trace: Trace) {
|
|
|
498
501
|
visit(root, new Set())
|
|
499
502
|
}
|
|
500
503
|
|
|
504
|
+
/** The installed package holding `file`: its `node_modules/<name>` dir, name, and path inside. */
|
|
505
|
+
function installedPackage(file: string) {
|
|
506
|
+
const posix = toPosixPath(file)
|
|
507
|
+
const at = posix.lastIndexOf('/node_modules/')
|
|
508
|
+
if (at === -1) return undefined
|
|
509
|
+
const rest = posix.slice(at + '/node_modules/'.length).split('/')
|
|
510
|
+
const length = rest[0]!.startsWith('@') ? 2 : 1
|
|
511
|
+
const name = rest.slice(0, length).join('/')
|
|
512
|
+
return { root: `${posix.slice(0, at)}/node_modules/${name}`, name, rest: rest.slice(length) }
|
|
513
|
+
}
|
|
514
|
+
|
|
501
515
|
function installed(file: string) {
|
|
502
516
|
return toPosixPath(file).includes('/node_modules/')
|
|
503
517
|
}
|
|
@@ -572,11 +586,13 @@ function resolveEdge(specifier: string, from: string, require = false) {
|
|
|
572
586
|
return target
|
|
573
587
|
}
|
|
574
588
|
|
|
575
|
-
/** The prebundled module a framework source file is served by, when
|
|
589
|
+
/** The prebundled module a framework source file is served by, when the release serves the prebundle. */
|
|
576
590
|
function frameworkCounterparts(file: string) {
|
|
577
|
-
const
|
|
578
|
-
if (
|
|
579
|
-
|
|
591
|
+
const src = path.join(frameworkRoot, 'src')
|
|
592
|
+
if (!servesPrebundle() || !isInside(src, file)) return []
|
|
593
|
+
const relative = path.relative(src, file).replace(/\.tsx?$/, '.js')
|
|
594
|
+
const counterpart = path.join(frameworkRoot, 'dist', 'server', relative)
|
|
595
|
+
return existsSync(counterpart) ? [counterpart, path.join(frameworkRoot, PREBUNDLE_STAMP)] : []
|
|
580
596
|
}
|
|
581
597
|
|
|
582
598
|
/** `_chunks/name-<hash>.js` chunk or `name.ts` module -> `name`. */
|
|
@@ -616,6 +632,22 @@ function addPackageFiles(file: string, trace: Trace, place: (file: string) => st
|
|
|
616
632
|
}
|
|
617
633
|
}
|
|
618
634
|
|
|
635
|
+
/** Whether `dir` is data of `from`'s package: inside it, not the module's own dir or above. */
|
|
636
|
+
function packageDataDir(dir: string, from: string) {
|
|
637
|
+
const root = installedPackage(from)?.root ?? packageRoot(path.dirname(from))
|
|
638
|
+
if (!root || !isInside(root, dir) || isInside(dir, path.dirname(from))) return false
|
|
639
|
+
return !path.relative(root, dir).split(path.sep).includes('node_modules')
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/** Every file under `dir`, nested packages aside. */
|
|
643
|
+
function dataFiles(dir: string): string[] {
|
|
644
|
+
return readdirSync(dir, { withFileTypes: true }).flatMap(entry => {
|
|
645
|
+
const file = path.join(dir, entry.name)
|
|
646
|
+
if (entry.isDirectory()) return entry.name === 'node_modules' ? [] : dataFiles(file)
|
|
647
|
+
return entry.isFile() ? [file] : []
|
|
648
|
+
})
|
|
649
|
+
}
|
|
650
|
+
|
|
619
651
|
function packageRoot(dir: string): string | undefined {
|
|
620
652
|
for (; dir !== path.dirname(dir); dir = path.dirname(dir)) {
|
|
621
653
|
if (existsSync(path.join(dir, 'package.json'))) return dir
|
|
@@ -655,7 +687,7 @@ function rewriteSpecifiers(file: string, source: string, edits: Map<string, stri
|
|
|
655
687
|
function urlTarget(specifier: string, from: string) {
|
|
656
688
|
try {
|
|
657
689
|
const url = new URL(specifier, pathToFileURL(from))
|
|
658
|
-
return url.protocol === 'file:' ? fileURLToPath(url) : undefined
|
|
690
|
+
return url.protocol === 'file:' ? path.resolve(fileURLToPath(url)) : undefined
|
|
659
691
|
} catch {
|
|
660
692
|
return undefined
|
|
661
693
|
}
|
package/src/css/assets.ts
CHANGED
|
@@ -126,11 +126,19 @@ export async function emitFontCssStylesheet(
|
|
|
126
126
|
: `${routeId}.css`
|
|
127
127
|
const name = hashedAssetName(logicalName, contents)
|
|
128
128
|
const file = path.join(outDir, name)
|
|
129
|
-
if (
|
|
129
|
+
if (existsSync(file) && (await readFile(file, 'utf8')) === contents) return name
|
|
130
|
+
try {
|
|
130
131
|
await writeFile(file, contents)
|
|
132
|
+
} catch (error) {
|
|
133
|
+
// A read-only deployment cannot add the sheet; the render inlines the font rules instead.
|
|
134
|
+
if (options.dev || !readOnlyErrors.has((error as NodeJS.ErrnoException).code ?? '')) throw error
|
|
135
|
+
return undefined
|
|
136
|
+
}
|
|
131
137
|
return name
|
|
132
138
|
}
|
|
133
139
|
|
|
140
|
+
const readOnlyErrors = new Set(['EROFS', 'EACCES', 'EPERM'])
|
|
141
|
+
|
|
134
142
|
// Prepend the configured assetPrefix (a CDN origin or path) to an app-absolute
|
|
135
143
|
// asset URL. Link hrefs use basePath instead and must NOT go through here.
|
|
136
144
|
export function withAssetPrefix(
|
package/src/render/renderer.ts
CHANGED
|
@@ -3987,14 +3987,17 @@ async function renderTreeInFrame(
|
|
|
3987
3987
|
...(nonce ? { nonce } : {}),
|
|
3988
3988
|
}),
|
|
3989
3989
|
)
|
|
3990
|
+
let fontStyle = ''
|
|
3990
3991
|
if (!inlineStylesheets && fonts.css) {
|
|
3991
3992
|
const fontAsset = await profileRenderStep(profile, 'font stylesheet', () =>
|
|
3992
3993
|
emitFontCssStylesheet(options.config, options.route.id, fonts.css, stylesheetAssets[0], {
|
|
3993
3994
|
dev: Boolean(options.dev),
|
|
3994
3995
|
}),
|
|
3995
3996
|
)
|
|
3996
|
-
const fontHref = assetHref(options.config, fontAsset)
|
|
3997
|
-
if (
|
|
3997
|
+
const fontHref = fontAsset && assetHref(options.config, fontAsset)
|
|
3998
|
+
if (!fontHref)
|
|
3999
|
+
fontStyle = `<style${nonce ? ` nonce="${escapeHtml(nonce)}"` : ''}>${fonts.css}</style>`
|
|
4000
|
+
else if (globalStylesheet) globalStylesheet = fontHref
|
|
3998
4001
|
else if (Array.isArray(routeStylesheet))
|
|
3999
4002
|
routeStylesheet = [fontHref, ...routeStylesheet.slice(1)]
|
|
4000
4003
|
else routeStylesheet = fontHref
|
|
@@ -4039,7 +4042,7 @@ async function renderTreeInFrame(
|
|
|
4039
4042
|
: ''
|
|
4040
4043
|
// Inlined CSS is a stylesheet, not a script: it belongs at the stylesheet slot so the cascade
|
|
4041
4044
|
// (and the emitted order) matches the linked path.
|
|
4042
|
-
const headStyles = inlineStylesheets
|
|
4045
|
+
const headStyles = [fontStyle, ...(inlineStylesheets ?? [])].filter(Boolean).join('\n')
|
|
4043
4046
|
const headScripts = profileRenderSyncStep(profile, 'head scripts', () =>
|
|
4044
4047
|
[
|
|
4045
4048
|
renderCollectedHeadScripts(),
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
import { join as __pnextJoin } from "node:path";
|
|
3
|
-
const __PNEXT_PACKAGE_ROOT__ = __pnextJoin(import.meta.dirname, "../../..");
|
|
4
|
-
// src/runtime/fingerprint.ts
|
|
5
|
-
import { createHash } from "crypto";
|
|
6
|
-
import { mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
7
|
-
import path from "path";
|
|
8
|
-
import { fileURLToPath } from "url";
|
|
9
|
-
var prebundleFingerprint = typeof { version: "0.1.8", fingerprint: "64aaa993cbaa58df", entries: ["cli/index", "cli/start", "client/reference", "api/client-cache", "compat/next/canonical-url", "compat/next/link-transform", "compat/next/client-navigation", "compat/next/og", "compat/next/link", "compat/next/usage", "compat/next/client-script", "compat/next/headers", "compat/next/custom-server", "compat/next/legacy-image", "compat/next/router", "compat/next/navigation", "compat/next/dist/server/web/spec-extension/unstable-no-store", "compat/next/dist/server/web/spec-extension/unstable-cache", "compat/next/dist/server/web/spec-extension/revalidate", "compat/next/dist/client/components/app-router-headers", "compat/next/web-vitals", "compat/next/root-params", "compat/next/route-state", "compat/next/server-only", "compat/next/client-server", "compat/next/legacy-request-apis", "compat/next/redirects", "compat/next/resource-hints", "compat/next/svgr", "compat/next/client-only", "compat/next/image/props", "compat/next/image/optimizer", "compat/next/image/validate", "compat/next/image/shared", "compat/next/image/patterns", "compat/next/image/config", "compat/next/image/client", "compat/next/image/static-metadata", "compat/next/user-agent", "compat/next/client-cache", "compat/next/head", "compat/next/dynamic", "compat/next/telemetry", "compat/next/offline", "compat/next/cache", "compat/next/constants", "compat/next/error", "compat/next/script", "compat/next/index", "compat/next/font/shared", "compat/next/font/runtime", "compat/next/font/google", "compat/next/font/cache", "compat/next/font/runtime-client", "compat/next/font/local", "compat/next/font/index", "compat/next/config-loader", "compat/next/config", "compat/next/image", "compat/next/server", "compat/next/rewrites", "compat/next/preferred-region", "compat/next/config-headers", "compat/next/form", "compat/react/dom", "compat/react/hooks-extra", "compat/react/react-server", "compat/react/dom-client", "compat/react/style-values", "compat/react/compiler-runtime", "compat/react/router-shim", "compat/react/dom-server", "compat/react/dom-react-server", "compat/react/server-component-use", "compat/react/action-state", "compat/react/client", "compat/react/client-lite", "compat/react/server-inserted-html", "compat/react/parity", "compat/react/preact", "compat/react/use", "compat/react/view-transition", "compat/react/internals", "compat/react/server"] } === "object" ? { version: "0.1.8", fingerprint: "64aaa993cbaa58df", entries: ["cli/index", "cli/start", "client/reference", "api/client-cache", "compat/next/canonical-url", "compat/next/link-transform", "compat/next/client-navigation", "compat/next/og", "compat/next/link", "compat/next/usage", "compat/next/client-script", "compat/next/headers", "compat/next/custom-server", "compat/next/legacy-image", "compat/next/router", "compat/next/navigation", "compat/next/dist/server/web/spec-extension/unstable-no-store", "compat/next/dist/server/web/spec-extension/unstable-cache", "compat/next/dist/server/web/spec-extension/revalidate", "compat/next/dist/client/components/app-router-headers", "compat/next/web-vitals", "compat/next/root-params", "compat/next/route-state", "compat/next/server-only", "compat/next/client-server", "compat/next/legacy-request-apis", "compat/next/redirects", "compat/next/resource-hints", "compat/next/svgr", "compat/next/client-only", "compat/next/image/props", "compat/next/image/optimizer", "compat/next/image/validate", "compat/next/image/shared", "compat/next/image/patterns", "compat/next/image/config", "compat/next/image/client", "compat/next/image/static-metadata", "compat/next/user-agent", "compat/next/client-cache", "compat/next/head", "compat/next/dynamic", "compat/next/telemetry", "compat/next/offline", "compat/next/cache", "compat/next/constants", "compat/next/error", "compat/next/script", "compat/next/index", "compat/next/font/shared", "compat/next/font/runtime", "compat/next/font/google", "compat/next/font/cache", "compat/next/font/runtime-client", "compat/next/font/local", "compat/next/font/index", "compat/next/config-loader", "compat/next/config", "compat/next/image", "compat/next/server", "compat/next/rewrites", "compat/next/preferred-region", "compat/next/config-headers", "compat/next/form", "compat/react/dom", "compat/react/hooks-extra", "compat/react/react-server", "compat/react/dom-client", "compat/react/style-values", "compat/react/compiler-runtime", "compat/react/router-shim", "compat/react/dom-server", "compat/react/dom-react-server", "compat/react/server-component-use", "compat/react/action-state", "compat/react/client", "compat/react/client-lite", "compat/react/server-inserted-html", "compat/react/parity", "compat/react/preact", "compat/react/use", "compat/react/view-transition", "compat/react/internals", "compat/react/server"] }.fingerprint : undefined;
|
|
10
|
-
var SOURCE_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".cjs", ".mjs"]);
|
|
11
|
-
var DECLARATION = /\.d\.[cm]?ts$/;
|
|
12
|
-
var frameworkSrc = fileURLToPath(new URL("..", Bun.pathToFileURL(__PNEXT_PACKAGE_ROOT__ + "/src/runtime/fingerprint.ts").href));
|
|
13
|
-
function sourceFiles(dir, found = []) {
|
|
14
|
-
let entries;
|
|
15
|
-
try {
|
|
16
|
-
entries = readdirSync(dir, { withFileTypes: true });
|
|
17
|
-
} catch {
|
|
18
|
-
return found;
|
|
19
|
-
}
|
|
20
|
-
for (const entry of entries.sort((a, b) => a.name < b.name ? -1 : 1)) {
|
|
21
|
-
const full = path.join(dir, entry.name);
|
|
22
|
-
if (entry.isDirectory())
|
|
23
|
-
sourceFiles(full, found);
|
|
24
|
-
else if (SOURCE_EXTENSIONS.has(path.extname(entry.name)) && !DECLARATION.test(entry.name))
|
|
25
|
-
found.push(full);
|
|
26
|
-
}
|
|
27
|
-
return found;
|
|
28
|
-
}
|
|
29
|
-
function contentFingerprint(files, dir) {
|
|
30
|
-
const hash = createHash("sha256");
|
|
31
|
-
for (const file of files) {
|
|
32
|
-
hash.update(path.relative(dir, file));
|
|
33
|
-
try {
|
|
34
|
-
hash.update(Bun.hash(readFileSync(file)).toString(36));
|
|
35
|
-
} catch {}
|
|
36
|
-
hash.update("\x00");
|
|
37
|
-
}
|
|
38
|
-
return hash.digest("hex").slice(0, 16);
|
|
39
|
-
}
|
|
40
|
-
var RECORD_VERSION = 1;
|
|
41
|
-
function statSignature(files, dir) {
|
|
42
|
-
const hash = createHash("sha256");
|
|
43
|
-
for (const file of files) {
|
|
44
|
-
const stats = statSync(file, { throwIfNoEntry: false });
|
|
45
|
-
hash.update(`${path.relative(dir, file)}:${stats?.size ?? -1}:${stats?.mtimeMs ?? -1}\x00`);
|
|
46
|
-
}
|
|
47
|
-
return hash.digest("hex").slice(0, 16);
|
|
48
|
-
}
|
|
49
|
-
function recordFile(dir) {
|
|
50
|
-
return path.join(dir, "framework.json");
|
|
51
|
-
}
|
|
52
|
-
function readRecord(dir) {
|
|
53
|
-
try {
|
|
54
|
-
const parsed = JSON.parse(readFileSync(recordFile(dir), "utf8"));
|
|
55
|
-
return parsed.version === RECORD_VERSION && parsed.stats && parsed.fingerprint ? parsed : undefined;
|
|
56
|
-
} catch {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function writeRecord(dir, record) {
|
|
61
|
-
try {
|
|
62
|
-
mkdirSync(dir, { recursive: true });
|
|
63
|
-
writeFileSync(recordFile(dir), JSON.stringify(record));
|
|
64
|
-
} catch {}
|
|
65
|
-
}
|
|
66
|
-
var fingerprint;
|
|
67
|
-
var fingerprintStats;
|
|
68
|
-
var scanned = false;
|
|
69
|
-
var recorded = new Set;
|
|
70
|
-
function frameworkFingerprint(recordDir) {
|
|
71
|
-
const pinned = process.env.PNEXT_FRAMEWORK_FINGERPRINT ?? prebundleFingerprint;
|
|
72
|
-
if (pinned)
|
|
73
|
-
return pinned;
|
|
74
|
-
if (fingerprint !== undefined && (!recordDir || recorded.has(recordDir)))
|
|
75
|
-
return fingerprint;
|
|
76
|
-
const previous = recordDir ? readRecord(recordDir) : undefined;
|
|
77
|
-
if (!scanned || fingerprint === undefined || fingerprintStats === undefined) {
|
|
78
|
-
const files = sourceFiles(frameworkSrc);
|
|
79
|
-
fingerprintStats = statSignature(files, frameworkSrc);
|
|
80
|
-
const recordedFingerprint = previous?.stats === fingerprintStats ? previous.fingerprint : undefined;
|
|
81
|
-
scanned = recordedFingerprint === undefined;
|
|
82
|
-
fingerprint = recordedFingerprint ?? contentFingerprint(files, frameworkSrc);
|
|
83
|
-
}
|
|
84
|
-
if (recordDir) {
|
|
85
|
-
recorded.add(recordDir);
|
|
86
|
-
if (previous?.stats !== fingerprintStats)
|
|
87
|
-
writeRecord(recordDir, { version: RECORD_VERSION, stats: fingerprintStats, fingerprint });
|
|
88
|
-
}
|
|
89
|
-
return fingerprint;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
export { frameworkFingerprint };
|