@wular/pnext 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/pnext +9 -2
- package/dist/server/_chunks/aliases-j47a10ce.js +44 -0
- package/dist/server/_chunks/analyze-arswqe6s.js +445 -0
- package/dist/server/_chunks/boot-af0mv3dy.js +36 -0
- package/dist/server/_chunks/build-spy3dxp4.js +84 -0
- package/dist/server/_chunks/build-t9h0hec3.js +3550 -0
- package/dist/server/_chunks/build-tier-m7yvqz61.js +2472 -0
- package/dist/server/_chunks/compile-53j02j27.js +22 -0
- package/dist/server/_chunks/config-1yzwexq6.js +27 -0
- package/dist/server/_chunks/config-n2z7yxps.js +22 -0
- package/dist/server/_chunks/create-meec9hs6.js +134 -0
- package/dist/server/_chunks/dev-fjmqg6en.js +220 -0
- package/dist/server/_chunks/esbuild-yyktfrtt.js +15 -0
- package/dist/server/_chunks/generate-n9sh6hzt.js +21 -0
- package/dist/server/_chunks/index-0374j2b9.js +66 -0
- package/dist/server/_chunks/index-06nyqntx.js +213 -0
- package/dist/server/_chunks/index-1011cscr.js +5263 -0
- package/dist/server/_chunks/index-11sfk4hb.js +170 -0
- package/dist/server/_chunks/index-20ppawv7.js +297 -0
- package/dist/server/_chunks/index-2dv4y4wd.js +1065 -0
- package/dist/server/_chunks/index-2vz0wzdn.js +59 -0
- package/dist/server/_chunks/index-2wfv4kvx.js +182 -0
- package/dist/server/_chunks/index-357na4a8.js +109 -0
- package/dist/server/_chunks/index-3b3at80h.js +109 -0
- package/dist/server/_chunks/index-3tf1xjsp.js +6166 -0
- package/dist/server/_chunks/index-3xbr4eyv.js +105 -0
- package/dist/server/_chunks/index-4399bvd2.js +18 -0
- package/dist/server/_chunks/index-4hgjrqh7.js +851 -0
- package/dist/server/_chunks/index-4q2gbfwk.js +2530 -0
- package/dist/server/_chunks/index-4t92hdxd.js +172 -0
- package/dist/server/_chunks/index-4zzebszd.js +10 -0
- package/dist/server/_chunks/index-5gyr4emz.js +107 -0
- package/dist/server/_chunks/index-5hr4062s.js +70 -0
- package/dist/server/_chunks/index-68m3mwbd.js +84 -0
- package/dist/server/_chunks/index-6b009mt0.js +56 -0
- package/dist/server/_chunks/index-6e4fqv30.js +588 -0
- package/dist/server/_chunks/index-6gex3pfa.js +15 -0
- package/dist/server/_chunks/index-6kp9r0d9.js +11 -0
- package/dist/server/_chunks/index-6q7zvrap.js +134 -0
- package/dist/server/_chunks/index-73z4esab.js +38 -0
- package/dist/server/_chunks/index-79ngvam8.js +60 -0
- package/dist/server/_chunks/index-7wc9n8be.js +25 -0
- package/dist/server/_chunks/index-8k7pfejn.js +1599 -0
- package/dist/server/_chunks/index-8kcxdfya.js +206 -0
- package/dist/server/_chunks/index-91x12ykq.js +274 -0
- package/dist/server/_chunks/index-9ch50vtq.js +18 -0
- package/dist/server/_chunks/index-9hx2641q.js +28 -0
- package/dist/server/_chunks/index-9n2914ww.js +535 -0
- package/dist/server/_chunks/index-9ych9ma8.js +207 -0
- package/dist/server/_chunks/index-b6wtkdp4.js +24 -0
- package/dist/server/_chunks/index-bcws5eh2.js +35 -0
- package/dist/server/_chunks/index-c0g2wf3z.js +92 -0
- package/dist/server/_chunks/index-cf4rvxv6.js +95 -0
- package/dist/server/_chunks/index-cjgqs13g.js +65 -0
- package/dist/server/_chunks/index-ckkdpht5.js +41 -0
- package/dist/server/_chunks/index-cyfednwb.js +87 -0
- package/dist/server/_chunks/index-danncfhy.js +311 -0
- package/dist/server/_chunks/index-dg0f05zs.js +199 -0
- package/dist/server/_chunks/index-e3a6yx84.js +18 -0
- package/dist/server/_chunks/index-e88tyv35.js +45 -0
- package/dist/server/_chunks/index-eajaspjk.js +1253 -0
- package/dist/server/_chunks/index-eeaanp2e.js +483 -0
- package/dist/server/_chunks/index-egykcqg3.js +101 -0
- package/dist/server/_chunks/index-en7n9f7m.js +22 -0
- package/dist/server/_chunks/index-ezgj0tr1.js +88 -0
- package/dist/server/_chunks/index-fkp000p1.js +590 -0
- package/dist/server/_chunks/index-fn1chkkd.js +214 -0
- package/dist/server/_chunks/index-fp8r0sqs.js +64 -0
- package/dist/server/_chunks/index-ggk2j965.js +9432 -0
- package/dist/server/_chunks/index-grta8ap3.js +238 -0
- package/dist/server/_chunks/index-h2a70tg4.js +7 -0
- package/dist/server/_chunks/index-h4xy648y.js +51 -0
- package/dist/server/_chunks/index-hkdfj58q.js +92 -0
- package/dist/server/_chunks/index-j2zrcp1k.js +66 -0
- package/dist/server/_chunks/index-jcsjq3d1.js +20 -0
- package/dist/server/_chunks/index-jepjvcrf.js +198 -0
- package/dist/server/_chunks/index-jks0x0a1.js +14 -0
- package/dist/server/_chunks/index-jx7bqvw1.js +57 -0
- package/dist/server/_chunks/index-k1g3epw0.js +1299 -0
- package/dist/server/_chunks/index-knp0s912.js +7 -0
- package/dist/server/_chunks/index-kq8kpzye.js +472 -0
- package/dist/server/_chunks/index-kqyy1d4f.js +50 -0
- package/dist/server/_chunks/index-kresp2n8.js +445 -0
- package/dist/server/_chunks/index-ms9v9tnx.js +31 -0
- package/dist/server/_chunks/index-n4hxpng2.js +11 -0
- package/dist/server/_chunks/index-ncnes8c6.js +17 -0
- package/dist/server/_chunks/index-nqh3xhdc.js +57 -0
- package/dist/server/_chunks/index-nyrba2kr.js +4130 -0
- package/dist/server/_chunks/index-p77b4kcx.js +296 -0
- package/dist/server/_chunks/index-pym1cezq.js +39 -0
- package/dist/server/_chunks/index-q738kkhj.js +100 -0
- package/dist/server/_chunks/index-qjj6gddn.js +54 -0
- package/dist/server/_chunks/index-qm6kmhqs.js +110 -0
- package/dist/server/_chunks/index-qn4z5s3c.js +819 -0
- package/dist/server/_chunks/index-qpwsgt3a.js +158 -0
- package/dist/server/_chunks/index-r97ptz1q.js +97 -0
- package/dist/server/_chunks/index-ras0sdab.js +26 -0
- package/dist/server/_chunks/index-rcs322t1.js +19 -0
- package/dist/server/_chunks/index-rn8dyr1f.js +126 -0
- package/dist/server/_chunks/index-rt9qq1va.js +4 -0
- package/dist/server/_chunks/index-rthrsed5.js +356 -0
- package/dist/server/_chunks/index-sctcgyvv.js +185 -0
- package/dist/server/_chunks/index-sjpckxqn.js +213 -0
- package/dist/server/_chunks/index-sq3kvz3g.js +200 -0
- package/dist/server/_chunks/index-stbk3jhn.js +31 -0
- package/dist/server/_chunks/index-sv8m6789.js +266 -0
- package/dist/server/_chunks/index-tgcakdxc.js +125 -0
- package/dist/server/_chunks/index-tgsfjmep.js +74 -0
- package/dist/server/_chunks/index-tq0pc7eg.js +154 -0
- package/dist/server/_chunks/index-tq1f96v7.js +51 -0
- package/dist/server/_chunks/index-tqn2qnnn.js +241 -0
- package/dist/server/_chunks/index-tvqkq6e6.js +128 -0
- package/dist/server/_chunks/index-v1ags1na.js +132 -0
- package/dist/server/_chunks/index-vvmmknm1.js +1431 -0
- package/dist/server/_chunks/index-vvq7rqtn.js +329 -0
- package/dist/server/_chunks/index-vz0km5qk.js +33 -0
- package/dist/server/_chunks/index-w6h8m6vp.js +138 -0
- package/dist/server/_chunks/index-web361b8.js +138 -0
- package/dist/server/_chunks/index-wpfhfbs4.js +194 -0
- package/dist/server/_chunks/index-x0y005nh.js +283 -0
- package/dist/server/_chunks/index-x3yn4ywm.js +22 -0
- package/dist/server/_chunks/index-x93hv0sc.js +271 -0
- package/dist/server/_chunks/index-xvj80c3a.js +30 -0
- package/dist/server/_chunks/index-xywjg2vc.js +100 -0
- package/dist/server/_chunks/index-y2jr2n72.js +152 -0
- package/dist/server/_chunks/index-y36a0ybw.js +57 -0
- package/dist/server/_chunks/index-ye9hmsvf.js +47 -0
- package/dist/server/_chunks/index-yhxkxghe.js +56 -0
- package/dist/server/_chunks/index-ym67zqxp.js +130 -0
- package/dist/server/_chunks/index-ytjvpbm2.js +736 -0
- package/dist/server/_chunks/index-yz54pxrh.js +960 -0
- package/dist/server/_chunks/index-z4z9zv3b.js +733 -0
- package/dist/server/_chunks/index-z84ab1w0.js +1270 -0
- package/dist/server/_chunks/index-z88qv16t.js +11 -0
- package/dist/server/_chunks/index-zqpqyg8p.js +666 -0
- package/dist/server/_chunks/loader-7yw0j98z.js +78 -0
- package/dist/server/_chunks/modules-jn8bmbn8.js +74 -0
- package/dist/server/_chunks/pipeline-yy9jhydf.js +832 -0
- package/dist/server/_chunks/production-jar9ztm3.js +44 -0
- package/dist/server/_chunks/proxy-config-j84dgksn.js +21 -0
- package/dist/server/_chunks/proxy-w1d0wmsn.js +33 -0
- package/dist/server/_chunks/router-k1reahfn.js +498 -0
- package/dist/server/_chunks/routes-2s277fc6.js +64 -0
- package/dist/server/_chunks/run-pvd8bs1t.js +696 -0
- package/dist/server/_chunks/server-mt4a994c.js +1835 -0
- package/dist/server/_chunks/tsconfig-defaults-1nb3308g.js +20 -0
- package/dist/server/_chunks/typegen-0qr0459b.js +35 -0
- package/dist/server/api/client-cache.js +14 -0
- package/dist/server/cli/index.js +378 -0
- package/dist/server/cli/start.js +137 -0
- package/dist/server/client/reference.js +16 -0
- package/dist/server/compat/next/cache.js +56 -0
- package/dist/server/compat/next/canonical-url.js +13 -0
- package/dist/server/compat/next/client-cache.js +57 -0
- package/dist/server/compat/next/client-navigation.js +232 -0
- package/dist/server/compat/next/client-only.js +1 -0
- package/dist/server/compat/next/client-script.js +178 -0
- package/dist/server/compat/next/client-server.js +34 -0
- package/dist/server/compat/next/config-headers.js +32 -0
- package/dist/server/compat/next/config-loader.js +25 -0
- package/dist/server/compat/next/config.js +10 -0
- package/dist/server/compat/next/constants.js +18 -0
- package/dist/server/compat/next/custom-server.js +10 -0
- package/dist/server/compat/next/dist/client/components/app-router-headers.js +48 -0
- package/dist/server/compat/next/dist/server/web/spec-extension/revalidate.js +27 -0
- package/dist/server/compat/next/dist/server/web/spec-extension/unstable-cache.js +25 -0
- package/dist/server/compat/next/dist/server/web/spec-extension/unstable-no-store.js +25 -0
- package/dist/server/compat/next/dynamic.js +32 -0
- package/dist/server/compat/next/error.js +112 -0
- package/dist/server/compat/next/font/cache.js +14 -0
- package/dist/server/compat/next/font/google.js +3 -0
- package/dist/server/compat/next/font/index.js +1 -0
- package/dist/server/compat/next/font/local.js +22 -0
- package/dist/server/compat/next/font/runtime-client.js +33 -0
- package/dist/server/compat/next/font/runtime.js +41 -0
- package/dist/server/compat/next/font/shared.js +22 -0
- package/dist/server/compat/next/form.js +129 -0
- package/dist/server/compat/next/head.js +10 -0
- package/dist/server/compat/next/headers.js +30 -0
- package/dist/server/compat/next/image/client.js +11 -0
- package/dist/server/compat/next/image/config.js +18 -0
- package/dist/server/compat/next/image/optimizer.js +25 -0
- package/dist/server/compat/next/image/patterns.js +12 -0
- package/dist/server/compat/next/image/props.js +16 -0
- package/dist/server/compat/next/image/shared.js +86 -0
- package/dist/server/compat/next/image/static-metadata.js +32 -0
- package/dist/server/compat/next/image/validate.js +8 -0
- package/dist/server/compat/next/image.js +59 -0
- package/dist/server/compat/next/index.js +1 -0
- package/dist/server/compat/next/legacy-image.js +78 -0
- package/dist/server/compat/next/legacy-request-apis.js +24 -0
- package/dist/server/compat/next/link-transform.js +14 -0
- package/dist/server/compat/next/link.js +14 -0
- package/dist/server/compat/next/navigation.js +190 -0
- package/dist/server/compat/next/offline.js +45 -0
- package/dist/server/compat/next/og.js +8 -0
- package/dist/server/compat/next/preferred-region.js +8 -0
- package/dist/server/compat/next/redirects.js +30 -0
- package/dist/server/compat/next/resource-hints.js +30 -0
- package/dist/server/compat/next/rewrites.js +41 -0
- package/dist/server/compat/next/root-params.js +121 -0
- package/dist/server/compat/next/route-state.js +23 -0
- package/dist/server/compat/next/router.js +103 -0
- package/dist/server/compat/next/script.js +37 -0
- package/dist/server/compat/next/server-only.js +1 -0
- package/dist/server/compat/next/server.js +131 -0
- package/dist/server/compat/next/svgr.js +14 -0
- package/dist/server/compat/next/telemetry.js +10 -0
- package/dist/server/compat/next/usage.js +13 -0
- package/dist/server/compat/next/user-agent.js +12 -0
- package/dist/server/compat/next/web-vitals.js +35 -0
- package/dist/server/compat/react/action-state.js +11 -0
- package/dist/server/compat/react/client-lite.js +83 -0
- package/dist/server/compat/react/client.js +131 -0
- package/dist/server/compat/react/compiler-runtime.js +42 -0
- package/dist/server/compat/react/dom-client.js +106 -0
- package/dist/server/compat/react/dom-react-server.js +37 -0
- package/dist/server/compat/react/dom-server.js +40 -0
- package/dist/server/compat/react/dom.js +52 -0
- package/dist/server/compat/react/hooks-extra.js +12 -0
- package/dist/server/compat/react/internals.js +14 -0
- package/dist/server/compat/react/parity.js +11 -0
- package/dist/server/compat/react/preact.js +113 -0
- package/dist/server/compat/react/react-server.js +133 -0
- package/dist/server/compat/react/router-shim.js +8 -0
- package/dist/server/compat/react/server-component-use.js +14 -0
- package/dist/server/compat/react/server-inserted-html.js +14 -0
- package/dist/server/compat/react/server.js +194 -0
- package/dist/server/compat/react/style-values.js +10 -0
- package/dist/server/compat/react/use.js +10 -0
- package/dist/server/compat/react/view-transition.js +12 -0
- package/dist/server/generation.json +1 -0
- package/package.json +4 -1
- package/src/api/dynamic.tsx +2 -0
- package/src/api/server.ts +24 -6
- package/src/cli/adapters/vercel-warm.ts +315 -61
- package/src/cli/adapters/vercel.ts +348 -71
- package/src/cli/build.ts +58 -33
- package/src/cli/index.ts +23 -10
- package/src/cli/serve/entry.ts +21 -159
- package/src/cli/serve/immutable.ts +31 -0
- package/src/cli/serve/pipeline.ts +82 -84
- package/src/cli/start.ts +3 -1
- package/src/client/chunk-fold.ts +19 -6
- package/src/client/react-tier.ts +3 -2
- package/src/client/reference-stub.ts +21 -2
- package/src/compat/actions/client-plugin.ts +4 -2
- package/src/compat/actions/config.ts +6 -5
- package/src/compat/actions/extensions.ts +2 -3
- package/src/compat/aliases.ts +8 -1
- package/src/compat/bundler/config.ts +88 -0
- package/src/compat/bundler/optimize-package-imports.ts +86 -26
- package/src/compat/bundler/relay-transform.ts +15 -3
- package/src/compat/cache-control.ts +16 -8
- package/src/compat/css/modules.ts +18 -5
- package/src/compat/lifecycle/error-funnel.ts +1 -1
- package/src/compat/lifecycle/instrumentation.ts +117 -24
- package/src/compat/lifecycle/testmode.ts +3 -2
- package/src/compat/next/config-loader.ts +137 -13
- package/src/compat/next/font/runtime.ts +22 -2
- package/src/compat/next/og.ts +3 -3
- package/src/compat/next/usage.ts +3 -2
- package/src/compat/pages/api.ts +83 -14
- package/src/compat/pages/router.ts +30 -14
- package/src/compat/register/bundler.ts +3 -1
- package/src/compat/register/middleware.ts +1 -1
- package/src/compat/register/otel.ts +5 -9
- package/src/compat/register/render.ts +3 -1
- package/src/compat/register/use-cache.ts +3 -1
- package/src/compat/release.ts +46 -0
- package/src/compat/segment/serve.ts +1 -1
- package/src/compat/validation/validate.ts +10 -7
- package/src/config.ts +51 -7
- package/src/css/assets.ts +213 -0
- package/src/css/build.ts +174 -238
- package/src/dev/server.ts +27 -8
- package/src/extensions.ts +4 -0
- package/src/render/hooks.ts +13 -0
- package/src/render/renderer.ts +52 -32
- package/src/request/context.ts +9 -0
- package/src/resolve/dynamic.ts +3 -1
- package/src/resolve/imports.ts +12 -52
- package/src/resolve/package-json.ts +56 -0
- package/src/resolve/scan-facts.ts +65 -0
- package/src/routing/href.ts +10 -3
- package/src/routing/match.ts +287 -0
- package/src/routing/metadata-files.ts +19 -5
- package/src/routing/proxy-config.ts +137 -0
- package/src/routing/proxy.ts +35 -134
- package/src/routing/routes.ts +22 -281
- package/src/runtime/fingerprint.ts +23 -8
- package/src/runtime/load.ts +170 -0
- package/src/runtime/loader.ts +215 -43
- package/src/runtime/module-cache.ts +13 -0
- package/src/runtime/modules.ts +370 -81
- package/src/runtime/prebundle.ts +81 -0
- package/src/runtime/production.ts +391 -0
- package/src/runtime/release-graph.ts +334 -0
- package/src/runtime/vendor-build.ts +724 -13
- package/src/runtime/vendor.ts +16 -3
- package/src/types.ts +2 -0
- package/src/utils/fs.ts +89 -3
package/src/runtime/modules.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { builtinModules } from 'node:module'
|
|
2
2
|
import os from 'node:os'
|
|
3
3
|
import path from 'node:path'
|
|
4
|
-
import { existsSync, readFileSync, type Dirent } from 'node:fs'
|
|
4
|
+
import { existsSync, readFileSync, readdirSync, realpathSync, statSync, type Dirent } from 'node:fs'
|
|
5
5
|
import { fileURLToPath } from 'node:url'
|
|
6
6
|
import { copyFile, mkdir, readdir, readlink, rm, symlink, writeFile } from 'node:fs/promises'
|
|
7
7
|
import type { OnResolveResult, Plugin } from 'esbuild'
|
|
@@ -23,7 +23,13 @@ import {
|
|
|
23
23
|
serverBundleRequireConditions,
|
|
24
24
|
type ServerBundleTarget,
|
|
25
25
|
} from './loader'
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
clearReleaseDependencyLog,
|
|
28
|
+
externalServerPackageHref,
|
|
29
|
+
noteReleaseModuleLayer,
|
|
30
|
+
runtimeServerImportTarget,
|
|
31
|
+
type ReleaseDependencyLayer,
|
|
32
|
+
} from '../runtime/vendor-build'
|
|
27
33
|
import { writeFileAtomic } from '../utils/fs'
|
|
28
34
|
import { traceEnabled, traceValue } from '../utils/trace-flags'
|
|
29
35
|
import { createHash } from 'node:crypto'
|
|
@@ -58,6 +64,7 @@ import {
|
|
|
58
64
|
importSpecifiers,
|
|
59
65
|
moduleSpecifierEdges,
|
|
60
66
|
rewriteSpecifierLiterals,
|
|
67
|
+
stripJsonImportAttributes,
|
|
61
68
|
} from '../resolve/scan-facts'
|
|
62
69
|
import {
|
|
63
70
|
cacheRoot,
|
|
@@ -76,7 +83,20 @@ import {
|
|
|
76
83
|
transformServerModule,
|
|
77
84
|
type SpecifierKind,
|
|
78
85
|
} from './module-transform'
|
|
86
|
+
import { splitResourceQuery } from '../resolve/engine'
|
|
79
87
|
import { findShakeableDynamicImports } from '../resolve/tree-shake'
|
|
88
|
+
import { productionRelease, releaseModuleHref } from './production'
|
|
89
|
+
import {
|
|
90
|
+
clearModuleGraphFailure,
|
|
91
|
+
forgetModuleEvalError,
|
|
92
|
+
importModuleOnce,
|
|
93
|
+
isReleaseCompile,
|
|
94
|
+
noteModuleGraphFailure,
|
|
95
|
+
setReleaseCompileFlag,
|
|
96
|
+
throwIfModuleEvalFailed,
|
|
97
|
+
} from './load'
|
|
98
|
+
|
|
99
|
+
export { importModuleOnce, isReleaseCompile, throwIfModuleGraphFailed } from './load'
|
|
80
100
|
import type { RouteManifestEntry } from '../types'
|
|
81
101
|
import { uniqueIdentifier } from '../utils/code'
|
|
82
102
|
import { formatDuration } from '../utils/verbose'
|
|
@@ -114,37 +134,13 @@ const routeBundleBuilds = new Map<string, Promise<string>>()
|
|
|
114
134
|
// present during an earlier check. This avoids repeated reads/parses without
|
|
115
135
|
// turning one observation into a permanent claim that the closure still exists.
|
|
116
136
|
const completeArtifactClosures = new Map<string, readonly string[]>()
|
|
117
|
-
let moduleGraphFailure: Error | undefined
|
|
118
137
|
|
|
119
138
|
/** Reset build-only graph state before starting another build in this process. */
|
|
120
139
|
export function resetModuleGraphFailure(): void {
|
|
121
|
-
|
|
140
|
+
clearModuleGraphFailure()
|
|
122
141
|
completeArtifactClosures.clear()
|
|
123
142
|
}
|
|
124
143
|
|
|
125
|
-
/**
|
|
126
|
-
* Fail a build even when its renderer converted a module-resolution exception
|
|
127
|
-
* into a 500 response. Rendering may recover from user-code errors, but a
|
|
128
|
-
* missing content-addressed artifact means the build output itself is broken.
|
|
129
|
-
*/
|
|
130
|
-
export function throwIfModuleGraphFailed(): void {
|
|
131
|
-
if (moduleGraphFailure !== undefined) throw moduleGraphFailure
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function noteModuleGraphFailure(error: unknown): void {
|
|
135
|
-
moduleGraphFailure ??= error instanceof Error ? error : new Error(String(error))
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function isCompiledModuleResolutionError(error: unknown, href: string): boolean {
|
|
139
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
140
|
-
if (!message.includes('Cannot find module')) return false
|
|
141
|
-
return (
|
|
142
|
-
href.includes('/cache/server/') ||
|
|
143
|
-
/[/\\]cache[/\\]server[/\\]/.test(message) ||
|
|
144
|
-
message.includes('/cache/server/')
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
|
|
148
144
|
// PNEXT_TRACE=server: attribute every per-module compile to its profile,
|
|
149
145
|
// so cross-profile duplicate work is countable rather than inferred. Counts are
|
|
150
146
|
// load-insensitive, which is what makes them usable on a contended box.
|
|
@@ -222,35 +218,10 @@ function reportModuleStats() {
|
|
|
222
218
|
}
|
|
223
219
|
const routeModuleLoaders = new Map<string, Promise<DevRouteModuleLoaders>>()
|
|
224
220
|
|
|
225
|
-
// A module that throws while evaluating stays failed in Bun's registry for the process lifetime, and
|
|
226
|
-
// re-importing it surfaces downstream symptoms (a missing bundle entry, TDZ on an export) instead of
|
|
227
|
-
// the original error. Record the first failure per compiled href and re-throw THAT on every later
|
|
228
|
-
// request. Compiled hrefs are content-addressed, so a save that fixes the module yields a new href
|
|
229
|
-
// and the entry is never consulted again.
|
|
230
|
-
const moduleEvalErrors = new Map<string, unknown>()
|
|
231
221
|
const warmRetryHrefs = new Map<string, Promise<string>>()
|
|
232
222
|
const warmImports = new Map<string, Promise<void>>()
|
|
233
223
|
let warmRetryGeneration = 0
|
|
234
224
|
|
|
235
|
-
/**
|
|
236
|
-
* Import a compiled module, re-throwing its first evaluation error on later imports.
|
|
237
|
-
*
|
|
238
|
-
* Production needs this as much as dev: a re-import resolves with a half-evaluated namespace whose
|
|
239
|
-
* `export const` bindings are still in TDZ, so the render's next read (`module.metadata`) throws
|
|
240
|
-
* `Cannot access 'metadata' before initialization` and that replaces the real error in the response.
|
|
241
|
-
* Prod hrefs are content-addressed too, so the entry keys the same way dev's does.
|
|
242
|
-
*/
|
|
243
|
-
export async function importModuleOnce<T>(href: string): Promise<T> {
|
|
244
|
-
if (moduleEvalErrors.has(href)) throw moduleEvalErrors.get(href)
|
|
245
|
-
try {
|
|
246
|
-
return (await import(href)) as T
|
|
247
|
-
} catch (error) {
|
|
248
|
-
if (isCompiledModuleResolutionError(error, href)) noteModuleGraphFailure(error)
|
|
249
|
-
moduleEvalErrors.set(href, error)
|
|
250
|
-
throw error
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
225
|
interface ImportDevModuleOptions {
|
|
255
226
|
/** A speculative import whose evaluation failure must not become render state. */
|
|
256
227
|
warm?: boolean
|
|
@@ -298,7 +269,7 @@ export async function importDevModule<T>(
|
|
|
298
269
|
let attemptedEvaluation = false
|
|
299
270
|
try {
|
|
300
271
|
importHref = (await warmRetryHrefs.get(href)) ?? href
|
|
301
|
-
|
|
272
|
+
throwIfModuleEvalFailed(importHref)
|
|
302
273
|
// Pre-planned vendor builds are enqueued without an awaiter; nothing
|
|
303
274
|
// evaluates until they all settle (no-op when the pipeline is empty).
|
|
304
275
|
await drainPreplanBuilds()
|
|
@@ -312,7 +283,7 @@ export async function importDevModule<T>(
|
|
|
312
283
|
// the real render a fresh module identity, so speculative work can never poison the request.
|
|
313
284
|
const retryHref = nextWarmRetryHref(href)
|
|
314
285
|
warmRetryHrefs.set(href, retryHref)
|
|
315
|
-
|
|
286
|
+
forgetModuleEvalError(importHref, error)
|
|
316
287
|
await retryHref
|
|
317
288
|
}
|
|
318
289
|
throw error
|
|
@@ -338,6 +309,7 @@ const moduleCaches = new WeakMap<ResolvedConfig, DevModuleCache>()
|
|
|
338
309
|
export function devModuleGraph(config: ResolvedConfig): DevModuleCache {
|
|
339
310
|
const existing = moduleCaches.get(config)
|
|
340
311
|
if (existing) return existing
|
|
312
|
+
if (isReleaseCompile()) releaseAnchors.set(cacheRoot(config.outPath), portableAnchors(config))
|
|
341
313
|
const cache = devModuleCache(config, {
|
|
342
314
|
compileKey: devCompileKey(config),
|
|
343
315
|
edges: (file, source) => graphEdges(config, file, source),
|
|
@@ -429,6 +401,14 @@ function devAliasKeys(config: ResolvedConfig) {
|
|
|
429
401
|
return keys
|
|
430
402
|
}
|
|
431
403
|
|
|
404
|
+
/** The out dir is compiled output, save the pages sources a build materializes into it. */
|
|
405
|
+
function isCompiledOutput(config: ResolvedConfig, file: string) {
|
|
406
|
+
return (
|
|
407
|
+
isInside(config.outPath, file) &&
|
|
408
|
+
!isInside(path.join(config.outRootPath, 'pnext-pages-compat'), file)
|
|
409
|
+
)
|
|
410
|
+
}
|
|
411
|
+
|
|
432
412
|
/**
|
|
433
413
|
* Source edges the graph hash follows. A superset of the compiled graph is safe - it only widens what
|
|
434
414
|
* a save invalidates - but a subset would leave a dependent holding a name that no longer describes
|
|
@@ -444,7 +424,7 @@ function graphEdges(config: ResolvedConfig, file: string, source: string) {
|
|
|
444
424
|
const resolved = resolveLocalImport(config, file, sourcePath.replace(/\?.*$/, ''))
|
|
445
425
|
const isLocalSource = sourcePath.startsWith('.') || path.isAbsolute(sourcePath)
|
|
446
426
|
// Compiled output is never a source of the graph that produced it.
|
|
447
|
-
if (resolved &&
|
|
427
|
+
if (resolved && isCompiledOutput(config, resolved)) continue
|
|
448
428
|
if (resolved && (isLocalSource || isInside(config.workspaceRoot, resolved))) {
|
|
449
429
|
imports.push(path.resolve(resolved))
|
|
450
430
|
continue
|
|
@@ -547,6 +527,9 @@ export async function devServerModuleHref(
|
|
|
547
527
|
_version?: string,
|
|
548
528
|
moduleOptions: DevServerModuleOptions = {},
|
|
549
529
|
) {
|
|
530
|
+
const served = productionRelease(config)
|
|
531
|
+
if (served)
|
|
532
|
+
return releaseModuleHref(served, 'server', moduleOptions.conditionTarget ?? 'server', file)
|
|
550
533
|
const conditionTarget = pagesLayerConditionTarget(
|
|
551
534
|
config,
|
|
552
535
|
file,
|
|
@@ -585,6 +568,8 @@ export async function devClientModuleHref(
|
|
|
585
568
|
_version?: string,
|
|
586
569
|
serverTarget?: ServerBundleTarget,
|
|
587
570
|
) {
|
|
571
|
+
const served = productionRelease(config)
|
|
572
|
+
if (served) return releaseModuleHref(served, 'client', serverTarget ?? 'server', file)
|
|
588
573
|
const conditionTarget = clientLayerConditionTarget(config, file, serverTarget ?? 'server')
|
|
589
574
|
const throughPackage = await packageClientModuleHref(config, file, conditionTarget)
|
|
590
575
|
if (throughPackage) return throughPackage
|
|
@@ -1414,30 +1399,252 @@ export function setEmitCompiledSpecifiersManifest(enabled: boolean) {
|
|
|
1414
1399
|
}
|
|
1415
1400
|
}
|
|
1416
1401
|
|
|
1402
|
+
// A production build compiles for its release: `.js` artifact names, one asset-context link per
|
|
1403
|
+
// directory, core CSS module class maps. Dev keeps its own compile.
|
|
1404
|
+
// A build's sources do not change under it, so each directory's asset context links once; dev relinks.
|
|
1405
|
+
const linkedAssetContexts = new Map<string, Promise<void>>()
|
|
1406
|
+
|
|
1407
|
+
/** @internal The build sets this for its own duration. Returns a restore function. */
|
|
1408
|
+
export function setReleaseCompile(enabled: boolean) {
|
|
1409
|
+
const previous = isReleaseCompile()
|
|
1410
|
+
setReleaseCompileFlag(enabled)
|
|
1411
|
+
// Each build starts from an emptied out dir, so nothing linked or stubbed before still stands.
|
|
1412
|
+
linkedAssetContexts.clear()
|
|
1413
|
+
assetStubs.clear()
|
|
1414
|
+
releaseAnchors.clear()
|
|
1415
|
+
packageCandidates.clear()
|
|
1416
|
+
packageSpecifiers.clear()
|
|
1417
|
+
clearReleaseDependencyLog()
|
|
1418
|
+
return () => setReleaseCompileFlag(previous)
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1417
1421
|
/** Sidecar suffix for a compiled artifact's recorded specifiers. */
|
|
1418
1422
|
export const compiledSpecifiersManifestSuffix = '.pnext-specifiers.json'
|
|
1419
1423
|
|
|
1420
1424
|
const compiledScriptFilePattern = /\.(?:m?js|cjs|jsx|tsx?)$/
|
|
1421
1425
|
|
|
1426
|
+
/** Where a release may move with its app: the root, its node_modules links, the workspace. */
|
|
1427
|
+
interface PortableAnchors {
|
|
1428
|
+
roots: string[]
|
|
1429
|
+
/** Real directory -> the logical path the app's node_modules names it by. */
|
|
1430
|
+
links: Map<string, string>
|
|
1431
|
+
}
|
|
1432
|
+
|
|
1433
|
+
const releaseAnchors = new Map<string, PortableAnchors>()
|
|
1434
|
+
|
|
1435
|
+
function portableAnchors(config: ResolvedConfig): PortableAnchors {
|
|
1436
|
+
const links = new Map<string, string>()
|
|
1437
|
+
const link = (logical: string) => {
|
|
1438
|
+
try {
|
|
1439
|
+
const real = realpathSync(logical)
|
|
1440
|
+
if (real !== logical && !links.has(real)) links.set(real, logical)
|
|
1441
|
+
} catch {
|
|
1442
|
+
// A dangling entry links nothing.
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
const nodeModules = path.join(config.root, 'node_modules')
|
|
1446
|
+
link(nodeModules)
|
|
1447
|
+
for (const name of listDirectory(nodeModules)) {
|
|
1448
|
+
const entry = path.join(nodeModules, name)
|
|
1449
|
+
if (name.startsWith('@'))
|
|
1450
|
+
for (const scoped of listDirectory(entry)) link(path.join(entry, scoped))
|
|
1451
|
+
else link(entry)
|
|
1452
|
+
}
|
|
1453
|
+
return { roots: [config.root, config.workspaceRoot], links }
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
function listDirectory(dir: string) {
|
|
1457
|
+
try {
|
|
1458
|
+
return readdirSync(dir)
|
|
1459
|
+
} catch {
|
|
1460
|
+
return []
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
|
|
1464
|
+
/**
|
|
1465
|
+
* Rewrite `file://` URLs in compiled output relative to `file`: import specifiers become relative
|
|
1466
|
+
* specifiers, and (for a release) inlined URL literals become `new URL(<relative>, import.meta.url)`.
|
|
1467
|
+
* `locate` maps an absolute target to the path to link, or undefined to leave it. A release names an
|
|
1468
|
+
* installed package file by the bare specifier that resolves back to it, so the serving install wins.
|
|
1469
|
+
*/
|
|
1470
|
+
function relocateSource(
|
|
1471
|
+
file: string,
|
|
1472
|
+
contents: string,
|
|
1473
|
+
locate: (absolute: string) => string | undefined,
|
|
1474
|
+
installed: (absolute: string) => boolean = () => false,
|
|
1475
|
+
) {
|
|
1476
|
+
const relativeTo = (target: string) => {
|
|
1477
|
+
const relative = toPosixPath(path.relative(path.dirname(file), target))
|
|
1478
|
+
return relative.startsWith('.') ? relative : `./${relative}`
|
|
1479
|
+
}
|
|
1480
|
+
const edits: { start: number; end: number; value: string }[] = []
|
|
1481
|
+
for (const found of outputSpecifiers(contents)) {
|
|
1482
|
+
const { sourcePath, hash } = splitHash(found.value)
|
|
1483
|
+
const url = sourcePath.startsWith('file://')
|
|
1484
|
+
// A release also re-links plain absolute specifiers (a bundled `require('/abs/path')`).
|
|
1485
|
+
if (!url && !(isReleaseCompile() && path.isAbsolute(sourcePath))) continue
|
|
1486
|
+
const absolute = url ? fileURLToPath(sourcePath) : sourcePath
|
|
1487
|
+
const target = locate(absolute)
|
|
1488
|
+
const bare = isReleaseCompile() && installed(absolute) && packageSpecifier(file, absolute)
|
|
1489
|
+
const value = bare || (target && relativeTo(target))
|
|
1490
|
+
if (!value) continue
|
|
1491
|
+
const query = url ? new URL(sourcePath).search : ''
|
|
1492
|
+
edits.push({
|
|
1493
|
+
start: found.start,
|
|
1494
|
+
end: found.end,
|
|
1495
|
+
value: JSON.stringify(`${value}${query}${hash}`),
|
|
1496
|
+
})
|
|
1497
|
+
}
|
|
1498
|
+
const specifiers = spliceSource(contents, edits)
|
|
1499
|
+
if (!isReleaseCompile()) return specifiers
|
|
1500
|
+
// Path literals (client-reference targets, module URLs) resolve beside the artifact at runtime.
|
|
1501
|
+
return specifiers.replace(
|
|
1502
|
+
/(?<!\\)"((?:file:\/\/)?\/[^"\\\n]+)"(\s*:)?/g,
|
|
1503
|
+
(literal, value: string, key: string | undefined) => {
|
|
1504
|
+
const url = value.startsWith('file:')
|
|
1505
|
+
const target = locate(url ? fileURLToPath(value) : value)
|
|
1506
|
+
if (!target) return literal
|
|
1507
|
+
const href = `new URL(${JSON.stringify(relativeTo(target))}, import.meta.url)`
|
|
1508
|
+
const expression = url ? `${href}.href` : `decodeURIComponent(${href}.pathname)`
|
|
1509
|
+
return key ? `[${expression}]${key}` : expression
|
|
1510
|
+
},
|
|
1511
|
+
)
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
const isInstalled = (file: string) => file.includes(`${path.sep}node_modules${path.sep}`)
|
|
1515
|
+
const packageCandidates = new Map<string, string | null>()
|
|
1516
|
+
const packageSpecifiers = new Map<string, boolean>()
|
|
1517
|
+
|
|
1518
|
+
/** The bare specifier that resolves from `from` back to installed `file`, if one does. */
|
|
1519
|
+
function packageSpecifier(from: string, file: string) {
|
|
1520
|
+
const candidate = packageCandidate(file)
|
|
1521
|
+
// One miss settles it: the fallback path is always correct, only less portable.
|
|
1522
|
+
if (!candidate || packageSpecifiers.get(candidate) === false) return undefined
|
|
1523
|
+
const key = `${path.dirname(from)}\0${candidate}`
|
|
1524
|
+
let resolves = packageSpecifiers.get(key)
|
|
1525
|
+
if (resolves === undefined) {
|
|
1526
|
+
try {
|
|
1527
|
+
resolves = realpathSync(Bun.resolveSync(candidate, path.dirname(from))) === realpathSync(file)
|
|
1528
|
+
} catch {
|
|
1529
|
+
resolves = false
|
|
1530
|
+
}
|
|
1531
|
+
packageSpecifiers.set(key, resolves)
|
|
1532
|
+
if (!resolves) packageSpecifiers.set(candidate, false)
|
|
1533
|
+
}
|
|
1534
|
+
return resolves ? candidate : undefined
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
/** How installed `file` is named bare: the exports subpath that targets it, else its deep path. */
|
|
1538
|
+
function packageCandidate(file: string) {
|
|
1539
|
+
let candidate = packageCandidates.get(file)
|
|
1540
|
+
if (candidate !== undefined) return candidate
|
|
1541
|
+
candidate = null
|
|
1542
|
+
const packageDir = nodeModulesPackageDir(file)
|
|
1543
|
+
const name = packageDir && packageNameOfDirectory(packageDir)
|
|
1544
|
+
if (packageDir && name) {
|
|
1545
|
+
const subpath = `./${toPosixPath(path.relative(packageDir, file))}`
|
|
1546
|
+
const exports = packageExportsMap(packageDir)
|
|
1547
|
+
if (!exports) candidate = `${name}/${subpath.slice(2)}`
|
|
1548
|
+
for (const [key, value] of Object.entries(exports ?? {})) {
|
|
1549
|
+
if (key.includes('*') || !exportTargets(value).includes(subpath)) continue
|
|
1550
|
+
candidate = key === '.' ? name : `${name}/${key.slice(2)}`
|
|
1551
|
+
break
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
packageCandidates.set(file, candidate)
|
|
1555
|
+
return candidate
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
/** A package's exports as a subpath map (`"."` for a bare entry), or undefined when it has none. */
|
|
1559
|
+
function packageExportsMap(packageDir: string): Record<string, unknown> | undefined {
|
|
1560
|
+
try {
|
|
1561
|
+
const { exports } = JSON.parse(readFileSync(path.join(packageDir, 'package.json'), 'utf8')) as {
|
|
1562
|
+
exports?: unknown
|
|
1563
|
+
}
|
|
1564
|
+
if (exports === undefined || exports === null) return undefined
|
|
1565
|
+
if (typeof exports !== 'object' || Array.isArray(exports)) return { '.': exports }
|
|
1566
|
+
return Object.keys(exports).some(key => key.startsWith('.'))
|
|
1567
|
+
? (exports as Record<string, unknown>)
|
|
1568
|
+
: { '.': exports }
|
|
1569
|
+
} catch {
|
|
1570
|
+
return undefined
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
function exportTargets(value: unknown): string[] {
|
|
1575
|
+
if (typeof value === 'string') return [value]
|
|
1576
|
+
if (Array.isArray(value)) return value.flatMap(exportTargets)
|
|
1577
|
+
return value && typeof value === 'object' ? Object.values(value).flatMap(exportTargets) : []
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
/** A release bundle emitted outside the module graph, rewritten to reach its targets relatively. */
|
|
1581
|
+
export function relocateReleaseBundle(config: ResolvedConfig, file: string, contents: string) {
|
|
1582
|
+
const anchors = portableAnchors(config)
|
|
1583
|
+
return relocateSource(file, contents, absolute => portableTarget(anchors, absolute), isInstalled)
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
/** A release artifact written outside writeCompiledFile (vendor bundles), re-linked like one. */
|
|
1587
|
+
export function releaseArtifactSource(file: string, contents: string) {
|
|
1588
|
+
if (!isReleaseCompile()) return contents
|
|
1589
|
+
const cacheRoot = [...releaseAnchors.keys()].find(root => isInside(root, file))
|
|
1590
|
+
const anchors = cacheRoot && releaseAnchors.get(cacheRoot)
|
|
1591
|
+
if (!cacheRoot || !anchors) return contents
|
|
1592
|
+
return relocateSource(
|
|
1593
|
+
file,
|
|
1594
|
+
releaseInputComments(contents),
|
|
1595
|
+
absolute => (isInside(cacheRoot, absolute) ? absolute : portableTarget(anchors, absolute)),
|
|
1596
|
+
absolute => !isInside(cacheRoot, absolute) && isInstalled(absolute),
|
|
1597
|
+
)
|
|
1598
|
+
}
|
|
1599
|
+
|
|
1600
|
+
/**
|
|
1601
|
+
* esbuild's per-input `// <path>` comments, cut to the file name (or its `node_modules/` path, which
|
|
1602
|
+
* names a vendored font caller): their paths walk the build machine.
|
|
1603
|
+
*/
|
|
1604
|
+
function releaseInputComments(contents: string) {
|
|
1605
|
+
return contents.replace(/^\/\/ (?:[\w-]+:)?\.{0,2}\/[^\s]*$/gm, comment => {
|
|
1606
|
+
const installed = comment.indexOf('node_modules/')
|
|
1607
|
+
return `// ${installed === -1 ? path.basename(comment) : comment.slice(installed)}`
|
|
1608
|
+
})
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
/** `target` as a path a moved release still reaches: through the app's own tree, never the machine's. */
|
|
1612
|
+
function portableTarget(anchors: PortableAnchors, target: string) {
|
|
1613
|
+
if (anchors.roots.some(root => isInside(root, target))) return target
|
|
1614
|
+
// Nearest linked ancestor first, so a package link wins over the node_modules link that holds it.
|
|
1615
|
+
for (let dir = path.dirname(target); dir !== path.dirname(dir); dir = path.dirname(dir)) {
|
|
1616
|
+
const logical = anchors.links.get(dir)
|
|
1617
|
+
if (logical) return path.join(logical, path.relative(dir, target))
|
|
1618
|
+
}
|
|
1619
|
+
return undefined
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
const compiledJsonModule = /\.json\.js(?:[?#]|$)/
|
|
1623
|
+
|
|
1422
1624
|
async function writeCompiledFile(file: string, contents: string) {
|
|
1423
1625
|
const profileRoot = compiledArtifactProfileRoot(file)
|
|
1424
|
-
|
|
1626
|
+
const anchors =
|
|
1627
|
+
profileRoot && isReleaseCompile() ? releaseAnchors.get(path.dirname(profileRoot)) : undefined
|
|
1628
|
+
if (
|
|
1629
|
+
profileRoot &&
|
|
1630
|
+
(anchors
|
|
1631
|
+
? /["'](?:file:\/\/)?\/|^\/\/ (?:[\w-]+:)?\.{0,2}\//m.test(contents)
|
|
1632
|
+
: contents.includes('file://'))
|
|
1633
|
+
) {
|
|
1425
1634
|
const cacheRoot = path.dirname(profileRoot)
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
edits.push({
|
|
1434
|
-
start: found.start,
|
|
1435
|
-
end: found.end,
|
|
1436
|
-
value: JSON.stringify(`${relative.startsWith('.') ? relative : `./${relative}`}${hash}`),
|
|
1437
|
-
})
|
|
1438
|
-
}
|
|
1439
|
-
contents = spliceSource(contents, edits)
|
|
1635
|
+
contents = relocateSource(
|
|
1636
|
+
file,
|
|
1637
|
+
anchors ? releaseInputComments(contents) : contents,
|
|
1638
|
+
absolute =>
|
|
1639
|
+
isInside(cacheRoot, absolute) ? absolute : anchors && portableTarget(anchors, absolute),
|
|
1640
|
+
absolute => !isInside(cacheRoot, absolute) && isInstalled(absolute),
|
|
1641
|
+
)
|
|
1440
1642
|
}
|
|
1643
|
+
// A compiled `.json.js` is JS: a release loads it natively, where `type: "json"` would parse it as JSON.
|
|
1644
|
+
if (anchors && contents.includes('.json.js'))
|
|
1645
|
+
contents = stripJsonImportAttributes(contents, file, specifier =>
|
|
1646
|
+
compiledJsonModule.test(specifier),
|
|
1647
|
+
)
|
|
1441
1648
|
await writeFileAtomic(file, contents)
|
|
1442
1649
|
noteDevArtifactWritten(file)
|
|
1443
1650
|
if (emitCompiledSpecifiersManifest && compiledScriptFilePattern.test(file)) {
|
|
@@ -1497,7 +1704,7 @@ function missingCompiledArtifact(entry: string): string | undefined {
|
|
|
1497
1704
|
try {
|
|
1498
1705
|
target = sourcePath.startsWith('file://')
|
|
1499
1706
|
? fileURLToPath(sourcePath)
|
|
1500
|
-
: path.resolve(path.dirname(file), sourcePath)
|
|
1707
|
+
: path.resolve(path.dirname(file), splitResourceQuery(sourcePath).path)
|
|
1501
1708
|
} catch {
|
|
1502
1709
|
return sourcePath
|
|
1503
1710
|
}
|
|
@@ -1668,6 +1875,9 @@ async function writeDevModuleUncached(
|
|
|
1668
1875
|
clientLayerConditionTarget(config, file, options.conditionTarget),
|
|
1669
1876
|
)
|
|
1670
1877
|
: options
|
|
1878
|
+
if (effectiveOptions !== options) {
|
|
1879
|
+
noteReleaseModuleLayer(config, outFile, 'client', effectiveOptions.conditionTarget)
|
|
1880
|
+
}
|
|
1671
1881
|
// The asset-context link walk is pure I/O against directories nothing below
|
|
1672
1882
|
// reads, so it overlaps the shaking/scan/child-compile work and is only
|
|
1673
1883
|
// awaited before the write.
|
|
@@ -2212,7 +2422,7 @@ async function assetStubModule(config: ResolvedConfig, resolved: string, profile
|
|
|
2212
2422
|
if (existing) return existing
|
|
2213
2423
|
const next = (async () => {
|
|
2214
2424
|
const contents =
|
|
2215
|
-
|
|
2425
|
+
(await serverCssModuleSource(config, resolved)) ??
|
|
2216
2426
|
(isCssFile(base)
|
|
2217
2427
|
? ''
|
|
2218
2428
|
: isStaticImageFile(base)
|
|
@@ -2309,7 +2519,7 @@ function serverAssetPlugin(config: ResolvedConfig): Plugin {
|
|
|
2309
2519
|
build.onLoad({ filter: /.*/, namespace: serverAssetNamespace }, async args => {
|
|
2310
2520
|
// Registry-provided CSS modules (e.g. *.module.scss) export their class
|
|
2311
2521
|
// map on the server instead of the empty-asset stub.
|
|
2312
|
-
const cssModule =
|
|
2522
|
+
const cssModule = await serverCssModuleSource(config, args.path)
|
|
2313
2523
|
return {
|
|
2314
2524
|
contents:
|
|
2315
2525
|
cssModule ??
|
|
@@ -2347,7 +2557,7 @@ async function resolveDevModuleSpecifier(
|
|
|
2347
2557
|
if (
|
|
2348
2558
|
options.stubClientImports &&
|
|
2349
2559
|
!isCssFile(target) &&
|
|
2350
|
-
!
|
|
2560
|
+
!isCompiledOutput(config, target) &&
|
|
2351
2561
|
existsSync(target) &&
|
|
2352
2562
|
(await fileHasUseClientDirective(target))
|
|
2353
2563
|
) {
|
|
@@ -2374,6 +2584,23 @@ async function resolveDevModuleSpecifier(
|
|
|
2374
2584
|
|
|
2375
2585
|
const { sourcePath, hash } = splitHash(specifier)
|
|
2376
2586
|
|
|
2587
|
+
// A release compiles an unclaimed `?query` import's base module; the query keeps its own instance.
|
|
2588
|
+
const queried = splitResourceQuery(sourcePath)
|
|
2589
|
+
if (
|
|
2590
|
+
isReleaseCompile() &&
|
|
2591
|
+
queried.query &&
|
|
2592
|
+
sourcePath.startsWith('.') &&
|
|
2593
|
+
compiledScriptFilePattern.test(queried.path)
|
|
2594
|
+
) {
|
|
2595
|
+
const from = importer && !importer.startsWith('<') ? importer : file
|
|
2596
|
+
const base = resolveImport(config.root, from, queried.path, config.workspaceRoot)
|
|
2597
|
+
if (base && isInside(config.workspaceRoot, base)) {
|
|
2598
|
+
await writeDevModule(config, base, visited, options)
|
|
2599
|
+
const href = pathToFileHref(await devModulePath(config, base, options))
|
|
2600
|
+
return { path: `${href}${queried.query}${hash}`, external: true }
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2377
2604
|
const compatAlias =
|
|
2378
2605
|
pagesCompatSourceAlias(config, specifier, importer, options) ?? options.aliases[specifier]
|
|
2379
2606
|
if (compatAlias) {
|
|
@@ -2893,7 +3120,7 @@ function localImportTargets(
|
|
|
2893
3120
|
// vendor bundle) are already compiled modules Bun imports directly. Feeding one back through the
|
|
2894
3121
|
// pipeline compiles it a SECOND time, splitting module identity and pulling artifact names into the
|
|
2895
3122
|
// source graph, where every boot's fresh names look like edits.
|
|
2896
|
-
if (resolved && !
|
|
3123
|
+
if (resolved && !isCompiledOutput(config, resolved)) {
|
|
2897
3124
|
targets.push({
|
|
2898
3125
|
target: resolved,
|
|
2899
3126
|
isLocalSource: sourcePath.startsWith('.') || path.isAbsolute(sourcePath),
|
|
@@ -2941,9 +3168,20 @@ async function writeClientReferenceModules(
|
|
|
2941
3168
|
return { specifiers, files }
|
|
2942
3169
|
}
|
|
2943
3170
|
|
|
3171
|
+
/** How a release's stub names its source portably (see ClientReferenceModuleOptions.portable). */
|
|
3172
|
+
function portableReference(file: string, sourceFile: string) {
|
|
3173
|
+
const profileRoot = compiledArtifactProfileRoot(file)
|
|
3174
|
+
const anchors = isReleaseCompile() && profileRoot && releaseAnchors.get(path.dirname(profileRoot))
|
|
3175
|
+
const target = anchors && portableTarget(anchors, sourceFile)
|
|
3176
|
+
return target ? { portable: { from: file, target, real: target !== sourceFile } } : {}
|
|
3177
|
+
}
|
|
3178
|
+
|
|
2944
3179
|
async function writeClientReferenceModule(file: string, sourceFile: string, exportNames: string[]) {
|
|
2945
3180
|
await mkdir(path.dirname(file), { recursive: true })
|
|
2946
|
-
await writeCompiledFile(
|
|
3181
|
+
await writeCompiledFile(
|
|
3182
|
+
file,
|
|
3183
|
+
clientReferenceModuleSource(sourceFile, exportNames, portableReference(file, sourceFile)),
|
|
3184
|
+
)
|
|
2947
3185
|
}
|
|
2948
3186
|
|
|
2949
3187
|
async function fileHasUseClientDirective(file: string) {
|
|
@@ -2964,6 +3202,20 @@ function isInside(root: string, file: string) {
|
|
|
2964
3202
|
return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative))
|
|
2965
3203
|
}
|
|
2966
3204
|
|
|
3205
|
+
/** Where an App Router layer's release modules compile to. */
|
|
3206
|
+
export function releaseLayerArtifactDir(config: ResolvedConfig, layer: ReleaseDependencyLayer) {
|
|
3207
|
+
const profile =
|
|
3208
|
+
layer === 'client:client'
|
|
3209
|
+
? devModuleProfile(clientLayerOptions(config))
|
|
3210
|
+
: devModuleProfile({
|
|
3211
|
+
profile: 'compat',
|
|
3212
|
+
conditionTarget: 'server',
|
|
3213
|
+
externalLoadTarget: externalLoadTargetForConditionTarget('server'),
|
|
3214
|
+
reactServerLayer: true,
|
|
3215
|
+
} as DevModuleOptions)
|
|
3216
|
+
return path.join(cacheRoot(config.outPath), `modules-${profile}`)
|
|
3217
|
+
}
|
|
3218
|
+
|
|
2967
3219
|
function devModuleProfile(options: DevModuleOptions) {
|
|
2968
3220
|
if (options.profile === 'client') {
|
|
2969
3221
|
// Pages-router SSR layers ('pages'/'pages-edge') resolve package exports
|
|
@@ -2989,7 +3241,13 @@ function devServerPath(config: ResolvedConfig, file: string, profile: string, ha
|
|
|
2989
3241
|
// A compiled `.json` module is JS (esbuild's json loader wraps it in exports),
|
|
2990
3242
|
// so it must not keep the `.json` name — the runtime would parse the artifact
|
|
2991
3243
|
// as JSON. Keeping the source name in front of `.js` keeps it collision-free.
|
|
2992
|
-
|
|
3244
|
+
// Build output names compiled scripts `.js`, so production imports them without a TS/MDX loader.
|
|
3245
|
+
const outExt =
|
|
3246
|
+
ext === '.json'
|
|
3247
|
+
? '.json.js'
|
|
3248
|
+
: isReleaseCompile() && /\.(?:[jt]sx?|mdx?)$/.test(ext)
|
|
3249
|
+
? '.js'
|
|
3250
|
+
: ext
|
|
2993
3251
|
return path.join(
|
|
2994
3252
|
cacheRoot(config.outPath),
|
|
2995
3253
|
profile === 'server' ? 'modules' : `modules-${profile}`,
|
|
@@ -3082,6 +3340,15 @@ function isCssFile(file: string) {
|
|
|
3082
3340
|
return file.endsWith('.css')
|
|
3083
3341
|
}
|
|
3084
3342
|
|
|
3343
|
+
/** A CSS module's class map as a build's server output imports it; core's plain CSS modules map here. */
|
|
3344
|
+
async function serverCssModuleSource(config: ResolvedConfig, file: string) {
|
|
3345
|
+
const registered = getCssExtensions().loadCssModuleForClient(file)
|
|
3346
|
+
const coreBuild = isReleaseCompile() && !reactCompatEnabled(config)
|
|
3347
|
+
if (registered !== undefined || !coreBuild || !file.endsWith('.module.css')) return registered
|
|
3348
|
+
const { cssModuleMapping } = await import('../css/build')
|
|
3349
|
+
return `export default ${JSON.stringify(await cssModuleMapping(file))};`
|
|
3350
|
+
}
|
|
3351
|
+
|
|
3085
3352
|
function isStaticImageFile(file: string) {
|
|
3086
3353
|
return /\.(?:png|jpe?g|gif|webp|avif|svg|ico|bmp)(?:$|[?#])/.test(file)
|
|
3087
3354
|
}
|
|
@@ -3133,9 +3400,20 @@ function resolveLocalImport(config: ResolvedConfig, fromFile: string, specifier:
|
|
|
3133
3400
|
|
|
3134
3401
|
async function linkAssetContext(config: ResolvedConfig, file: string, profile: string) {
|
|
3135
3402
|
if (!isInside(config.root, file)) return
|
|
3136
|
-
const sourceDirs = ancestorDirs(config.root, path.dirname(file))
|
|
3403
|
+
const sourceDirs = ancestorDirs(config.root, path.dirname(file)).filter(
|
|
3404
|
+
dir => !isCompiledOutput(config, dir),
|
|
3405
|
+
)
|
|
3137
3406
|
await Promise.all(
|
|
3138
|
-
sourceDirs.map(sourceDir =>
|
|
3407
|
+
sourceDirs.map(sourceDir => {
|
|
3408
|
+
if (!isReleaseCompile()) return linkDirectoryAssetContext(config, sourceDir, profile)
|
|
3409
|
+
const key = `${config.outPath}\0${profile}\0${sourceDir}`
|
|
3410
|
+
let linked = linkedAssetContexts.get(key)
|
|
3411
|
+
if (!linked) {
|
|
3412
|
+
linked = linkDirectoryAssetContext(config, sourceDir, profile)
|
|
3413
|
+
linkedAssetContexts.set(key, linked)
|
|
3414
|
+
}
|
|
3415
|
+
return linked
|
|
3416
|
+
}),
|
|
3139
3417
|
)
|
|
3140
3418
|
}
|
|
3141
3419
|
|
|
@@ -3168,6 +3446,14 @@ async function linkDirectoryAssetContext(
|
|
|
3168
3446
|
if (!assetContextEntry(config, sourceDir, entry.name, entry.isDirectory())) return
|
|
3169
3447
|
const source = path.join(sourceDir, entry.name)
|
|
3170
3448
|
const target = path.join(targetDir, entry.name)
|
|
3449
|
+
// A linked directory below the root (pages-compat's `source-pages`) compiles on its own path:
|
|
3450
|
+
// staging the link would write its artifacts through it, into the source tree.
|
|
3451
|
+
if (
|
|
3452
|
+
entry.isSymbolicLink() &&
|
|
3453
|
+
sourceDir !== config.root &&
|
|
3454
|
+
statSync(source, { throwIfNoEntry: false })?.isDirectory()
|
|
3455
|
+
)
|
|
3456
|
+
return
|
|
3171
3457
|
// Root-level sibling asset directories are mirrored, not symlinked wholesale: a `dir` symlink
|
|
3172
3458
|
// would make every path beneath it - including code modules that must be compiled through the
|
|
3173
3459
|
// alias transform - resolve straight back to raw source, shadowing the staged compile.
|
|
@@ -3208,9 +3494,11 @@ async function stagedManifestSource(file: string) {
|
|
|
3208
3494
|
async function linkOrCopyAsset(source: string, target: string) {
|
|
3209
3495
|
const resolvedSource = path.resolve(source)
|
|
3210
3496
|
// Concurrent walkers keep a repaired link and remove only the stale target.
|
|
3497
|
+
// A release links relatively: moved with its app, it names no build-machine path.
|
|
3498
|
+
const linkTarget = isReleaseCompile() ? path.relative(path.dirname(target), source) : source
|
|
3211
3499
|
for (let attempt = 0; attempt < 4; attempt += 1) {
|
|
3212
3500
|
try {
|
|
3213
|
-
await symlink(
|
|
3501
|
+
await symlink(linkTarget, target, 'file')
|
|
3214
3502
|
return
|
|
3215
3503
|
} catch (error) {
|
|
3216
3504
|
if ((error as NodeJS.ErrnoException).code !== 'EEXIST') break
|
|
@@ -3266,7 +3554,8 @@ function assetContextEntry(
|
|
|
3266
3554
|
'pages',
|
|
3267
3555
|
'public',
|
|
3268
3556
|
'node_modules',
|
|
3269
|
-
|
|
3557
|
+
// The out dir's top segment (`dist` for `dist/build`): mirroring it would recurse into its own output.
|
|
3558
|
+
path.relative(config.root, config.outRootPath).split(path.sep)[0],
|
|
3270
3559
|
]).has(name)
|
|
3271
3560
|
}
|
|
3272
3561
|
|