@wular/pnext 0.0.3 → 0.0.6
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/README.md +11 -11
- package/bin/pnext +1 -1
- package/config/lint/base.js +7 -7
- package/config/ts/base.json +2 -4
- package/config/ts/react.json +2 -6
- package/package.json +23 -2
- package/reference/compat.md +1 -1
- package/reference/config.md +2 -2
- package/reference/css.md +13 -9
- package/reference/dev.md +1 -1
- package/reference/metadata.md +7 -7
- package/reference/navigation.md +35 -28
- package/reference/performance.md +70 -70
- package/reference/rendering.md +17 -17
- package/reference/routing.md +17 -17
- package/reference/typegen.md +12 -8
- package/src/api/cache.ts +36 -37
- package/src/api/client-cache.ts +2 -2
- package/src/api/client-navigation.ts +113 -109
- package/src/api/dynamic.tsx +58 -55
- package/src/api/link.tsx +49 -52
- package/src/api/navigation.ts +59 -58
- package/src/api/server.ts +152 -144
- package/src/api/suspense.ts +4 -4
- package/src/cli/adapters/vercel-warm.ts +126 -121
- package/src/cli/adapters/vercel.ts +437 -443
- package/src/cli/analyze.ts +333 -144
- package/src/cli/{named-bin.ts → boot/named-bin.ts} +37 -37
- package/src/cli/{boot-trace.ts → boot/trace.ts} +10 -10
- package/src/cli/build.ts +976 -978
- package/src/cli/create.ts +71 -63
- package/src/cli/dev.ts +116 -116
- package/src/cli/index.ts +88 -85
- package/src/cli/migrate/package-json.ts +73 -71
- package/src/cli/migrate/report.ts +32 -33
- package/src/cli/migrate/{index.ts → run.ts} +48 -49
- package/src/cli/migrate/scan.ts +46 -46
- package/src/cli/migrate/spinner.ts +9 -9
- package/src/cli/migrate/tsconfig.ts +35 -35
- package/src/cli/{server-entry.ts → serve/entry.ts} +57 -57
- package/src/cli/{request-pipeline.ts → serve/pipeline.ts} +386 -394
- package/src/cli/{serve-ui.ts → serve/ui.ts} +47 -47
- package/src/cli/start.ts +65 -66
- package/src/{typegen.ts → cli/typegen.ts} +59 -59
- package/src/client/build.ts +794 -768
- package/src/client/chunk-fold.ts +245 -240
- package/src/client/{paths.ts → chunk-name.ts} +6 -6
- package/src/client/entry.ts +162 -147
- package/src/client/prebuilt.ts +231 -223
- package/src/client/profile.ts +29 -29
- package/src/client/react-compiler.ts +20 -15
- package/src/client/{compat-surface.ts → react-tier.ts} +64 -64
- package/src/client/reference-stub.ts +51 -51
- package/src/client/reference.ts +19 -19
- package/src/{api → client}/router/events.ts +17 -17
- package/src/{api → client}/router/history.ts +16 -16
- package/src/{api → client}/router/hub.ts +52 -53
- package/src/{api/router.ts → client/router/index.ts} +61 -60
- package/src/{api → client}/router/policies.ts +24 -24
- package/src/{api → client}/router/runtime.ts +1988 -1961
- package/src/{api → client}/router/types.ts +93 -98
- package/src/compat/actions/client-plugin.ts +42 -43
- package/src/compat/actions/client-stub.ts +14 -14
- package/src/compat/actions/{action-client.ts → client.ts} +194 -193
- package/src/compat/actions/config.ts +63 -64
- package/src/compat/actions/detect.ts +68 -68
- package/src/compat/actions/discovery.ts +105 -105
- package/src/compat/actions/{action-dispatch.ts → dispatch.ts} +277 -274
- package/src/compat/actions/early-submit.ts +1 -1
- package/src/compat/actions/endpoint.ts +198 -198
- package/src/compat/actions/extensions.ts +811 -0
- package/src/compat/actions/flight.ts +23 -23
- package/src/compat/actions/form-state.ts +34 -34
- package/src/compat/actions/hoist.ts +382 -236
- package/src/compat/actions/ids.ts +7 -12
- package/src/compat/actions/index.ts +8 -8
- package/src/compat/actions/instances.ts +46 -46
- package/src/compat/actions/origin.ts +47 -48
- package/src/compat/actions/protocol.ts +22 -22
- package/src/compat/actions/registry.ts +19 -19
- package/src/compat/{misc/action-return.ts → actions/return.ts} +60 -57
- package/src/compat/actions/rewrite.ts +125 -125
- package/src/compat/actions/{action-router.ts → router.ts} +10 -10
- package/src/compat/actions/serve.ts +132 -136
- package/src/compat/actions/server-tag.ts +4 -4
- package/src/compat/actions/{action-shared.ts → shared.ts} +34 -34
- package/src/compat/actions/unrecognized-error.ts +4 -4
- package/src/compat/{index.ts → aliases.ts} +112 -109
- package/src/compat/bundler/bun-externals.ts +18 -18
- package/src/compat/bundler/cjs-exports.ts +271 -223
- package/src/compat/bundler/config.ts +116 -111
- package/src/compat/bundler/externals.ts +12 -12
- package/src/compat/bundler/import-meta-url.ts +19 -19
- package/src/compat/bundler/modularize-imports.ts +36 -33
- package/src/compat/bundler/new-url-asset.ts +22 -24
- package/src/compat/bundler/optimize-package-imports.ts +111 -107
- package/src/compat/bundler/polyfill.ts +28 -28
- package/src/compat/bundler/react-compiler.ts +35 -29
- package/src/compat/bundler/react-profiler.tsx +11 -11
- package/src/compat/bundler/relay-transform.ts +48 -47
- package/src/compat/bundler/require-context.ts +119 -113
- package/src/compat/bundler/resolve-extensions.ts +19 -19
- package/src/compat/bundler/source-cache.ts +25 -25
- package/src/compat/bundler/static-imports.ts +7 -7
- package/src/compat/bundler/symlink-imports.ts +46 -46
- package/src/compat/bundler/tsconfig-paths.ts +13 -15
- package/src/compat/bundler/wasm.ts +58 -60
- package/src/compat/bundler/webpack-loaders.ts +254 -241
- package/src/compat/bundler/worker.ts +101 -104
- package/src/compat/cache/build-flags.ts +29 -29
- package/src/compat/cache/build-prerender-errors.ts +40 -44
- package/src/compat/cache/custom-handler.ts +60 -53
- package/src/compat/cache/fetch-patch.ts +240 -240
- package/src/compat/cache/handler.ts +27 -31
- package/src/compat/cache/modern-handler.ts +148 -126
- package/src/compat/cache/resume-data-cache.ts +47 -45
- package/src/compat/cache/revalidate.ts +233 -232
- package/src/compat/cache/runtime-error.ts +35 -35
- package/src/compat/cache/use-cache-transform.ts +442 -417
- package/src/compat/cache/use-cache.ts +650 -614
- package/src/compat/cache-control.ts +140 -142
- package/src/compat/client/base-path.ts +21 -20
- package/src/compat/client/css-order.ts +18 -18
- package/src/compat/client/errors/bare-boundary.ts +11 -11
- package/src/compat/client/errors/control-flow.ts +23 -23
- package/src/compat/client/errors/error-boundary.ts +61 -61
- package/src/compat/client/errors/global-error.ts +101 -91
- package/src/compat/client/errors/install.ts +71 -72
- package/src/compat/client/errors/lazy.ts +23 -23
- package/src/compat/client/errors/primitive-throw.ts +47 -45
- package/src/compat/client/errors/soft-refresh.ts +4 -4
- package/src/compat/client/link-status.ts +33 -33
- package/src/compat/client/{nav-compat-runtime.ts → nav-runtime.ts} +20 -20
- package/src/compat/client/{nav-compat.ts → nav.ts} +12 -13
- package/src/compat/client/navigation-scroll.ts +63 -63
- package/src/compat/client/optimistic-routing.ts +93 -88
- package/src/compat/client/prefetch-cache.ts +23 -24
- package/src/compat/client/route-announcer.ts +35 -35
- package/src/compat/client/segment-cache-policy.ts +20 -20
- package/src/compat/client/segment-cache.ts +309 -315
- package/src/compat/client/segment-prefetch.ts +127 -132
- package/src/compat/client/trailing-slash.ts +5 -4
- package/src/compat/css/chunking.ts +113 -116
- package/src/compat/css/inline-css.ts +21 -21
- package/src/compat/css/lightningcss.ts +37 -38
- package/src/compat/css/modules.ts +161 -175
- package/src/compat/css/nonce.ts +7 -7
- package/src/compat/css/sass-plugin.ts +18 -21
- package/src/compat/css/sass.ts +150 -152
- package/src/compat/css/styled-jsx-runtime.ts +27 -27
- package/src/compat/css/styled-jsx.ts +21 -21
- package/src/compat/edge-runtime.ts +27 -27
- package/src/compat/{adapter → export}/build-complete.ts +72 -75
- package/src/compat/export/client.ts +29 -31
- package/src/compat/export/{index.ts → emit.ts} +111 -110
- package/src/compat/export/standalone.ts +62 -54
- package/src/compat/image-optimizer/cache.ts +51 -49
- package/src/compat/image-optimizer/detect.ts +52 -52
- package/src/compat/image-optimizer/{index.ts → optimize.ts} +189 -194
- package/src/compat/image-optimizer/source.ts +77 -80
- package/src/compat/lifecycle/after-scope.ts +26 -26
- package/src/compat/lifecycle/after.ts +48 -45
- package/src/compat/lifecycle/error-funnel.ts +98 -102
- package/src/compat/lifecycle/error-serialize.ts +30 -26
- package/src/compat/lifecycle/error-ui.ts +67 -32
- package/src/compat/lifecycle/instrumentation-client.ts +36 -38
- package/src/compat/lifecycle/instrumentation.ts +85 -85
- package/src/compat/lifecycle/node-console.ts +11 -11
- package/src/compat/lifecycle/testmode.ts +160 -132
- package/src/compat/mdx/compile.ts +60 -57
- package/src/compat/mdx/plugin.ts +11 -11
- package/src/compat/mdx/{next-mdx-stub.ts → stub.ts} +5 -5
- package/src/compat/{metadata-route-artifacts.ts → metadata-artifacts.ts} +195 -191
- package/src/compat/metadata.ts +75 -81
- package/src/compat/next/cache.ts +68 -69
- package/src/compat/next/canonical-url.ts +9 -9
- package/src/compat/next/client-cache.ts +19 -19
- package/src/compat/next/client-navigation.ts +112 -116
- package/src/compat/next/client-only.ts +1 -1
- package/src/compat/next/client-script.tsx +99 -93
- package/src/compat/next/client-server.ts +10 -10
- package/src/compat/next/config-loader.ts +176 -173
- package/src/compat/next/config.ts +7 -7
- package/src/compat/next/constants.cjs +6 -6
- package/src/compat/next/constants.ts +6 -6
- package/src/compat/next/custom-server.ts +26 -24
- package/src/compat/next/dist/client/components/app-router-headers.ts +21 -21
- package/src/compat/next/dist/server/app-render/work-unit-async-storage.external.cjs +3 -4
- package/src/compat/next/dist/server/web/spec-extension/revalidate.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-cache.ts +1 -1
- package/src/compat/next/dist/server/web/spec-extension/unstable-no-store.ts +1 -1
- package/src/compat/next/dynamic.tsx +21 -18
- package/src/compat/next/error.tsx +52 -52
- package/src/compat/next/font/cache.ts +74 -74
- package/src/compat/next/font/google.ts +2 -2
- package/src/compat/next/font/index.ts +1 -1
- package/src/compat/next/font/local.ts +3 -3
- package/src/compat/next/font/runtime-client.ts +17 -15
- package/src/compat/next/font/runtime.ts +443 -408
- package/src/compat/next/font/shared.ts +120 -108
- package/src/compat/next/form.tsx +63 -63
- package/src/compat/next/head.tsx +2 -2
- package/src/compat/next/headers.ts +103 -95
- package/src/compat/next/image/client.tsx +220 -0
- package/src/compat/next/image/config.ts +56 -58
- package/src/compat/next/image/optimizer.ts +40 -36
- package/src/compat/next/image/patterns.ts +37 -40
- package/src/compat/next/{image-props.ts → image/props.ts} +208 -202
- package/src/compat/next/image/shared.ts +65 -57
- package/src/compat/next/image/static-metadata.ts +98 -107
- package/src/compat/next/image/validate.ts +79 -88
- package/src/compat/next/image.tsx +19 -23
- package/src/compat/next/index.ts +1 -1
- package/src/compat/next/legacy-image.tsx +59 -60
- package/src/compat/next/{link-validation-transform.ts → link-transform.ts} +95 -96
- package/src/compat/next/link.tsx +158 -158
- package/src/compat/next/navigation.cjs +12 -3
- package/src/compat/next/navigation.ts +48 -50
- package/src/compat/next/offline.ts +27 -27
- package/src/compat/next/og.ts +121 -124
- package/src/compat/next/preferred-region.ts +13 -14
- package/src/compat/next/redirects.ts +58 -56
- package/src/compat/next/resource-hints.ts +73 -76
- package/src/compat/next/rewrites.ts +130 -133
- package/src/compat/next/root-params.ts +45 -45
- package/src/compat/next/{optimistic-route-state.ts → route-state.ts} +52 -52
- package/src/compat/next/router.cjs +4 -2
- package/src/compat/next/router.ts +58 -61
- package/src/compat/next/script.tsx +108 -108
- package/src/compat/next/server-only.ts +1 -1
- package/src/compat/next/server.ts +19 -19
- package/src/compat/next/svgr.ts +18 -17
- package/src/compat/next/telemetry.ts +24 -24
- package/src/compat/next/{image-usage.ts → usage.ts} +70 -39
- package/src/compat/next/user-agent.ts +53 -49
- package/src/compat/next/web-vitals.ts +22 -24
- package/src/compat/otel/api.ts +41 -41
- package/src/compat/otel/client-trace-metadata.ts +25 -27
- package/src/compat/otel/fetch-span.ts +29 -29
- package/src/compat/otel/tracer.ts +331 -331
- package/src/compat/pages/api.ts +456 -0
- package/src/compat/pages/client-plugin.ts +36 -36
- package/src/compat/pages/router-state.ts +34 -34
- package/src/compat/pages/{index.ts → router.ts} +130 -135
- package/src/compat/ppr/io.ts +12 -12
- package/src/compat/ppr/missing-root-params.ts +34 -38
- package/src/compat/ppr/root-params-scan.ts +66 -66
- package/src/compat/ppr/root-params-transform.ts +24 -26
- package/src/compat/ppr/root-params.ts +30 -30
- package/src/compat/ppr/segment-config-incompat.ts +6 -7
- package/src/compat/protocol.ts +71 -70
- package/src/compat/react/action-state.ts +47 -48
- package/src/compat/react/client-lite.ts +15 -15
- package/src/compat/react/client.ts +4 -4
- package/src/compat/react/compiler-runtime.ts +11 -11
- package/src/compat/react/dom-client.ts +44 -44
- package/src/compat/react/dom-react-server.ts +10 -16
- package/src/compat/react/dom-server.ts +10 -10
- package/src/compat/react/dom.ts +52 -52
- package/src/compat/react/hooks-extra.ts +34 -35
- package/src/compat/react/parity.ts +64 -61
- package/src/compat/react/preact.ts +81 -82
- package/src/compat/react/react-server.ts +28 -28
- package/src/compat/react/router-shim.ts +1 -1
- package/src/compat/react/server-component-use.ts +8 -8
- package/src/compat/react/server-inserted-html.ts +30 -31
- package/src/compat/react/server.ts +53 -55
- package/src/compat/react/use.ts +32 -32
- package/src/compat/react/view-transition.ts +20 -20
- package/src/compat/register/actions.ts +35 -824
- package/src/compat/register/boot.ts +41 -41
- package/src/compat/register/build-tier.ts +5 -5
- package/src/compat/register/build.ts +74 -70
- package/src/compat/register/bundler.ts +161 -156
- package/src/compat/register/cache.ts +20 -20
- package/src/compat/register/client-errors.ts +3 -3
- package/src/compat/register/config.ts +6 -6
- package/src/compat/register/css-extras.ts +30 -34
- package/src/compat/register/edge-runtime.ts +3 -3
- package/src/compat/register/errors.ts +10 -12
- package/src/compat/register/export.ts +16 -16
- package/src/compat/register/font.ts +11 -11
- package/src/compat/register/hooks.ts +2 -2
- package/src/compat/register/image.ts +40 -40
- package/src/compat/register/index.ts +59 -62
- package/src/compat/register/instrumentation-client.ts +10 -10
- package/src/compat/register/lifecycle.ts +25 -28
- package/src/compat/register/mdx.ts +10 -10
- package/src/compat/register/middleware.ts +226 -16
- package/src/compat/register/otel.ts +80 -88
- package/src/compat/register/pages-api.ts +10 -463
- package/src/compat/register/ppr.ts +16 -16
- package/src/compat/register/protocol.ts +17 -18
- package/src/compat/register/proxy.ts +49 -51
- package/src/compat/register/render.ts +79 -76
- package/src/compat/register/routing.ts +162 -159
- package/src/compat/register/segment.ts +24 -1887
- package/src/compat/register/static-image.ts +3 -3
- package/src/compat/register/{misc.ts → taint.ts} +9 -9
- package/src/compat/register/typed-routes.ts +14 -14
- package/src/compat/register/{usecache.ts → use-cache.ts} +39 -39
- package/src/compat/register/validation.ts +18 -18
- package/src/compat/segment/loading-boundary.ts +43 -45
- package/src/compat/segment/page-slot.ts +69 -69
- package/src/compat/segment/serve.ts +1884 -0
- package/src/compat/segment/tree.ts +113 -112
- package/src/compat/segment/vary-key.ts +38 -38
- package/src/compat/segment/vary-params.ts +138 -142
- package/src/compat/static-params.ts +14 -12
- package/src/compat/tsconfig-defaults.ts +87 -91
- package/src/compat/typecheck/{index.ts → check.ts} +234 -212
- package/src/compat/typecheck/worker.ts +15 -12
- package/src/compat/typed-routes/{index.ts → generate.ts} +36 -36
- package/src/compat/typed-routes/manifest.ts +174 -170
- package/src/compat/typed-routes/typegen.ts +127 -110
- package/src/compat/validation/errors.ts +16 -19
- package/src/compat/validation/prerender-diagnostics.ts +521 -504
- package/src/compat/validation/{index.ts → validate.ts} +647 -648
- package/src/compat-bootstrap.ts +16 -16
- package/src/config.ts +69 -69
- package/src/css/build.ts +230 -227
- package/src/css/postcss.ts +79 -80
- package/src/css/worker.ts +14 -15
- package/src/dev/client-actions.ts +10 -10
- package/src/dev/client-chunk-store.ts +27 -27
- package/src/dev/{client-key-cache.ts → restart/client-key.ts} +76 -76
- package/src/dev/{restart-cache.ts → restart/enabled.ts} +1 -1
- package/src/dev/{global-css-cache.ts → restart/global-css.ts} +91 -83
- package/src/dev/{node-module-bundle-cache.ts → restart/node-modules.ts} +24 -24
- package/src/dev/{route-bundle-key-cache.ts → restart/route-bundle-key.ts} +53 -53
- package/src/dev/{route-facts-cache.ts → restart/route-facts.ts} +82 -82
- package/src/dev/server.ts +804 -820
- package/src/env.ts +46 -43
- package/src/extensions.ts +491 -478
- package/src/index.ts +8 -8
- package/src/internal.ts +20 -23
- package/src/{islands → render}/boundary-error.ts +3 -3
- package/src/render/hooks.ts +71 -71
- package/src/render/island-context.ts +14 -14
- package/src/render/metadata.ts +310 -310
- package/src/{ppr-postpone.ts → render/postpone.ts} +5 -5
- package/src/{ppr.ts → render/ppr.ts} +244 -245
- package/src/render/renderer.ts +2076 -2082
- package/src/render/resource-hints.ts +16 -17
- package/src/render/slots.tsx +224 -235
- package/src/{islands → render}/static-children.ts +9 -12
- package/src/{islands → render}/static-slots.ts +37 -37
- package/src/{cache/context.ts → request/cache.ts} +20 -20
- package/src/request/context.ts +107 -107
- package/src/{dynamic/source.ts → resolve/dynamic.ts} +152 -143
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +442 -186
- package/src/resolve/source-text.ts +37 -37
- package/src/{dynamic → resolve}/tree-shake.ts +132 -128
- package/src/routing/forwarded.ts +19 -19
- package/src/routing/handler.ts +84 -91
- package/src/routing/href.ts +69 -70
- package/src/routing/{metadata.ts → metadata-files.ts} +403 -401
- package/src/{proxy.ts → routing/proxy.ts} +306 -312
- package/src/routing/{request-runtime.ts → request-environment.ts} +10 -10
- package/src/routing/routes.ts +833 -848
- package/src/routing/slots.ts +164 -160
- package/src/runtime/loader.ts +952 -0
- package/src/{dev → runtime}/module-cache.ts +309 -287
- package/src/{dev → runtime}/module-generations.ts +9 -9
- package/src/{dev → runtime}/module-transform.ts +81 -72
- package/src/{dev/imports.ts → runtime/modules.ts} +934 -847
- package/src/runtime/{server.ts → vendor-build.ts} +848 -1696
- package/src/runtime/vendor.ts +425 -404
- package/src/styles.d.ts +9 -0
- package/src/types.ts +320 -335
- package/src/utils/ansi.ts +5 -5
- package/src/utils/{source.ts → code.ts} +15 -12
- package/src/utils/content-type.ts +3 -3
- package/src/utils/decode.ts +2 -2
- package/src/utils/dev-profile.ts +13 -13
- package/src/utils/error-log.ts +6 -6
- package/src/utils/esbuild.ts +18 -18
- package/src/utils/fs-cache.ts +13 -13
- package/src/utils/fs.ts +57 -49
- package/src/utils/html.ts +20 -24
- package/src/utils/native-require.ts +8 -8
- package/src/utils/serialize.ts +139 -146
- package/src/utils/verbose.ts +18 -18
- package/src/cli/analyze-print.ts +0 -181
- package/src/compat/middleware/manifest.ts +0 -210
- package/src/compat/next/image-client.tsx +0 -215
- package/src/compat/next/link-usage.ts +0 -29
- package/src/css/index.ts +0 -2
- package/src/render/index.ts +0 -1
- package/src/style-modules.d.ts +0 -9
package/src/client/prebuilt.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto'
|
|
2
|
-
import { readFileSync, readdirSync, statSync, type Dirent } from 'node:fs'
|
|
3
|
-
import path from 'node:path'
|
|
4
|
-
import { build, type BuildOptions, type Metafile, type Plugin } from 'esbuild'
|
|
5
|
-
import type { ResolvedConfig } from '../config'
|
|
6
|
-
import { getImportAliasExtensions } from '../extensions'
|
|
7
|
-
import { scanFacts } from '../resolve/scan-facts'
|
|
8
|
-
import { ensureDir, writeText } from '../utils/fs'
|
|
9
|
-
import { escapeRegex } from '../utils/
|
|
10
|
-
import { CLIENT_RUNTIME_MODULE } from './entry'
|
|
1
|
+
import { createHash } from 'node:crypto'
|
|
2
|
+
import { readFileSync, readdirSync, statSync, type Dirent } from 'node:fs'
|
|
3
|
+
import path from 'node:path'
|
|
4
|
+
import { build, type BuildOptions, type Metafile, type Plugin } from 'esbuild'
|
|
5
|
+
import type { ResolvedConfig } from '../config'
|
|
6
|
+
import { getImportAliasExtensions } from '../extensions'
|
|
7
|
+
import { scanFacts } from '../resolve/scan-facts'
|
|
8
|
+
import { ensureDir, writeText } from '../utils/fs'
|
|
9
|
+
import { escapeRegex } from '../utils/code'
|
|
10
|
+
import { CLIENT_RUNTIME_MODULE } from './entry'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* The route-independent half of every client bundle - pnext's own client runtime, the compat
|
|
@@ -22,29 +22,29 @@ import { CLIENT_RUNTIME_MODULE } from './entry';
|
|
|
22
22
|
*/
|
|
23
23
|
export interface PrebuiltRuntime {
|
|
24
24
|
/** Content address of (framework source × alias set × build options). */
|
|
25
|
-
key: string
|
|
25
|
+
key: string
|
|
26
26
|
/** Directory holding the artifact. */
|
|
27
|
-
dir: string
|
|
27
|
+
dir: string
|
|
28
28
|
/** URL prefix route entries import the artifact from — the SERVED url. */
|
|
29
|
-
publicPath: string
|
|
29
|
+
publicPath: string
|
|
30
30
|
/**
|
|
31
31
|
* The same directory as an `assets/…` path, for the preload bookkeeping that
|
|
32
32
|
* speaks in app-relative asset names rather than urls.
|
|
33
33
|
*/
|
|
34
|
-
assetPath: string
|
|
34
|
+
assetPath: string
|
|
35
35
|
/** specifier → every export name that module has (learned by a probe build). */
|
|
36
|
-
exports: Map<string, string[]
|
|
36
|
+
exports: Map<string, string[]>
|
|
37
37
|
/** specifier → the export names route entries actually bind. What ships. */
|
|
38
|
-
surface: Map<string, Set<string
|
|
38
|
+
surface: Map<string, Set<string>>
|
|
39
39
|
/** Artifact files statically reachable from the aggregate, relative to it. */
|
|
40
|
-
closure: { static: string[]; dynamic: string[] }
|
|
40
|
+
closure: { static: string[]; dynamic: string[] }
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/** The aggregate's file name inside the artifact dir. */
|
|
44
|
-
export const PREBUILT_MODULE = 'pnext-runtime.js'
|
|
44
|
+
export const PREBUILT_MODULE = 'pnext-runtime.js'
|
|
45
45
|
|
|
46
46
|
/** Framework source root — anything resolving inside it is route-independent. */
|
|
47
|
-
const frameworkSrc = path.resolve(import.meta.dirname, '..')
|
|
47
|
+
const frameworkSrc = path.resolve(import.meta.dirname, '..')
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* The vendor half of the surface. Single-instance modules (context identity,
|
|
@@ -58,7 +58,7 @@ const vendorSpecifiers = [
|
|
|
58
58
|
'preact/compat/client',
|
|
59
59
|
'preact/jsx-runtime',
|
|
60
60
|
'preact/jsx-dev-runtime',
|
|
61
|
-
]
|
|
61
|
+
]
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* The react-compat aliases seed the artifact alongside the vendors: their targets are `export *`
|
|
@@ -66,37 +66,37 @@ const vendorSpecifiers = [
|
|
|
66
66
|
* preact/compat's WHOLE surface. Everything else is discovered lazily - a leaf compat module
|
|
67
67
|
* bundled once costs only what its importer named.
|
|
68
68
|
*/
|
|
69
|
-
const reactAliasSpecifier = /^react(?:-dom)?(?:\/|$)
|
|
69
|
+
const reactAliasSpecifier = /^react(?:-dom)?(?:\/|$)/
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* The React Compiler's runtime is resolved per build (and asserted on in the
|
|
73
73
|
* route bundle), so it stays out of the artifact.
|
|
74
74
|
*/
|
|
75
|
-
const isCompilerRuntime = (specifier: string) => specifier.endsWith('compiler-runtime')
|
|
75
|
+
const isCompilerRuntime = (specifier: string) => specifier.endsWith('compiler-runtime')
|
|
76
76
|
|
|
77
|
-
const identifier = /^[A-Za-z_$][A-Za-z0-9_$]
|
|
77
|
+
const identifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/
|
|
78
78
|
|
|
79
79
|
/** (specifier, export name) → one collision-free identifier in the aggregate. */
|
|
80
80
|
export function mangledName(specifier: string, name: string) {
|
|
81
|
-
return `__p_${shortHash(specifier)}_${name}
|
|
81
|
+
return `__p_${shortHash(specifier)}_${name}`
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
function shortHash(value: string) {
|
|
85
|
-
return createHash('sha1').update(value).digest('hex').slice(0, 8)
|
|
85
|
+
return createHash('sha1').update(value).digest('hex').slice(0, 8)
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
function seedSpecifiers(aliases: string[]) {
|
|
89
89
|
const react = aliases.filter(
|
|
90
90
|
alias => reactAliasSpecifier.test(alias) && !isCompilerRuntime(alias),
|
|
91
|
-
)
|
|
92
|
-
return [...new Set([...vendorSpecifiers, ...react])]
|
|
91
|
+
)
|
|
92
|
+
return [...new Set([...vendorSpecifiers, ...react])]
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
/** Every framework specifier this app could demand: aliases + preact + pnext src. */
|
|
96
96
|
export function prebuiltSpecifierFilter(config: ResolvedConfig): RegExp {
|
|
97
|
-
const aliases = Object.keys(getImportAliasExtensions().aliases(config, 'client'))
|
|
98
|
-
const bare = [...new Set([...aliases, ...vendorSpecifiers])]
|
|
99
|
-
return new RegExp(`^(?:${bare.map(escapeRegex).join('|')}|${escapeRegex(frameworkSrc)}/)`)
|
|
97
|
+
const aliases = Object.keys(getImportAliasExtensions().aliases(config, 'client'))
|
|
98
|
+
const bare = [...new Set([...aliases, ...vendorSpecifiers])]
|
|
99
|
+
return new RegExp(`^(?:${bare.map(escapeRegex).join('|')}|${escapeRegex(frameworkSrc)}/)`)
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
/**
|
|
@@ -106,10 +106,10 @@ export function prebuiltSpecifierFilter(config: ResolvedConfig): RegExp {
|
|
|
106
106
|
* glue whose weight - router, compat, preact - is external through it anyway.
|
|
107
107
|
*/
|
|
108
108
|
export function isFrameworkSpecifier(specifier: string, filter: RegExp) {
|
|
109
|
-
if (specifier === CLIENT_RUNTIME_MODULE) return false
|
|
110
|
-
if (isCompilerRuntime(specifier)) return false
|
|
111
|
-
if (specifier.startsWith(frameworkSrc)) return true
|
|
112
|
-
return filter.test(specifier) && !specifier.startsWith('.')
|
|
109
|
+
if (specifier === CLIENT_RUNTIME_MODULE) return false
|
|
110
|
+
if (isCompilerRuntime(specifier)) return false
|
|
111
|
+
if (specifier.startsWith(frameworkSrc)) return true
|
|
112
|
+
return filter.test(specifier) && !specifier.startsWith('.')
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
/**
|
|
@@ -124,59 +124,64 @@ export function prebuiltRuntimeKey(
|
|
|
124
124
|
buildOptions: BuildOptions,
|
|
125
125
|
signature = '',
|
|
126
126
|
) {
|
|
127
|
-
const hash = createHash('sha1')
|
|
128
|
-
hash.update(frameworkSourceHash())
|
|
129
|
-
hash.update('\0')
|
|
130
|
-
hash.update(JSON.stringify(Object.keys(getImportAliasExtensions().aliases(config, 'client'))))
|
|
131
|
-
hash.update('\0')
|
|
127
|
+
const hash = createHash('sha1')
|
|
128
|
+
hash.update(frameworkSourceHash())
|
|
129
|
+
hash.update('\0')
|
|
130
|
+
hash.update(JSON.stringify(Object.keys(getImportAliasExtensions().aliases(config, 'client'))))
|
|
131
|
+
hash.update('\0')
|
|
132
132
|
hash.update(
|
|
133
|
-
JSON.stringify([
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
133
|
+
JSON.stringify([
|
|
134
|
+
buildOptions.define,
|
|
135
|
+
buildOptions.minify,
|
|
136
|
+
buildOptions.target,
|
|
137
|
+
buildOptions.pure,
|
|
138
|
+
]),
|
|
139
|
+
)
|
|
140
|
+
hash.update('\0')
|
|
141
|
+
hash.update(signature)
|
|
142
|
+
return hash.digest('hex').slice(0, 16)
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
let cachedSourceHash: string | undefined
|
|
145
|
+
let cachedSourceHash: string | undefined
|
|
141
146
|
|
|
142
147
|
/**
|
|
143
148
|
* Hash of pnext's own source. Cheap on the cold path: mtime+size per file, not contents - the tree is
|
|
144
149
|
* pnext's own install, so a same-mtime file is the same file.
|
|
145
150
|
*/
|
|
146
151
|
function frameworkSourceHash() {
|
|
147
|
-
if (cachedSourceHash) return cachedSourceHash
|
|
148
|
-
const hash = createHash('sha1')
|
|
152
|
+
if (cachedSourceHash) return cachedSourceHash
|
|
153
|
+
const hash = createHash('sha1')
|
|
149
154
|
const walk = (dir: string) => {
|
|
150
|
-
let entries: Dirent[]
|
|
155
|
+
let entries: Dirent[]
|
|
151
156
|
try {
|
|
152
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
157
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
153
158
|
} catch {
|
|
154
|
-
return
|
|
159
|
+
return
|
|
155
160
|
}
|
|
156
161
|
for (const entry of entries.sort((a, b) => (a.name < b.name ? -1 : 1))) {
|
|
157
|
-
const file = path.join(dir, entry.name)
|
|
158
|
-
if (entry.isDirectory()) walk(file)
|
|
162
|
+
const file = path.join(dir, entry.name)
|
|
163
|
+
if (entry.isDirectory()) walk(file)
|
|
159
164
|
else if (/\.(?:tsx?|jsx?|mjs|cjs)$/.test(entry.name)) {
|
|
160
|
-
const stats = statSync(file, { throwIfNoEntry: false })
|
|
161
|
-
if (stats) hash.update(`${file}:${stats.size}:${stats.mtimeMs}\n`)
|
|
165
|
+
const stats = statSync(file, { throwIfNoEntry: false })
|
|
166
|
+
if (stats) hash.update(`${file}:${stats.size}:${stats.mtimeMs}\n`)
|
|
162
167
|
}
|
|
163
168
|
}
|
|
164
|
-
}
|
|
165
|
-
walk(frameworkSrc)
|
|
166
|
-
cachedSourceHash = hash.digest('hex').slice(0, 16)
|
|
167
|
-
return cachedSourceHash
|
|
169
|
+
}
|
|
170
|
+
walk(frameworkSrc)
|
|
171
|
+
cachedSourceHash = hash.digest('hex').slice(0, 16)
|
|
172
|
+
return cachedSourceHash
|
|
168
173
|
}
|
|
169
174
|
|
|
170
175
|
export interface ArtifactOptions {
|
|
171
176
|
/** The client import aliases in force, part of the key and of the seed. */
|
|
172
|
-
aliases: string[]
|
|
173
|
-
dir: string
|
|
174
|
-
publicPath: string
|
|
175
|
-
assetPath: string
|
|
176
|
-
key: string
|
|
177
|
-
buildOptions: BuildOptions
|
|
177
|
+
aliases: string[]
|
|
178
|
+
dir: string
|
|
179
|
+
publicPath: string
|
|
180
|
+
assetPath: string
|
|
181
|
+
key: string
|
|
182
|
+
buildOptions: BuildOptions
|
|
178
183
|
/** Fresh plugin chain per build — esbuild plugins carry per-build state. */
|
|
179
|
-
plugins: () => Plugin[]
|
|
184
|
+
plugins: () => Plugin[]
|
|
180
185
|
}
|
|
181
186
|
|
|
182
187
|
/**
|
|
@@ -187,15 +192,15 @@ export interface ArtifactOptions {
|
|
|
187
192
|
* re-export through several levels of their own stars.
|
|
188
193
|
*/
|
|
189
194
|
async function probeExports(specifiers: string[], options: ArtifactOptions) {
|
|
190
|
-
const found = new Map<string, string[]>()
|
|
191
|
-
if (specifiers.length === 0) return found
|
|
192
|
-
const probeDir = path.join(options.dir, '.probe')
|
|
193
|
-
await ensureDir(probeDir)
|
|
194
|
-
const entryPoints: { in: string; out: string }[] = []
|
|
195
|
+
const found = new Map<string, string[]>()
|
|
196
|
+
if (specifiers.length === 0) return found
|
|
197
|
+
const probeDir = path.join(options.dir, '.probe')
|
|
198
|
+
await ensureDir(probeDir)
|
|
199
|
+
const entryPoints: { in: string; out: string }[] = []
|
|
195
200
|
for (const specifier of specifiers) {
|
|
196
|
-
const file = path.join(probeDir, `${shortHash(specifier)}.ts`)
|
|
197
|
-
await writeText(file, `export * from ${JSON.stringify(specifier)};\n`)
|
|
198
|
-
entryPoints.push({ in: file, out: shortHash(specifier) })
|
|
201
|
+
const file = path.join(probeDir, `${shortHash(specifier)}.ts`)
|
|
202
|
+
await writeText(file, `export * from ${JSON.stringify(specifier)};\n`)
|
|
203
|
+
entryPoints.push({ in: file, out: shortHash(specifier) })
|
|
199
204
|
}
|
|
200
205
|
const result = await build({
|
|
201
206
|
...options.buildOptions,
|
|
@@ -206,15 +211,18 @@ async function probeExports(specifiers: string[], options: ArtifactOptions) {
|
|
|
206
211
|
write: false,
|
|
207
212
|
metafile: true,
|
|
208
213
|
plugins: options.plugins(),
|
|
209
|
-
})
|
|
214
|
+
})
|
|
210
215
|
for (const specifier of specifiers) {
|
|
211
216
|
const output = Object.entries(result.metafile.outputs).find(
|
|
212
217
|
([name]) => path.basename(name) === `${shortHash(specifier)}.js`,
|
|
213
|
-
)
|
|
218
|
+
)
|
|
214
219
|
// `export *` never carries `default`; probeSurface asks for it separately.
|
|
215
|
-
found.set(
|
|
220
|
+
found.set(
|
|
221
|
+
specifier,
|
|
222
|
+
(output?.[1].exports ?? []).filter(name => identifier.test(name)),
|
|
223
|
+
)
|
|
216
224
|
}
|
|
217
|
-
return found
|
|
225
|
+
return found
|
|
218
226
|
}
|
|
219
227
|
|
|
220
228
|
/**
|
|
@@ -226,18 +234,18 @@ async function probeExports(specifiers: string[], options: ArtifactOptions) {
|
|
|
226
234
|
* once, unwritten, and every name that did not materialize is dropped.
|
|
227
235
|
*/
|
|
228
236
|
async function probeSurface(specifiers: string[], options: ArtifactOptions) {
|
|
229
|
-
const probed = await probeExports(specifiers, options)
|
|
230
|
-
if (probed.size === 0) return probed
|
|
237
|
+
const probed = await probeExports(specifiers, options)
|
|
238
|
+
if (probed.size === 0) return probed
|
|
231
239
|
const candidate = new Map(
|
|
232
240
|
[...probed].map(([specifier, names]) => [specifier, new Set([...names, 'default'])]),
|
|
233
|
-
)
|
|
234
|
-
const { text } = await buildAggregate(options, candidate, false)
|
|
241
|
+
)
|
|
242
|
+
const { text } = await buildAggregate(options, candidate, false)
|
|
235
243
|
return new Map(
|
|
236
244
|
[...candidate].map(([specifier, names]) => [
|
|
237
245
|
specifier,
|
|
238
246
|
[...names].filter(name => text.includes(mangledName(specifier, name))),
|
|
239
247
|
]),
|
|
240
|
-
)
|
|
248
|
+
)
|
|
241
249
|
}
|
|
242
250
|
|
|
243
251
|
/**
|
|
@@ -249,20 +257,20 @@ async function buildAggregate(
|
|
|
249
257
|
surface: Map<string, Set<string>>,
|
|
250
258
|
write: boolean,
|
|
251
259
|
) {
|
|
252
|
-
const lines: string[] = []
|
|
260
|
+
const lines: string[] = []
|
|
253
261
|
for (const specifier of [...surface.keys()].sort()) {
|
|
254
|
-
const names = [...surface.get(specifier)!].filter(name => identifier.test(name)).sort()
|
|
255
|
-
const spec = JSON.stringify(specifier)
|
|
256
|
-
if (names.length === 0) lines.push(`import ${spec};`)
|
|
262
|
+
const names = [...surface.get(specifier)!].filter(name => identifier.test(name)).sort()
|
|
263
|
+
const spec = JSON.stringify(specifier)
|
|
264
|
+
if (names.length === 0) lines.push(`import ${spec};`)
|
|
257
265
|
else {
|
|
258
|
-
const clause = names.map(name => `${name} as ${mangledName(specifier, name)}`).join(', ')
|
|
259
|
-
lines.push(`export { ${clause} } from ${spec};`)
|
|
266
|
+
const clause = names.map(name => `${name} as ${mangledName(specifier, name)}`).join(', ')
|
|
267
|
+
lines.push(`export { ${clause} } from ${spec};`)
|
|
260
268
|
}
|
|
261
269
|
}
|
|
262
|
-
const aggregateDir = path.join(options.dir, '.aggregate')
|
|
263
|
-
await ensureDir(aggregateDir)
|
|
264
|
-
const entry = path.join(aggregateDir, 'runtime.ts')
|
|
265
|
-
await writeText(entry, `${lines.join('\n')}\n`)
|
|
270
|
+
const aggregateDir = path.join(options.dir, '.aggregate')
|
|
271
|
+
await ensureDir(aggregateDir)
|
|
272
|
+
const entry = path.join(aggregateDir, 'runtime.ts')
|
|
273
|
+
await writeText(entry, `${lines.join('\n')}\n`)
|
|
266
274
|
|
|
267
275
|
const result = await build({
|
|
268
276
|
...options.buildOptions,
|
|
@@ -273,17 +281,17 @@ async function buildAggregate(
|
|
|
273
281
|
write,
|
|
274
282
|
metafile: true,
|
|
275
283
|
plugins: options.plugins(),
|
|
276
|
-
})
|
|
277
|
-
const emitted = result.outputFiles?.find(file => path.basename(file.path) === PREBUILT_MODULE)
|
|
278
|
-
const text = emitted?.text ?? readFileSafe(path.join(options.dir, PREBUILT_MODULE))
|
|
279
|
-
return { text, metafile: result.metafile }
|
|
284
|
+
})
|
|
285
|
+
const emitted = result.outputFiles?.find(file => path.basename(file.path) === PREBUILT_MODULE)
|
|
286
|
+
const text = emitted?.text ?? readFileSafe(path.join(options.dir, PREBUILT_MODULE))
|
|
287
|
+
return { text, metafile: result.metafile }
|
|
280
288
|
}
|
|
281
289
|
|
|
282
290
|
function readFileSafe(file: string) {
|
|
283
291
|
try {
|
|
284
|
-
return readFileSync(file, 'utf8')
|
|
292
|
+
return readFileSync(file, 'utf8')
|
|
285
293
|
} catch {
|
|
286
|
-
return ''
|
|
294
|
+
return ''
|
|
287
295
|
}
|
|
288
296
|
}
|
|
289
297
|
|
|
@@ -297,7 +305,7 @@ export async function buildPrebuiltRuntime(
|
|
|
297
305
|
exportsBySpecifier: Map<string, string[]>,
|
|
298
306
|
surface: Map<string, Set<string>>,
|
|
299
307
|
): Promise<PrebuiltRuntime> {
|
|
300
|
-
const { metafile } = await buildAggregate(options, surface, true)
|
|
308
|
+
const { metafile } = await buildAggregate(options, surface, true)
|
|
301
309
|
return {
|
|
302
310
|
key: options.key,
|
|
303
311
|
dir: options.dir,
|
|
@@ -306,33 +314,32 @@ export async function buildPrebuiltRuntime(
|
|
|
306
314
|
exports: exportsBySpecifier,
|
|
307
315
|
surface,
|
|
308
316
|
closure: aggregateClosure(metafile),
|
|
309
|
-
}
|
|
317
|
+
}
|
|
310
318
|
}
|
|
311
319
|
|
|
312
|
-
|
|
313
320
|
function aggregateClosure(metafile: Metafile) {
|
|
314
|
-
const entry = Object.keys(metafile.outputs).find(name => path.basename(name) === PREBUILT_MODULE)
|
|
315
|
-
const statics = new Set<string>()
|
|
316
|
-
const dynamics = new Set<string>()
|
|
317
|
-
if (!entry) return { static: [], dynamic: [] }
|
|
318
|
-
const seen = new Set([`${entry}:static`])
|
|
319
|
-
const queue = [{ output: entry, dynamic: false }]
|
|
321
|
+
const entry = Object.keys(metafile.outputs).find(name => path.basename(name) === PREBUILT_MODULE)
|
|
322
|
+
const statics = new Set<string>()
|
|
323
|
+
const dynamics = new Set<string>()
|
|
324
|
+
if (!entry) return { static: [], dynamic: [] }
|
|
325
|
+
const seen = new Set([`${entry}:static`])
|
|
326
|
+
const queue = [{ output: entry, dynamic: false }]
|
|
320
327
|
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
321
328
|
for (let head = 0; head < queue.length; head += 1) {
|
|
322
|
-
const current = queue[head]
|
|
329
|
+
const current = queue[head]!
|
|
323
330
|
for (const imported of metafile.outputs[current.output]?.imports ?? []) {
|
|
324
|
-
if (imported.kind !== 'import-statement' && imported.kind !== 'dynamic-import') continue
|
|
325
|
-
const dynamic = current.dynamic || imported.kind === 'dynamic-import'
|
|
326
|
-
const visitKey = `${imported.path}:${dynamic ? 'dynamic' : 'static'}
|
|
327
|
-
if (seen.has(visitKey)) continue
|
|
328
|
-
seen.add(visitKey)
|
|
329
|
-
queue.push({ output: imported.path, dynamic })
|
|
330
|
-
const relative = path.relative(path.dirname(entry), imported.path).split(path.sep).join('/')
|
|
331
|
-
(dynamic ? dynamics : statics).add(relative)
|
|
331
|
+
if (imported.kind !== 'import-statement' && imported.kind !== 'dynamic-import') continue
|
|
332
|
+
const dynamic = current.dynamic || imported.kind === 'dynamic-import'
|
|
333
|
+
const visitKey = `${imported.path}:${dynamic ? 'dynamic' : 'static'}`
|
|
334
|
+
if (seen.has(visitKey)) continue
|
|
335
|
+
seen.add(visitKey)
|
|
336
|
+
queue.push({ output: imported.path, dynamic })
|
|
337
|
+
const relative = path.relative(path.dirname(entry), imported.path).split(path.sep).join('/')
|
|
338
|
+
;(dynamic ? dynamics : statics).add(relative)
|
|
332
339
|
}
|
|
333
340
|
}
|
|
334
|
-
for (const name of statics) dynamics.delete(name)
|
|
335
|
-
return { static: [...statics], dynamic: [...dynamics] }
|
|
341
|
+
for (const name of statics) dynamics.delete(name)
|
|
342
|
+
return { static: [...statics], dynamic: [...dynamics] }
|
|
336
343
|
}
|
|
337
344
|
/**
|
|
338
345
|
* Route-build seam. A framework specifier resolves to a virtual module that re-exports the target's
|
|
@@ -347,50 +354,48 @@ export function prebuiltExternalPlugin(
|
|
|
347
354
|
unprobed: Set<string>,
|
|
348
355
|
sourceOf: (importer: string) => string | undefined,
|
|
349
356
|
): Plugin {
|
|
350
|
-
const namespace = 'pnext-prebuilt'
|
|
351
|
-
const moduleUrl = prebuiltModuleUrl(runtime)
|
|
357
|
+
const namespace = 'pnext-prebuilt'
|
|
358
|
+
const moduleUrl = prebuiltModuleUrl(runtime)
|
|
352
359
|
return {
|
|
353
360
|
name: 'pnext-prebuilt-runtime',
|
|
354
361
|
setup(build) {
|
|
355
362
|
build.onResolve({ filter: new RegExp(`^${escapeRegex(moduleUrl)}$`) }, () => ({
|
|
356
363
|
path: moduleUrl,
|
|
357
364
|
external: true,
|
|
358
|
-
}))
|
|
365
|
+
}))
|
|
359
366
|
build.onResolve({ filter }, args => {
|
|
360
|
-
if (args.namespace === namespace) return undefined
|
|
361
|
-
if (!isFrameworkSpecifier(args.path, filter)) return undefined
|
|
367
|
+
if (args.namespace === namespace) return undefined
|
|
368
|
+
if (!isFrameworkSpecifier(args.path, filter)) return undefined
|
|
362
369
|
if (!runtime.exports.has(args.path)) {
|
|
363
|
-
unprobed.add(args.path)
|
|
364
|
-
return undefined
|
|
370
|
+
unprobed.add(args.path)
|
|
371
|
+
return undefined
|
|
365
372
|
}
|
|
366
373
|
// A dynamic import takes the module as a NAMESPACE - every export is live - so routing one
|
|
367
374
|
// through the artifact would drag the whole surface into the initial tier that the dynamic
|
|
368
375
|
// import exists to stay out of. Leave it deferred, unless the artifact already ships that
|
|
369
376
|
// module, in which case serving it from there keeps the single instance.
|
|
370
|
-
if (args.kind === 'dynamic-import' && !runtime.surface.has(args.path)) return undefined
|
|
377
|
+
if (args.kind === 'dynamic-import' && !runtime.surface.has(args.path)) return undefined
|
|
371
378
|
// The importer travels in the path because onLoad is not told it, and
|
|
372
379
|
// the demanded names are a property of the IMPORTER, not the specifier:
|
|
373
380
|
// esbuild cannot shake named imports out of an external module, so
|
|
374
381
|
// whatever the virtual module offers is what ships.
|
|
375
|
-
return { path: `${args.path}\0${args.importer}`, namespace }
|
|
376
|
-
})
|
|
382
|
+
return { path: `${args.path}\0${args.importer}`, namespace }
|
|
383
|
+
})
|
|
377
384
|
build.onLoad({ filter: /.*/, namespace }, args => {
|
|
378
|
-
const separator = args.path.lastIndexOf('\0')
|
|
379
|
-
const specifier = args.path.slice(0, separator)
|
|
380
|
-
const importer = args.path.slice(separator + 1)
|
|
381
|
-
const available = runtime.exports.get(specifier) ?? []
|
|
382
|
-
const demanded = demandedNames(importer, specifier, sourceOf(importer), available)
|
|
383
|
-
const clause = demanded
|
|
384
|
-
.map(name => `${mangledName(specifier, name)} as ${name}`)
|
|
385
|
-
.join(', ');
|
|
385
|
+
const separator = args.path.lastIndexOf('\0')
|
|
386
|
+
const specifier = args.path.slice(0, separator)
|
|
387
|
+
const importer = args.path.slice(separator + 1)
|
|
388
|
+
const available = runtime.exports.get(specifier) ?? []
|
|
389
|
+
const demanded = demandedNames(importer, specifier, sourceOf(importer), available)
|
|
390
|
+
const clause = demanded.map(name => `${mangledName(specifier, name)} as ${name}`).join(', ')
|
|
386
391
|
const contents =
|
|
387
392
|
clause.length > 0
|
|
388
393
|
? `export { ${clause} } from ${JSON.stringify(moduleUrl)};\n`
|
|
389
|
-
: `import ${JSON.stringify(moduleUrl)};\n
|
|
390
|
-
return { contents, loader: 'js', resolveDir: path.dirname(specifier) }
|
|
391
|
-
})
|
|
394
|
+
: `import ${JSON.stringify(moduleUrl)};\n`
|
|
395
|
+
return { contents, loader: 'js', resolveDir: path.dirname(specifier) }
|
|
396
|
+
})
|
|
392
397
|
},
|
|
393
|
-
}
|
|
398
|
+
}
|
|
394
399
|
}
|
|
395
400
|
/**
|
|
396
401
|
* The names one importer binds off one specifier. A namespace import, an `export * from`, or an import
|
|
@@ -403,110 +408,113 @@ function demandedNames(
|
|
|
403
408
|
source: string | undefined,
|
|
404
409
|
available: string[],
|
|
405
410
|
) {
|
|
406
|
-
if (source === undefined) return available
|
|
411
|
+
if (source === undefined) return available
|
|
407
412
|
// The generated entries are virtual and their importer id carries no extension; scanFacts picks
|
|
408
413
|
// the parser off the name, so an id like `index` would parse as plain JS, leaving the entry's
|
|
409
414
|
// TypeScript unreadable - which reads as "demands everything".
|
|
410
|
-
const sourceFile = /\.[cm]?[jt]sx?$/i.test(importer) ? importer : `${importer}.tsx
|
|
411
|
-
let edges
|
|
415
|
+
const sourceFile = /\.[cm]?[jt]sx?$/i.test(importer) ? importer : `${importer}.tsx`
|
|
416
|
+
let edges
|
|
412
417
|
try {
|
|
413
|
-
edges = scanFacts(sourceFile, source).imports
|
|
418
|
+
edges = scanFacts(sourceFile, source).imports
|
|
414
419
|
} catch {
|
|
415
|
-
return available
|
|
420
|
+
return available
|
|
416
421
|
}
|
|
417
|
-
const names = new Set<string>()
|
|
418
|
-
let named = false
|
|
422
|
+
const names = new Set<string>()
|
|
423
|
+
let named = false
|
|
419
424
|
for (const edge of edges) {
|
|
420
|
-
if (edge.specifier !== specifier) continue
|
|
421
|
-
named = true
|
|
422
|
-
if (edge.star || edge.exports.includes('*')) return available
|
|
423
|
-
for (const name of edge.exports) names.add(name)
|
|
425
|
+
if (edge.specifier !== specifier) continue
|
|
426
|
+
named = true
|
|
427
|
+
if (edge.star || edge.exports.includes('*')) return available
|
|
428
|
+
for (const name of edge.exports) names.add(name)
|
|
424
429
|
}
|
|
425
|
-
if (!named) return available
|
|
426
|
-
const offered = available.filter(name => names.has(name))
|
|
430
|
+
if (!named) return available
|
|
431
|
+
const offered = available.filter(name => names.has(name))
|
|
427
432
|
// A name the target does not export is the build's error to report, not
|
|
428
433
|
// something to silently drop — offer it and let esbuild say so.
|
|
429
|
-
for (const name of names) if (!available.includes(name)) offered.push(name)
|
|
430
|
-
return offered
|
|
434
|
+
for (const name of names) if (!available.includes(name)) offered.push(name)
|
|
435
|
+
return offered
|
|
431
436
|
}
|
|
432
437
|
|
|
433
438
|
export function prebuiltModuleUrl(runtime: Pick<PrebuiltRuntime, 'publicPath'>) {
|
|
434
|
-
return `${runtime.publicPath}/${PREBUILT_MODULE}
|
|
439
|
+
return `${runtime.publicPath}/${PREBUILT_MODULE}`
|
|
435
440
|
}
|
|
436
441
|
/**
|
|
437
442
|
* Read the surface the build actually demanded back off its own output: every mangled name imported
|
|
438
443
|
* from the artifact url. Exact by construction - it is the same list the browser will ask for.
|
|
439
444
|
*/
|
|
440
445
|
export function demandedFromOutputs(runtime: PrebuiltRuntime, outDir: string) {
|
|
441
|
-
const moduleUrl = prebuiltModuleUrl(runtime)
|
|
442
|
-
const byMangled = new Map<string, { specifier: string; name: string }>()
|
|
446
|
+
const moduleUrl = prebuiltModuleUrl(runtime)
|
|
447
|
+
const byMangled = new Map<string, { specifier: string; name: string }>()
|
|
443
448
|
for (const [specifier, names] of runtime.exports) {
|
|
444
|
-
for (const name of names) byMangled.set(mangledName(specifier, name), { specifier, name })
|
|
449
|
+
for (const name of names) byMangled.set(mangledName(specifier, name), { specifier, name })
|
|
445
450
|
}
|
|
446
|
-
const demanded = new Map<string, Set<string>>()
|
|
451
|
+
const demanded = new Map<string, Set<string>>()
|
|
447
452
|
const walk = (dir: string) => {
|
|
448
|
-
let entries: Dirent[]
|
|
453
|
+
let entries: Dirent[]
|
|
449
454
|
try {
|
|
450
|
-
entries = readdirSync(dir, { withFileTypes: true })
|
|
455
|
+
entries = readdirSync(dir, { withFileTypes: true })
|
|
451
456
|
} catch {
|
|
452
|
-
return
|
|
457
|
+
return
|
|
453
458
|
}
|
|
454
459
|
for (const entry of entries) {
|
|
455
|
-
const file = path.join(dir, entry.name)
|
|
460
|
+
const file = path.join(dir, entry.name)
|
|
456
461
|
// The artifact itself lives under the out dir in prod; it is where these
|
|
457
462
|
// names come from, not a consumer of them.
|
|
458
463
|
if (entry.isDirectory()) {
|
|
459
|
-
if (file !== runtime.dir) walk(file)
|
|
460
|
-
continue
|
|
464
|
+
if (file !== runtime.dir) walk(file)
|
|
465
|
+
continue
|
|
461
466
|
}
|
|
462
|
-
if (!entry.name.endsWith('.js')) continue
|
|
463
|
-
let source: string
|
|
467
|
+
if (!entry.name.endsWith('.js')) continue
|
|
468
|
+
let source: string
|
|
464
469
|
try {
|
|
465
|
-
source = readFileSync(file, 'utf8')
|
|
470
|
+
source = readFileSync(file, 'utf8')
|
|
466
471
|
} catch {
|
|
467
|
-
continue
|
|
472
|
+
continue
|
|
468
473
|
}
|
|
469
|
-
if (!source.includes(moduleUrl)) continue
|
|
474
|
+
if (!source.includes(moduleUrl)) continue
|
|
470
475
|
for (const edge of scanFacts(file, source).imports) {
|
|
471
|
-
if (edge.specifier !== moduleUrl) continue
|
|
476
|
+
if (edge.specifier !== moduleUrl) continue
|
|
472
477
|
for (const bound of edge.exports) {
|
|
473
|
-
const origin = byMangled.get(bound)
|
|
474
|
-
if (!origin) continue
|
|
475
|
-
const names = demanded.get(origin.specifier) ?? new Set<string>()
|
|
476
|
-
demanded.set(origin.specifier, names)
|
|
477
|
-
names.add(origin.name)
|
|
478
|
+
const origin = byMangled.get(bound)
|
|
479
|
+
if (!origin) continue
|
|
480
|
+
const names = demanded.get(origin.specifier) ?? new Set<string>()
|
|
481
|
+
demanded.set(origin.specifier, names)
|
|
482
|
+
names.add(origin.name)
|
|
478
483
|
}
|
|
479
484
|
}
|
|
480
485
|
}
|
|
481
|
-
}
|
|
482
|
-
walk(outDir)
|
|
483
|
-
return demanded
|
|
486
|
+
}
|
|
487
|
+
walk(outDir)
|
|
488
|
+
return demanded
|
|
484
489
|
}
|
|
485
490
|
|
|
486
491
|
/** Is every demanded name already in the artifact on disk? */
|
|
487
492
|
export function surfaceCovered(runtime: PrebuiltRuntime, demanded: Map<string, Set<string>>) {
|
|
488
493
|
for (const [specifier, names] of demanded) {
|
|
489
|
-
const have = runtime.surface.get(specifier)
|
|
490
|
-
if (!have) return false
|
|
491
|
-
for (const name of names) if (!have.has(name)) return false
|
|
494
|
+
const have = runtime.surface.get(specifier)
|
|
495
|
+
if (!have) return false
|
|
496
|
+
for (const name of names) if (!have.has(name)) return false
|
|
492
497
|
}
|
|
493
|
-
return true
|
|
498
|
+
return true
|
|
494
499
|
}
|
|
495
500
|
|
|
496
|
-
const manifestName = 'pnext-runtime.json'
|
|
501
|
+
const manifestName = 'pnext-runtime.json'
|
|
497
502
|
|
|
498
503
|
/**
|
|
499
504
|
* One artifact address is shared by every route build in the process, and in
|
|
500
505
|
* dev several routes compile at once. Serialize per address so two esbuild runs
|
|
501
506
|
* never write the same directory concurrently.
|
|
502
507
|
*/
|
|
503
|
-
const artifactLocks = new Map<string, Promise<unknown>>()
|
|
508
|
+
const artifactLocks = new Map<string, Promise<unknown>>()
|
|
504
509
|
|
|
505
510
|
function underLock<T>(dir: string, run: () => Promise<T>): Promise<T> {
|
|
506
|
-
const previous = artifactLocks.get(dir) ?? Promise.resolve()
|
|
507
|
-
const next = previous.then(run, run)
|
|
508
|
-
artifactLocks.set(
|
|
509
|
-
|
|
511
|
+
const previous = artifactLocks.get(dir) ?? Promise.resolve()
|
|
512
|
+
const next = previous.then(run, run)
|
|
513
|
+
artifactLocks.set(
|
|
514
|
+
dir,
|
|
515
|
+
next.catch(() => undefined),
|
|
516
|
+
)
|
|
517
|
+
return next
|
|
510
518
|
}
|
|
511
519
|
|
|
512
520
|
/**
|
|
@@ -516,11 +524,11 @@ function underLock<T>(dir: string, run: () => Promise<T>): Promise<T> {
|
|
|
516
524
|
* probed and folded in by the build that first demands it.
|
|
517
525
|
*/
|
|
518
526
|
export function ensurePrebuiltRuntime(options: ArtifactOptions) {
|
|
519
|
-
return underLock(options.dir, () => openPrebuiltRuntime(options))
|
|
527
|
+
return underLock(options.dir, () => openPrebuiltRuntime(options))
|
|
520
528
|
}
|
|
521
529
|
|
|
522
530
|
async function openPrebuiltRuntime(options: ArtifactOptions) {
|
|
523
|
-
const manifest = readManifest(options.dir)
|
|
531
|
+
const manifest = readManifest(options.dir)
|
|
524
532
|
if (manifest) {
|
|
525
533
|
return {
|
|
526
534
|
key: options.key,
|
|
@@ -528,14 +536,14 @@ async function openPrebuiltRuntime(options: ArtifactOptions) {
|
|
|
528
536
|
publicPath: options.publicPath,
|
|
529
537
|
assetPath: options.assetPath,
|
|
530
538
|
...manifest,
|
|
531
|
-
} satisfies PrebuiltRuntime
|
|
539
|
+
} satisfies PrebuiltRuntime
|
|
532
540
|
}
|
|
533
|
-
const exportsBySpecifier = await probeSurface(seedSpecifiers(options.aliases), options)
|
|
541
|
+
const exportsBySpecifier = await probeSurface(seedSpecifiers(options.aliases), options)
|
|
534
542
|
// Seed surface: nothing is demanded yet, so the aggregate starts empty and
|
|
535
543
|
// the first route build's own output says what belongs in it.
|
|
536
|
-
const runtime = await buildPrebuiltRuntime(options, exportsBySpecifier, new Map())
|
|
537
|
-
await writeManifest(runtime)
|
|
538
|
-
return runtime
|
|
544
|
+
const runtime = await buildPrebuiltRuntime(options, exportsBySpecifier, new Map())
|
|
545
|
+
await writeManifest(runtime)
|
|
546
|
+
return runtime
|
|
539
547
|
}
|
|
540
548
|
/**
|
|
541
549
|
* Fold what the build demanded - and any specifier it met for the first time - into the artifact. A
|
|
@@ -547,7 +555,7 @@ export function settlePrebuiltRuntime(
|
|
|
547
555
|
outDir: string,
|
|
548
556
|
unprobed: Set<string>,
|
|
549
557
|
) {
|
|
550
|
-
return underLock(options.dir, () => growPrebuiltRuntime(runtime, options, outDir, unprobed))
|
|
558
|
+
return underLock(options.dir, () => growPrebuiltRuntime(runtime, options, outDir, unprobed))
|
|
551
559
|
}
|
|
552
560
|
|
|
553
561
|
async function growPrebuiltRuntime(
|
|
@@ -558,43 +566,43 @@ async function growPrebuiltRuntime(
|
|
|
558
566
|
) {
|
|
559
567
|
// Another build may have grown the artifact while this one ran; merge onto
|
|
560
568
|
// what is on disk now, not onto the snapshot this build opened.
|
|
561
|
-
const current = readManifest(options.dir)
|
|
562
|
-
if (current) runtime = { ...runtime, ...current }
|
|
563
|
-
const demanded = demandedFromOutputs(runtime, outDir)
|
|
564
|
-
if (unprobed.size === 0 && surfaceCovered(runtime, demanded)) return runtime
|
|
565
|
-
const exportsBySpecifier = new Map(runtime.exports)
|
|
569
|
+
const current = readManifest(options.dir)
|
|
570
|
+
if (current) runtime = { ...runtime, ...current }
|
|
571
|
+
const demanded = demandedFromOutputs(runtime, outDir)
|
|
572
|
+
if (unprobed.size === 0 && surfaceCovered(runtime, demanded)) return runtime
|
|
573
|
+
const exportsBySpecifier = new Map(runtime.exports)
|
|
566
574
|
for (const [specifier, names] of await probeSurface([...unprobed], options)) {
|
|
567
|
-
exportsBySpecifier.set(specifier, names)
|
|
575
|
+
exportsBySpecifier.set(specifier, names)
|
|
568
576
|
}
|
|
569
|
-
const surface = new Map(runtime.surface)
|
|
577
|
+
const surface = new Map(runtime.surface)
|
|
570
578
|
for (const [specifier, names] of demanded) {
|
|
571
|
-
const target = surface.get(specifier) ?? new Set<string>()
|
|
572
|
-
surface.set(specifier, target)
|
|
573
|
-
for (const name of names) target.add(name)
|
|
579
|
+
const target = surface.get(specifier) ?? new Set<string>()
|
|
580
|
+
surface.set(specifier, target)
|
|
581
|
+
for (const name of names) target.add(name)
|
|
574
582
|
}
|
|
575
|
-
const grown = await buildPrebuiltRuntime(options, exportsBySpecifier, surface)
|
|
576
|
-
await writeManifest(grown)
|
|
577
|
-
return grown
|
|
583
|
+
const grown = await buildPrebuiltRuntime(options, exportsBySpecifier, surface)
|
|
584
|
+
await writeManifest(grown)
|
|
585
|
+
return grown
|
|
578
586
|
}
|
|
579
587
|
|
|
580
588
|
interface Manifest {
|
|
581
|
-
key: string
|
|
582
|
-
exports: Record<string, string[]
|
|
583
|
-
surface: Record<string, string[]
|
|
584
|
-
closure: { static: string[]; dynamic: string[] }
|
|
589
|
+
key: string
|
|
590
|
+
exports: Record<string, string[]>
|
|
591
|
+
surface: Record<string, string[]>
|
|
592
|
+
closure: { static: string[]; dynamic: string[] }
|
|
585
593
|
}
|
|
586
594
|
|
|
587
595
|
function readManifest(dir: string) {
|
|
588
596
|
try {
|
|
589
|
-
const parsed = JSON.parse(readFileSync(path.join(dir, manifestName), 'utf8')) as Manifest
|
|
590
|
-
if (!parsed.exports) return undefined
|
|
597
|
+
const parsed = JSON.parse(readFileSync(path.join(dir, manifestName), 'utf8')) as Manifest
|
|
598
|
+
if (!parsed.exports) return undefined
|
|
591
599
|
return {
|
|
592
600
|
exports: new Map(Object.entries(parsed.exports)),
|
|
593
601
|
surface: new Map(Object.entries(parsed.surface).map(([spec, n]) => [spec, new Set(n)])),
|
|
594
602
|
closure: parsed.closure,
|
|
595
|
-
}
|
|
603
|
+
}
|
|
596
604
|
} catch {
|
|
597
|
-
return undefined
|
|
605
|
+
return undefined
|
|
598
606
|
}
|
|
599
607
|
}
|
|
600
608
|
|
|
@@ -604,8 +612,8 @@ async function writeManifest(runtime: PrebuiltRuntime) {
|
|
|
604
612
|
exports: Object.fromEntries(runtime.exports),
|
|
605
613
|
surface: Object.fromEntries([...runtime.surface].map(([s, n]) => [s, [...n].sort()])),
|
|
606
614
|
closure: runtime.closure,
|
|
607
|
-
}
|
|
608
|
-
await writeText(path.join(runtime.dir, manifestName), JSON.stringify(manifest))
|
|
615
|
+
}
|
|
616
|
+
await writeText(path.join(runtime.dir, manifestName), JSON.stringify(manifest))
|
|
609
617
|
}
|
|
610
618
|
|
|
611
619
|
/**
|
|
@@ -613,9 +621,9 @@ async function writeManifest(runtime: PrebuiltRuntime) {
|
|
|
613
621
|
* `assets/…` names — what the rendered page's modulepreload list is written in.
|
|
614
622
|
*/
|
|
615
623
|
export function prebuiltAssets(runtime: PrebuiltRuntime) {
|
|
616
|
-
const join = (name: string) => `${runtime.assetPath}/${name}
|
|
624
|
+
const join = (name: string) => `${runtime.assetPath}/${name}`
|
|
617
625
|
return {
|
|
618
626
|
static: [join(PREBUILT_MODULE), ...runtime.closure.static.map(join)],
|
|
619
627
|
dynamic: runtime.closure.dynamic.map(join),
|
|
620
|
-
}
|
|
628
|
+
}
|
|
621
629
|
}
|