@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/runtime/loader.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* imports them; this module never imports from `./vendor-build`.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { hasModuleDirective } from '../utils/directive'
|
|
9
10
|
import { createHash } from 'node:crypto'
|
|
10
11
|
import { createRequire } from 'node:module'
|
|
11
12
|
import { existsSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs'
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
pnextAliases,
|
|
34
35
|
type CompatAliasTarget,
|
|
35
36
|
type ResolvedConfig,
|
|
37
|
+
outCachePath,
|
|
36
38
|
} from '../config'
|
|
37
39
|
import {
|
|
38
40
|
rewriteDynamicCallTargets,
|
|
@@ -175,7 +177,7 @@ export function registerServerRuntime(config: ResolvedConfig, sourceFiles: strin
|
|
|
175
177
|
...rootPaths(config.root),
|
|
176
178
|
...rootPaths(config.appPath),
|
|
177
179
|
// A release build evaluates its compiled artifacts as the release will: natively.
|
|
178
|
-
...(isReleaseCompile() ? [] : rootPaths(path.join(config.outPath, '
|
|
180
|
+
...(isReleaseCompile() ? [] : rootPaths(path.join(outCachePath(config.outPath), 'server'))),
|
|
179
181
|
// The pnext src root, so the framework's own source transforms too.
|
|
180
182
|
...rootPaths(path.join(import.meta.dirname, '..')),
|
|
181
183
|
...sourceRoots.flatMap(rootPaths),
|
|
@@ -380,7 +382,7 @@ export function nodeModuleSourceLoadsAsIs(source: string) {
|
|
|
380
382
|
/** The relative specifiers of a file that loads as-is, or undefined when it needs the bundle. */
|
|
381
383
|
function nodeModuleRelativeImports(source: string) {
|
|
382
384
|
if (serverDefineOptions().define || source.includes('use cache')) return undefined
|
|
383
|
-
if (
|
|
385
|
+
if (hasModuleDirective(source, 'use client') || hasModuleDirective(source, 'use server')) {
|
|
384
386
|
return undefined
|
|
385
387
|
}
|
|
386
388
|
try {
|
|
@@ -1140,7 +1142,7 @@ async function staticImageModuleSource(config: ResolvedConfig | undefined, file:
|
|
|
1140
1142
|
const source = compat ?? coreStaticAssetModule(sourcePath, bytes, emit)
|
|
1141
1143
|
if (config) {
|
|
1142
1144
|
for (const asset of emitted) {
|
|
1143
|
-
const target = path.join(config.outPath, '
|
|
1145
|
+
const target = path.join(config.outPath, 'static', ...asset.relative.split('/'))
|
|
1144
1146
|
await mkdir(path.dirname(target), { recursive: true })
|
|
1145
1147
|
if (!existsSync(target)) await Bun.write(target, asset.bytes)
|
|
1146
1148
|
}
|
|
@@ -17,6 +17,7 @@ import { fileURLToPath } from 'node:url'
|
|
|
17
17
|
import type { ResolvedConfig } from '../config'
|
|
18
18
|
import { writeFileAtomic } from '../utils/fs'
|
|
19
19
|
import { traceEnabled } from '../utils/trace-flags'
|
|
20
|
+
import { outCachePath } from '../out-paths'
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Kill switch for the request-head trims: the naming walk's synchronous source
|
|
@@ -205,7 +206,7 @@ export function devModuleCache(
|
|
|
205
206
|
}
|
|
206
207
|
|
|
207
208
|
export function cacheRoot(outPath: string) {
|
|
208
|
-
return path.join(outPath, '
|
|
209
|
+
return path.join(outCachePath(outPath), 'server')
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
function createDevModuleCache(
|
package/src/runtime/modules.ts
CHANGED
|
@@ -61,7 +61,9 @@ import {
|
|
|
61
61
|
resolvePackageSpecifier,
|
|
62
62
|
} from '../resolve/imports'
|
|
63
63
|
import {
|
|
64
|
+
absolutePathLiterals,
|
|
64
65
|
importSpecifiers,
|
|
66
|
+
lineComments,
|
|
65
67
|
moduleSpecifierEdges,
|
|
66
68
|
rewriteSpecifierLiterals,
|
|
67
69
|
stripJsonImportAttributes,
|
|
@@ -1498,16 +1500,38 @@ function relocateSource(
|
|
|
1498
1500
|
const specifiers = spliceSource(contents, edits)
|
|
1499
1501
|
if (!isReleaseCompile()) return specifiers
|
|
1500
1502
|
// Path literals (client-reference targets, module URLs) resolve beside the artifact at runtime.
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1503
|
+
const expression = (value: string) => {
|
|
1504
|
+
const url = value.startsWith('file:')
|
|
1505
|
+
const target = locate(url ? fileURLToPath(value) : value)
|
|
1506
|
+
if (!target) return undefined
|
|
1507
|
+
const href = `new URL(${JSON.stringify(relativeTo(target))}, import.meta.url)`
|
|
1508
|
+
return url ? `${href}.href` : `decodeURIComponent(${href}.pathname)`
|
|
1509
|
+
}
|
|
1510
|
+
const literals = absolutePathLiterals(file, specifiers)
|
|
1511
|
+
if (!literals) {
|
|
1512
|
+
// A recovered parse: the textual form, double-quoted literals only.
|
|
1513
|
+
return specifiers.replace(
|
|
1514
|
+
/(?<!\\)"((?:file:\/\/)?\/[^"\\\n]+)"(\s*:)?/g,
|
|
1515
|
+
(literal, value: string, key: string | undefined) => {
|
|
1516
|
+
const replacement = expression(value)
|
|
1517
|
+
if (!replacement) return literal
|
|
1518
|
+
return key ? `[${replacement}]${key}` : replacement
|
|
1519
|
+
},
|
|
1520
|
+
)
|
|
1521
|
+
}
|
|
1522
|
+
return spliceSource(
|
|
1523
|
+
specifiers,
|
|
1524
|
+
literals.flatMap(literal => {
|
|
1525
|
+
const replacement = expression(literal.value)
|
|
1526
|
+
if (!replacement) return []
|
|
1527
|
+
return [
|
|
1528
|
+
{
|
|
1529
|
+
start: literal.start,
|
|
1530
|
+
end: literal.end,
|
|
1531
|
+
value: literal.key ? `[${replacement}]` : replacement,
|
|
1532
|
+
},
|
|
1533
|
+
]
|
|
1534
|
+
}),
|
|
1511
1535
|
)
|
|
1512
1536
|
}
|
|
1513
1537
|
|
|
@@ -1591,7 +1615,7 @@ export function releaseArtifactSource(file: string, contents: string) {
|
|
|
1591
1615
|
if (!cacheRoot || !anchors) return contents
|
|
1592
1616
|
return relocateSource(
|
|
1593
1617
|
file,
|
|
1594
|
-
releaseInputComments(contents),
|
|
1618
|
+
releaseInputComments(file, contents),
|
|
1595
1619
|
absolute => (isInside(cacheRoot, absolute) ? absolute : portableTarget(anchors, absolute)),
|
|
1596
1620
|
absolute => !isInside(cacheRoot, absolute) && isInstalled(absolute),
|
|
1597
1621
|
)
|
|
@@ -1601,11 +1625,21 @@ export function releaseArtifactSource(file: string, contents: string) {
|
|
|
1601
1625
|
* esbuild's per-input `// <path>` comments, cut to the file name (or its `node_modules/` path, which
|
|
1602
1626
|
* names a vendored font caller): their paths walk the build machine.
|
|
1603
1627
|
*/
|
|
1604
|
-
function releaseInputComments(contents: string) {
|
|
1605
|
-
|
|
1628
|
+
function releaseInputComments(file: string, contents: string) {
|
|
1629
|
+
const shorten = (comment: string) => {
|
|
1606
1630
|
const installed = comment.indexOf('node_modules/')
|
|
1607
1631
|
return `// ${installed === -1 ? path.basename(comment) : comment.slice(installed)}`
|
|
1608
|
-
}
|
|
1632
|
+
}
|
|
1633
|
+
const inputPath = /^ (?:[\w-]+:)?\.{0,2}\/\S*$/
|
|
1634
|
+
const comments = lineComments(file, contents)
|
|
1635
|
+
// A recovered parse: the textual form, whole lines only.
|
|
1636
|
+
if (!comments) return contents.replace(/^\/\/ (?:[\w-]+:)?\.{0,2}\/[^\s]*$/gm, shorten)
|
|
1637
|
+
return spliceSource(
|
|
1638
|
+
contents,
|
|
1639
|
+
comments
|
|
1640
|
+
.filter(comment => inputPath.test(comment.value))
|
|
1641
|
+
.map(comment => ({ ...comment, value: shorten(`//${comment.value}`) })),
|
|
1642
|
+
)
|
|
1609
1643
|
}
|
|
1610
1644
|
|
|
1611
1645
|
/** `target` as a path a moved release still reaches: through the app's own tree, never the machine's. */
|
|
@@ -1634,7 +1668,7 @@ async function writeCompiledFile(file: string, contents: string) {
|
|
|
1634
1668
|
const cacheRoot = path.dirname(profileRoot)
|
|
1635
1669
|
contents = relocateSource(
|
|
1636
1670
|
file,
|
|
1637
|
-
anchors ? releaseInputComments(contents) : contents,
|
|
1671
|
+
anchors ? releaseInputComments(file, contents) : contents,
|
|
1638
1672
|
absolute =>
|
|
1639
1673
|
isInside(cacheRoot, absolute) ? absolute : anchors && portableTarget(anchors, absolute),
|
|
1640
1674
|
absolute => !isInside(cacheRoot, absolute) && isInstalled(absolute),
|
|
@@ -3585,7 +3619,7 @@ async function staticImageModuleSource(config: ResolvedConfig, file: string) {
|
|
|
3585
3619
|
const compat = await getAssetExtensions().staticAssetModule({ sourcePath, bytes, emit })
|
|
3586
3620
|
const source = compat ?? coreStaticAssetModule(sourcePath, bytes, emit)
|
|
3587
3621
|
for (const relative of emitted) {
|
|
3588
|
-
const target = path.join(config.outPath, '
|
|
3622
|
+
const target = path.join(config.outPath, 'static', ...relative.split('/'))
|
|
3589
3623
|
await mkdir(path.dirname(target), { recursive: true })
|
|
3590
3624
|
if (!existsSync(target)) await copyFile(sourcePath, target)
|
|
3591
3625
|
}
|
package/src/runtime/prebundle.ts
CHANGED
|
@@ -55,6 +55,21 @@ export function prebundledFile(file: string): string {
|
|
|
55
55
|
return entries.has(entry) ? path.join(distRoot, `${entry}.js`) : file
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
+
/** A resolve-only `Bun.plugin`, typed here: these modules sit in app type graphs without bun-types. */
|
|
59
|
+
interface ResolvePlugin {
|
|
60
|
+
name: string
|
|
61
|
+
setup(build: {
|
|
62
|
+
onResolve(
|
|
63
|
+
options: { filter: RegExp },
|
|
64
|
+
resolve: (args: { path: string; importer: string }) => { path: string } | undefined,
|
|
65
|
+
): void
|
|
66
|
+
}): void
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function registerResolvePlugin(plugin: ResolvePlugin) {
|
|
70
|
+
;(globalThis as unknown as { Bun: { plugin(plugin: ResolvePlugin): void } }).Bun.plugin(plugin)
|
|
71
|
+
}
|
|
72
|
+
|
|
58
73
|
let registered = false
|
|
59
74
|
|
|
60
75
|
/** Route imports of framework source, by path, to the prebundle. */
|
|
@@ -62,11 +77,16 @@ export function registerPrebundleResolve(): void {
|
|
|
62
77
|
if (!prebundle || registered) return
|
|
63
78
|
registered = true
|
|
64
79
|
const escaped = srcRoot.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
65
|
-
|
|
80
|
+
registerResolvePlugin({
|
|
66
81
|
name: 'pnext-prebundle',
|
|
67
82
|
setup(build) {
|
|
68
|
-
build.onResolve({ filter: new RegExp(
|
|
69
|
-
const
|
|
83
|
+
build.onResolve({ filter: new RegExp(`^${escaped}.*\\.tsx?$`) }, args => {
|
|
84
|
+
const target = prebundledFile(args.path)
|
|
85
|
+
return target === args.path ? undefined : { path: target }
|
|
86
|
+
})
|
|
87
|
+
// A URL encodes the root (`%20` for a space), so it is decoded before the root is compared.
|
|
88
|
+
build.onResolve({ filter: /^file:.*\.tsx?$/ }, args => {
|
|
89
|
+
const file = fileURLToPath(args.path)
|
|
70
90
|
const target = prebundledFile(file)
|
|
71
91
|
return target === file ? undefined : { path: target }
|
|
72
92
|
})
|
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
* build froze. A served request never reads, stats or hashes app source or config, and never
|
|
4
4
|
* compiles; everything it imports is named here. Dev and the build itself keep their own loaders.
|
|
5
5
|
*/
|
|
6
|
-
import { type Dirent, existsSync, readFileSync, readdirSync } from 'node:fs'
|
|
7
|
-
import {
|
|
6
|
+
import { type Dirent, existsSync, readFileSync, readdirSync, realpathSync } from 'node:fs'
|
|
7
|
+
import { rename, writeFile } from 'node:fs/promises'
|
|
8
8
|
import path from 'node:path'
|
|
9
9
|
import { pathToFileURL } from 'node:url'
|
|
10
10
|
import type { ResolvedConfig } from '../config'
|
|
11
11
|
import type { ReleasedFont } from '../render/hooks'
|
|
12
12
|
import type { StaticMetadataFile } from '../routing/metadata-files'
|
|
13
|
+
import { prebundledFile, registerResolvePlugin } from './prebundle'
|
|
14
|
+
import { splitResourceQuery } from '../utils/resource-query'
|
|
13
15
|
|
|
14
16
|
export const BUILD_INDEX_VERSION = 1
|
|
15
|
-
const LOCATOR_FILE = 'release-locator.json'
|
|
16
17
|
|
|
17
18
|
/** `server` is the RSC/server layer, `client` the SSR copy of client components. */
|
|
18
19
|
export type ReleaseLayer = 'server' | 'client'
|
|
@@ -91,6 +92,96 @@ export function buildIndexFile(outPath: string) {
|
|
|
91
92
|
return path.join(outPath, 'server', 'build-index.json')
|
|
92
93
|
}
|
|
93
94
|
|
|
95
|
+
export function buildManifestFile(outPath: string) {
|
|
96
|
+
return path.join(outPath, 'server', 'manifest.json')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The framework copy a standalone dir ships: its compiled modules name framework files there. */
|
|
100
|
+
export function releaseFrameworkRoot(outPath: string) {
|
|
101
|
+
try {
|
|
102
|
+
const { name } = JSON.parse(readFileSync(path.join(frameworkRoot, 'package.json'), 'utf8')) as {
|
|
103
|
+
name: string
|
|
104
|
+
}
|
|
105
|
+
return realpathSync(path.join(outPath, 'node_modules', name))
|
|
106
|
+
} catch {
|
|
107
|
+
return frameworkRoot
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Where a release's app sources are, as its compiled modules name them: the app root the build recorded
|
|
113
|
+
* relative to its output. In place that is the real root; a copied standalone keeps the same relation.
|
|
114
|
+
*/
|
|
115
|
+
export function releaseSourceRoot(outPath: string, serializedOutPath: string) {
|
|
116
|
+
return path.resolve(outPath, path.relative(serializedOutPath, '.'))
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Build-machine facts about a standalone dir, kept in the build cache beside it. */
|
|
120
|
+
export function standaloneOriginsFile(outPath: string) {
|
|
121
|
+
return path.join(path.dirname(outPath), 'cache', 'standalone.json')
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let shippedRelease: string | null | undefined
|
|
125
|
+
|
|
126
|
+
/** The standalone dir this framework copy ships in (`<dir>/node_modules/…/<name>`), if it is one. */
|
|
127
|
+
export function servingReleaseDir(): string | undefined {
|
|
128
|
+
if (shippedRelease === undefined) {
|
|
129
|
+
shippedRelease = null
|
|
130
|
+
// Isolated installs nest the copy deeper: `node_modules/.bun/<pkg>/node_modules/<name>`.
|
|
131
|
+
for (
|
|
132
|
+
let dir = path.dirname(frameworkRoot);
|
|
133
|
+
dir !== path.dirname(dir);
|
|
134
|
+
dir = path.dirname(dir)
|
|
135
|
+
) {
|
|
136
|
+
if (path.basename(dir) === 'node_modules' && existsSync(buildIndexFile(path.dirname(dir)))) {
|
|
137
|
+
shippedRelease = path.dirname(dir)
|
|
138
|
+
break
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return shippedRelease ?? undefined
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const linkedReleases = new Map<string, boolean>()
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Serve `release` from this framework copy without loading the standalone one beside it: its imports
|
|
149
|
+
* of its `node_modules` copies resolve back to the files they were cloned from, so the process keeps
|
|
150
|
+
* one instance of the framework and of every package. False when this copy cannot serve it in
|
|
151
|
+
* place: the build cache naming the origins is gone, or the release moved since.
|
|
152
|
+
*/
|
|
153
|
+
export function linkStandaloneOrigins(release: string): boolean {
|
|
154
|
+
if (servingReleaseDir() === release) return true
|
|
155
|
+
const known = linkedReleases.get(release)
|
|
156
|
+
if (known !== undefined) return known
|
|
157
|
+
let origins: Record<string, string> | undefined
|
|
158
|
+
try {
|
|
159
|
+
const parsed = JSON.parse(readFileSync(standaloneOriginsFile(release), 'utf8')) as {
|
|
160
|
+
release: string
|
|
161
|
+
origins: Record<string, string>
|
|
162
|
+
}
|
|
163
|
+
if (parsed.release === release) origins = parsed.origins
|
|
164
|
+
} catch {
|
|
165
|
+
origins = undefined
|
|
166
|
+
}
|
|
167
|
+
linkedReleases.set(release, origins !== undefined)
|
|
168
|
+
if (!origins) return false
|
|
169
|
+
const files = origins
|
|
170
|
+
const modules = `${path.join(release, 'node_modules')}${path.sep}`
|
|
171
|
+
registerResolvePlugin({
|
|
172
|
+
name: 'pnext-standalone-origins',
|
|
173
|
+
setup(build) {
|
|
174
|
+
build.onResolve({ filter: /node_modules\// }, args => {
|
|
175
|
+
const file = path.resolve(path.dirname(args.importer), splitResourceQuery(args.path).path)
|
|
176
|
+
if (!file.startsWith(modules)) return undefined
|
|
177
|
+
const origin = files[path.relative(release, file).split(path.sep).join('/')]
|
|
178
|
+
return origin && existsSync(origin) ? { path: prebundledFile(origin) } : undefined
|
|
179
|
+
})
|
|
180
|
+
},
|
|
181
|
+
})
|
|
182
|
+
return true
|
|
183
|
+
}
|
|
184
|
+
|
|
94
185
|
export function releaseModuleKey(layer: ReleaseLayer, target: string, file: string) {
|
|
95
186
|
return `${layer}:${target}:${file}`
|
|
96
187
|
}
|
|
@@ -145,11 +236,12 @@ export function attachRelease(config: ResolvedConfig, index = readBuildIndex(con
|
|
|
145
236
|
const existing = releases.get(config)
|
|
146
237
|
if (existing) return existing
|
|
147
238
|
const fromRoot = (file: string) => path.resolve(config.root, file)
|
|
239
|
+
const framework = releaseFrameworkRoot(config.outPath)
|
|
148
240
|
const modules = new Map<string, string>()
|
|
149
241
|
for (const [key, artifact] of Object.entries(index.modules)) {
|
|
150
242
|
const second = key.indexOf(':', key.indexOf(':') + 1)
|
|
151
243
|
modules.set(
|
|
152
|
-
`${key.slice(0, second + 1)}${releaseSourceFile(key.slice(second + 1), config.root, config.workspaceRoot)}`,
|
|
244
|
+
`${key.slice(0, second + 1)}${releaseSourceFile(key.slice(second + 1), config.root, config.workspaceRoot, framework)}`,
|
|
153
245
|
pathToFileURL(path.resolve(config.outPath, artifact)).href,
|
|
154
246
|
)
|
|
155
247
|
}
|
|
@@ -272,11 +364,16 @@ export function releaseSourceKey(file: string, root: string, workspaceRoot: stri
|
|
|
272
364
|
return `r:${toPosix(inRoot)}`
|
|
273
365
|
}
|
|
274
366
|
|
|
275
|
-
export function releaseSourceFile(
|
|
367
|
+
export function releaseSourceFile(
|
|
368
|
+
key: string,
|
|
369
|
+
root: string,
|
|
370
|
+
workspaceRoot: string,
|
|
371
|
+
framework = frameworkRoot,
|
|
372
|
+
) {
|
|
276
373
|
const value = key.slice(2)
|
|
277
374
|
if (key.startsWith('r:')) return path.join(root, value)
|
|
278
375
|
if (key.startsWith('w:')) return path.resolve(workspaceRoot, value)
|
|
279
|
-
if (key.startsWith('f:')) return path.resolve(
|
|
376
|
+
if (key.startsWith('f:')) return path.resolve(framework, value)
|
|
280
377
|
return path.join(root, value)
|
|
281
378
|
}
|
|
282
379
|
|
|
@@ -303,23 +400,6 @@ export function readBuildIndex(outPath: string): BuildIndex {
|
|
|
303
400
|
return index
|
|
304
401
|
}
|
|
305
402
|
|
|
306
|
-
/**
|
|
307
|
-
* Where a built root keeps its release: the dir its locator names when the latest build wrote outside
|
|
308
|
-
* the default out dir (a build into the default empties it, locator included), else the default.
|
|
309
|
-
* Undefined when the root holds no build.
|
|
310
|
-
*/
|
|
311
|
-
export function locateRelease(root: string, defaultOutDir: string): string | undefined {
|
|
312
|
-
const outPath = path.join(root, defaultOutDir)
|
|
313
|
-
try {
|
|
314
|
-
const { outDir } = JSON.parse(readFileSync(path.join(outPath, LOCATOR_FILE), 'utf8')) as {
|
|
315
|
-
outDir: string
|
|
316
|
-
}
|
|
317
|
-
return path.resolve(root, outDir)
|
|
318
|
-
} catch {
|
|
319
|
-
return existsSync(buildIndexFile(outPath)) ? outPath : undefined
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
403
|
/** The resolved config as the build saw it, with paths made relative to the root. */
|
|
324
404
|
export function serializeReleaseConfig(config: ResolvedConfig): Record<string, unknown> {
|
|
325
405
|
const relative = (file: string) => path.relative(config.root, file) || '.'
|
|
@@ -367,25 +447,10 @@ export function releaseConfig(
|
|
|
367
447
|
}
|
|
368
448
|
}
|
|
369
449
|
|
|
370
|
-
/** Publish the build index last, atomically
|
|
371
|
-
export async function writeBuildIndex(
|
|
372
|
-
config: ResolvedConfig,
|
|
373
|
-
index: BuildIndex,
|
|
374
|
-
defaultOutDir: string,
|
|
375
|
-
) {
|
|
450
|
+
/** Publish the build index last, atomically. */
|
|
451
|
+
export async function writeBuildIndex(config: ResolvedConfig, index: BuildIndex) {
|
|
376
452
|
const file = buildIndexFile(config.outPath)
|
|
377
453
|
const temporary = `${file}.${process.pid}.tmp`
|
|
378
454
|
await writeFile(temporary, JSON.stringify(index))
|
|
379
455
|
await rename(temporary, file)
|
|
380
|
-
const defaultOut = path.join(config.root, defaultOutDir)
|
|
381
|
-
if (path.resolve(config.outPath) === path.resolve(defaultOut)) return
|
|
382
|
-
await mkdir(defaultOut, { recursive: true })
|
|
383
|
-
const locator = path.join(defaultOut, LOCATOR_FILE)
|
|
384
|
-
await writeFile(
|
|
385
|
-
`${locator}.${process.pid}.tmp`,
|
|
386
|
-
JSON.stringify({ outDir: path.relative(config.root, config.outPath) }),
|
|
387
|
-
)
|
|
388
|
-
await rename(`${locator}.${process.pid}.tmp`, locator)
|
|
389
|
-
// A default-out release left by an earlier build is now stale: the locator already outranks it.
|
|
390
|
-
await rm(buildIndexFile(defaultOut), { force: true })
|
|
391
456
|
}
|
|
@@ -9,7 +9,8 @@ import { readFile, readdir, rm } from 'node:fs/promises'
|
|
|
9
9
|
import path from 'node:path'
|
|
10
10
|
import type { ResolvedConfig } from '../config'
|
|
11
11
|
import { getExternalPackagePolicy } from '../resolve/imports'
|
|
12
|
-
import { importSpecifiers } from '../resolve/scan-facts'
|
|
12
|
+
import { importMetaRefs, importSpecifiers } from '../resolve/scan-facts'
|
|
13
|
+
import { splitResourceQuery } from '../utils/resource-query'
|
|
13
14
|
import { toPosixPath, writeFileAtomic } from '../utils/fs'
|
|
14
15
|
import { hashBundleSpecifier } from './loader'
|
|
15
16
|
import { cacheRoot, devSourceIdentity } from './module-cache'
|
|
@@ -242,9 +243,7 @@ export async function pruneReleaseVendor(config: ResolvedConfig, sources: Map<st
|
|
|
242
243
|
const cache = cacheRoot(config.outPath)
|
|
243
244
|
const vendor = path.join(cache, 'vendor')
|
|
244
245
|
const graphs = path.join(cache, 'deps')
|
|
245
|
-
const compiled =
|
|
246
|
-
.filter(entry => !entry.isDirectory() && /\.[cm]?js$/.test(entry.name))
|
|
247
|
-
.map(entry => path.join(entry.parentPath, entry.name))
|
|
246
|
+
const compiled = await compiledFiles(cache)
|
|
248
247
|
const reached = new Set<string>()
|
|
249
248
|
let frontier = compiled.filter(file => !isInside(vendor, file) && !isInside(graphs, file))
|
|
250
249
|
while (frontier.length > 0) {
|
|
@@ -260,7 +259,7 @@ export async function pruneReleaseVendor(config: ResolvedConfig, sources: Map<st
|
|
|
260
259
|
(/\.[cm]?js$/.test(file)
|
|
261
260
|
? await readFile(file, 'utf8').catch(() => undefined)
|
|
262
261
|
: undefined)
|
|
263
|
-
for (const specifier of code ? relativeReferences(code) : []) {
|
|
262
|
+
for (const specifier of code ? relativeReferences(file, code) : []) {
|
|
264
263
|
const target = path.resolve(path.dirname(file), splitSuffix(specifier).specifier)
|
|
265
264
|
if (isInside(vendor, target)) next.push(target)
|
|
266
265
|
}
|
|
@@ -275,14 +274,25 @@ export async function pruneReleaseVendor(config: ResolvedConfig, sources: Map<st
|
|
|
275
274
|
)
|
|
276
275
|
}
|
|
277
276
|
|
|
277
|
+
// The compat cache mirrors app-root entries (node_modules included) as symlinks; never follow them.
|
|
278
|
+
async function compiledFiles(dir: string): Promise<string[]> {
|
|
279
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch(() => [])
|
|
280
|
+
const nested = await Promise.all(
|
|
281
|
+
entries.map(async entry => {
|
|
282
|
+
const file = path.join(dir, entry.name)
|
|
283
|
+
if (entry.isDirectory()) return compiledFiles(file)
|
|
284
|
+
return entry.isFile() && /\.[cm]?js$/.test(entry.name) ? [file] : []
|
|
285
|
+
}),
|
|
286
|
+
)
|
|
287
|
+
return nested.flat()
|
|
288
|
+
}
|
|
289
|
+
|
|
278
290
|
/** Relative module references in emitted code: imports, requires and `new URL(…, import.meta.url)`. */
|
|
279
|
-
function relativeReferences(code: string) {
|
|
291
|
+
function relativeReferences(file: string, code: string) {
|
|
280
292
|
return [
|
|
281
293
|
...outputSpecifiers(code).map(found => found.value),
|
|
282
294
|
...emittedRefs(code).map(ref => ref.specifier),
|
|
283
|
-
...
|
|
284
|
-
match => JSON.parse(match[1]!) as string,
|
|
285
|
-
),
|
|
295
|
+
...importMetaRefs(file, code).urls.map(url => url.specifier),
|
|
286
296
|
].filter(specifier => specifier.startsWith('.'))
|
|
287
297
|
}
|
|
288
298
|
|
|
@@ -296,10 +306,8 @@ function entryName(config: ResolvedConfig, entry: string) {
|
|
|
296
306
|
}
|
|
297
307
|
|
|
298
308
|
function splitSuffix(value: string) {
|
|
299
|
-
const
|
|
300
|
-
return
|
|
301
|
-
? { specifier: value, suffix: '' }
|
|
302
|
-
: { specifier: value.slice(0, index), suffix: value.slice(index) }
|
|
309
|
+
const { path: specifier, query: suffix } = splitResourceQuery(value)
|
|
310
|
+
return { specifier, suffix }
|
|
303
311
|
}
|
|
304
312
|
|
|
305
313
|
function packageName(specifier: string) {
|
|
@@ -34,7 +34,12 @@ import {
|
|
|
34
34
|
serverDefineOptions,
|
|
35
35
|
type ServerEsbuildPluginOptions,
|
|
36
36
|
} from '../extensions'
|
|
37
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
pathToFileHref,
|
|
39
|
+
type CompatAliasTarget,
|
|
40
|
+
type ResolvedConfig,
|
|
41
|
+
outCachePath,
|
|
42
|
+
} from '../config'
|
|
38
43
|
import {
|
|
39
44
|
cacheRoot,
|
|
40
45
|
devArtifactUsable,
|
|
@@ -65,9 +70,10 @@ import {
|
|
|
65
70
|
} from '../client/reference-stub'
|
|
66
71
|
import { noteCompiledClientReference } from '../client/reference'
|
|
67
72
|
import { reactCompatEnabled } from '../render/hooks'
|
|
68
|
-
import { writeFileAtomic } from '../utils/fs'
|
|
73
|
+
import { toPosixPath, writeFileAtomic } from '../utils/fs'
|
|
69
74
|
import { releaseArtifactSource } from './modules'
|
|
70
75
|
import { formatDuration } from '../utils/verbose'
|
|
76
|
+
import { hasModuleState, importMetaRefs, scanFacts } from '../resolve/scan-facts'
|
|
71
77
|
import {
|
|
72
78
|
addCommonJsNamedExports,
|
|
73
79
|
canonicalVendorCode,
|
|
@@ -263,6 +269,21 @@ function appendReleaseLog(config: ResolvedConfig, record: object) {
|
|
|
263
269
|
* itself (`import.meta.url`) or imports computed paths loads in place, as in 0.1.6: Next's webpack
|
|
264
270
|
* contexts bundle computed imports instead. Returns the files written and the entries left in place.
|
|
265
271
|
*/
|
|
272
|
+
/**
|
|
273
|
+
* esbuild names CommonJS modules by path from `absWorkingDir`; a `node_modules` linked from outside
|
|
274
|
+
* the app makes those names climb to the build machine's absolute path. The quoted prefix to rewrite.
|
|
275
|
+
*/
|
|
276
|
+
function machineModuleKeyPrefix(root: string) {
|
|
277
|
+
let real: string
|
|
278
|
+
try {
|
|
279
|
+
real = realpathSync(path.join(root, 'node_modules'))
|
|
280
|
+
} catch {
|
|
281
|
+
return undefined
|
|
282
|
+
}
|
|
283
|
+
const relative = toPosixPath(path.relative(root, real))
|
|
284
|
+
return relative.startsWith('../') ? `"${relative}/` : undefined
|
|
285
|
+
}
|
|
286
|
+
|
|
266
287
|
export async function linkReleaseDependencies(
|
|
267
288
|
config: ResolvedConfig,
|
|
268
289
|
layer: ReleaseDependencyLayer,
|
|
@@ -338,10 +359,12 @@ export async function linkReleaseDependencies(
|
|
|
338
359
|
await rm(staging, { recursive: true, force: true })
|
|
339
360
|
try {
|
|
340
361
|
await mkdir(path.join(staging, 'chunks'), { recursive: true })
|
|
362
|
+
const keys = machineModuleKeyPrefix(config.root)
|
|
341
363
|
for (const output of outputs) {
|
|
364
|
+
const text = keys ? output.text.replaceAll(keys, '"node_modules/') : output.text
|
|
342
365
|
const code = entryFiles.has(output.path)
|
|
343
|
-
? addCommonJsNamedExports(
|
|
344
|
-
:
|
|
366
|
+
? addCommonJsNamedExports(text, sharedCommonJsBody(output.path, text, texts))
|
|
367
|
+
: text
|
|
345
368
|
await writeFile(
|
|
346
369
|
path.join(staging, path.relative(outdir, output.path)),
|
|
347
370
|
releaseArtifactSource(
|
|
@@ -364,16 +387,13 @@ export async function linkReleaseDependencies(
|
|
|
364
387
|
|
|
365
388
|
// `import.meta` paths and an `import()` of a computed path resolve where the file lies; an import marked
|
|
366
389
|
// `webpackIgnore`/`@vite-ignore` is meant to stay a runtime import, as Next's bundle keeps it.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if (!/webpackIgnore:\s*true|@vite-ignore/.test(match[1]!)) return true
|
|
375
|
-
}
|
|
376
|
-
return false
|
|
390
|
+
/** Reads its own location or imports a computed path (unless it opts out with a magic comment). */
|
|
391
|
+
function readsBesideItself(file: string, source: string) {
|
|
392
|
+
const refs = importMetaRefs(file, source)
|
|
393
|
+
if (refs.readsLocation) return true
|
|
394
|
+
return refs.computedImports.some(
|
|
395
|
+
call => !/webpackIgnore:\s*true|@vite-ignore/.test(source.slice(call.start, call.end)),
|
|
396
|
+
)
|
|
377
397
|
}
|
|
378
398
|
|
|
379
399
|
/** Package dirs whose files read beside themselves or import computed paths. */
|
|
@@ -392,7 +412,7 @@ async function inPlacePackages(
|
|
|
392
412
|
await Promise.all(
|
|
393
413
|
installed.map(async file => {
|
|
394
414
|
const source = await readFile(file, 'utf8').catch(() => '')
|
|
395
|
-
if (readsBesideItself(source)) files.add(file)
|
|
415
|
+
if (readsBesideItself(file, source)) files.add(file)
|
|
396
416
|
}),
|
|
397
417
|
)
|
|
398
418
|
return [
|
|
@@ -411,9 +431,9 @@ async function inPlacePackages(
|
|
|
411
431
|
*/
|
|
412
432
|
function sharedCommonJsBody(file: string, code: string, texts: ReadonlyMap<string, string>) {
|
|
413
433
|
const wrapper = /(?:^|\n)export default (require_[\w$]+)\(\);?/.exec(code)?.[1]
|
|
434
|
+
// The chunk that defines the wrapper, from the parsed imports: `$` in its name is no regex hazard.
|
|
414
435
|
const chunk =
|
|
415
|
-
wrapper &&
|
|
416
|
-
new RegExp(`import\\s*\\{[^}]*\\b${wrapper}\\b[^}]*\\}\\s*from\\s*"([^"]+)"`).exec(code)?.[1]
|
|
436
|
+
wrapper && scanFacts(file, code).imports.find(edge => edge.exports.includes(wrapper))?.specifier
|
|
417
437
|
const text = chunk && texts.get(path.resolve(path.dirname(file), chunk))
|
|
418
438
|
if (!text) return code
|
|
419
439
|
const start = text.indexOf(`var ${wrapper} = `)
|
|
@@ -742,7 +762,12 @@ const vendorPortablePath = (config: ResolvedConfig, file: string) =>
|
|
|
742
762
|
devSourceIdentity(file, config.workspaceRoot)
|
|
743
763
|
|
|
744
764
|
function vendorArtifactFile(config: ResolvedConfig, key: string) {
|
|
745
|
-
return path.join(
|
|
765
|
+
return path.join(
|
|
766
|
+
outCachePath(config.outPath),
|
|
767
|
+
'server',
|
|
768
|
+
'vendor',
|
|
769
|
+
`${hashBundleSpecifier(key)}.mjs`,
|
|
770
|
+
)
|
|
746
771
|
}
|
|
747
772
|
|
|
748
773
|
/**
|
|
@@ -1041,7 +1066,7 @@ function reusableVendorContent(
|
|
|
1041
1066
|
loadVendorSharedEntries(config)
|
|
1042
1067
|
const id = vendorSharedFor(config).get(entry)
|
|
1043
1068
|
if (!id) return undefined
|
|
1044
|
-
const content = vendorContentFile(path.join(config.outPath, '
|
|
1069
|
+
const content = vendorContentFile(path.join(outCachePath(config.outPath), 'server', 'vendor'), id)
|
|
1045
1070
|
return existsSync(content) ? content : undefined
|
|
1046
1071
|
}
|
|
1047
1072
|
|
|
@@ -1704,9 +1729,6 @@ function packageExportSubpaths(packageRoot: string) {
|
|
|
1704
1729
|
}
|
|
1705
1730
|
|
|
1706
1731
|
/** A top-level binding created by `new` or a non-PURE call: an identity each copy would duplicate. */
|
|
1707
|
-
const MODULE_STATE =
|
|
1708
|
-
/^(?:export\s+)?(?:const|let|var)\s[^=;]*=\s*(?:(?:\/\*\s*[#@]__PURE__\s*\*\/\s*)?new\s|(?!require\s*\()[\w$.]+\s*\()/m
|
|
1709
|
-
|
|
1710
1732
|
async function statefulPackageFiles(entry: string, packageRoot: string) {
|
|
1711
1733
|
const files = [...(await packageReach(entry, packageRoot))]
|
|
1712
1734
|
const sources = await Promise.all(files.map(file => packageFileScan(file)))
|
|
@@ -1728,7 +1750,7 @@ function packageFileScan(file: string) {
|
|
|
1728
1750
|
.scanImports(source)
|
|
1729
1751
|
.map(({ path: specifier }) => specifier)
|
|
1730
1752
|
.filter(specifier => specifier.startsWith('.')),
|
|
1731
|
-
stateful:
|
|
1753
|
+
stateful: hasModuleState(file, source),
|
|
1732
1754
|
}))
|
|
1733
1755
|
.catch(() => undefined)
|
|
1734
1756
|
packageFileScans.set(file, scan)
|
package/src/types.ts
CHANGED
|
@@ -45,9 +45,8 @@ export interface PNextConfig {
|
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
|
-
* What
|
|
49
|
-
*
|
|
50
|
-
* when that classification is wrong for an app: `exclude` drops more, `keep` overrides a built-in drop.
|
|
48
|
+
* What `<outDir>/standalone` ships beyond the files its server imports. `exclude` drops traced
|
|
49
|
+
* `node_modules` files; `keep` ships app files the server reads at runtime, at their root-relative paths.
|
|
51
50
|
* Entries are directory names (`storybook-static`) or file suffixes (`.map`).
|
|
52
51
|
*/
|
|
53
52
|
export interface PNextAdapterConfig {
|