@wular/pnext 0.0.4 → 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 -1992
- 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 -1897
- 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} +139 -139
- package/src/resolve/engine.ts +90 -77
- package/src/resolve/imports.ts +475 -463
- package/src/resolve/scan-facts.ts +318 -296
- 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 +827 -815
- 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/cli/analyze-print.ts
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { bold, cyan, dim } from '../utils/ansi';
|
|
2
|
-
import type { analyzeProject } from './analyze';
|
|
3
|
-
|
|
4
|
-
type AnalyzeResult = Awaited<ReturnType<typeof analyzeProject>>;
|
|
5
|
-
type Compression = AnalyzeResult['compression'];
|
|
6
|
-
|
|
7
|
-
export function printAnalyzeResult(
|
|
8
|
-
result: AnalyzeResult,
|
|
9
|
-
options: { route?: string; files: boolean },
|
|
10
|
-
) {
|
|
11
|
-
console.log(
|
|
12
|
-
`PNext analyze: ${result.mode === 'production' ? 'production build' : 'dev server cache'} at ${dim(result.root)} (${result.compression})`,
|
|
13
|
-
);
|
|
14
|
-
printRouteBundles(result);
|
|
15
|
-
// With a route filter, the remaining files are mostly other routes' bundles —
|
|
16
|
-
// listing them as "other" would misread as unowned weight.
|
|
17
|
-
if (!options.route) printAnalyzeFiles(result, { details: options.files });
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function printRouteBundles(result: AnalyzeResult) {
|
|
21
|
-
if (result.routeBundles.length === 0) return;
|
|
22
|
-
|
|
23
|
-
console.log(`\n${bold('Routes')}`);
|
|
24
|
-
for (const bundle of result.routeBundles) {
|
|
25
|
-
console.log(`\n${cyan(bundle.route)} ${dim(`(${bundle.page} page)`)}`);
|
|
26
|
-
printBundleGroup('initial', bundle.initial, result.compression);
|
|
27
|
-
printDynamicBundleGroup('visible dynamic', bundle.visibleDynamic, result.compression);
|
|
28
|
-
printDynamicBundleGroup('dynamic', bundle.dynamic, result.compression);
|
|
29
|
-
printBundleGroup('shared after dynamic', bundle.lazyShared, result.compression);
|
|
30
|
-
}
|
|
31
|
-
console.log('');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function printBundleGroup(
|
|
35
|
-
label: string,
|
|
36
|
-
files: AnalyzeResult['routeBundles'][number]['initial'],
|
|
37
|
-
compression: Compression,
|
|
38
|
-
) {
|
|
39
|
-
if (files.length === 0) return;
|
|
40
|
-
console.log(`\n ${bold(label.padEnd(22))} ${formatTotalSize(files, compression)}`);
|
|
41
|
-
printBundleFiles(files, compression, ' ', rowColumns(files));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function printDynamicBundleGroup(
|
|
45
|
-
label: string,
|
|
46
|
-
files: AnalyzeResult['routeBundles'][number]['visibleDynamic'],
|
|
47
|
-
compression: Compression,
|
|
48
|
-
) {
|
|
49
|
-
if (files.length === 0) return;
|
|
50
|
-
console.log(`\n ${bold(label)}`);
|
|
51
|
-
const columns = rowColumns(files);
|
|
52
|
-
const componentWidth = Math.max(...files.map(file => file.exportName.length));
|
|
53
|
-
const pathWidth = Math.max(...files.map(file => file.path.length));
|
|
54
|
-
for (const file of files) {
|
|
55
|
-
console.log(
|
|
56
|
-
` ${file.exportName.padEnd(componentWidth)} ${dim(file.path.padEnd(pathWidth))} ${formatFileSize(file, compression, columns)}`,
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function formatTotalSize(
|
|
62
|
-
files: { rawBytes: number; compressedBytes: number }[],
|
|
63
|
-
compression: Compression,
|
|
64
|
-
) {
|
|
65
|
-
const rawBytes = files.reduce((total, file) => total + file.rawBytes, 0);
|
|
66
|
-
const compressedBytes = files.reduce((total, file) => total + file.compressedBytes, 0);
|
|
67
|
-
return `${formatBytes(compressedBytes)} ${compression} ${dim(`${formatBytes(rawBytes)} raw`)}`;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function printAnalyzeFiles(result: AnalyzeResult, options: { details: boolean }) {
|
|
71
|
-
const routeFiles = new Set(
|
|
72
|
-
result.routeBundles.flatMap(bundle => [
|
|
73
|
-
...bundle.initial.map(file => file.path),
|
|
74
|
-
...bundle.visibleDynamic.map(file => file.path),
|
|
75
|
-
...bundle.dynamic.map(file => file.path),
|
|
76
|
-
...bundle.lazyShared.map(file => file.path),
|
|
77
|
-
]),
|
|
78
|
-
);
|
|
79
|
-
const sorted = sortedAnalyzeFiles(result.files).filter(file => !routeFiles.has(file.path));
|
|
80
|
-
if (sorted.length === 0) return;
|
|
81
|
-
|
|
82
|
-
if (!options.details) {
|
|
83
|
-
console.log(
|
|
84
|
-
`Other files: ${formatFileCount(sorted)} ${formatTotalSize(sorted, result.compression)}`,
|
|
85
|
-
);
|
|
86
|
-
console.log('Run pnext analyze --files to list them.');
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
console.log(`${bold('Other files')}\n`);
|
|
91
|
-
for (const type of ['html', 'css', 'js', 'asset'] as const) {
|
|
92
|
-
const files = sorted.filter(file => file.type === type);
|
|
93
|
-
if (files.length === 0) continue;
|
|
94
|
-
console.log(bold(type));
|
|
95
|
-
printBundleFiles(files, result.compression, ' ', rowColumns(files));
|
|
96
|
-
console.log('');
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function printBundleFiles(
|
|
101
|
-
files: { path: string; rawBytes: number; compressedBytes: number }[],
|
|
102
|
-
compression: Compression,
|
|
103
|
-
indent: string,
|
|
104
|
-
columns: RowColumns,
|
|
105
|
-
) {
|
|
106
|
-
const pathWidth = Math.max(...files.map(file => file.path.length));
|
|
107
|
-
for (const file of files) {
|
|
108
|
-
console.log(
|
|
109
|
-
`${indent}${dim(file.path.padEnd(pathWidth))} ${formatFileSize(file, compression, columns)}`,
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
interface RowColumns {
|
|
115
|
-
compressedWidth: number;
|
|
116
|
-
rawWidth: number;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function rowColumns(files: { rawBytes: number; compressedBytes: number }[]): RowColumns {
|
|
120
|
-
return {
|
|
121
|
-
compressedWidth: Math.max(...files.map(file => formatBytes(file.compressedBytes).length)),
|
|
122
|
-
rawWidth: Math.max(...files.map(file => formatBytes(file.rawBytes).length)),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function formatFileSize(
|
|
127
|
-
file: { rawBytes: number; compressedBytes: number },
|
|
128
|
-
compression: Compression,
|
|
129
|
-
columns: RowColumns,
|
|
130
|
-
) {
|
|
131
|
-
const compressed = formatBytes(file.compressedBytes).padStart(columns.compressedWidth);
|
|
132
|
-
const raw = `${formatBytes(file.rawBytes).padStart(columns.rawWidth)} raw`;
|
|
133
|
-
return `${compressed} ${compression} ${dim(raw)}`;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function formatFileCount(files: AnalyzeResult['files']) {
|
|
137
|
-
const counts = new Map<string, number>();
|
|
138
|
-
for (const file of files) counts.set(file.type, (counts.get(file.type) ?? 0) + 1);
|
|
139
|
-
return [...counts].map(([type, count]) => `${count} ${pluralFileType(type, count)}`).join(', ');
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function pluralFileType(type: string, count: number) {
|
|
143
|
-
if (count === 1) return type;
|
|
144
|
-
if (type === 'js' || type === 'css' || type === 'html') return type;
|
|
145
|
-
return `${type}s`;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function sortedAnalyzeFiles(files: AnalyzeResult['files']) {
|
|
149
|
-
return [...files].sort((a, b) => {
|
|
150
|
-
const typeDelta = analyzeTypeRank(a.type) - analyzeTypeRank(b.type);
|
|
151
|
-
if (typeDelta) return typeDelta;
|
|
152
|
-
const sizeDelta = b.compressedBytes - a.compressedBytes;
|
|
153
|
-
if (sizeDelta) return sizeDelta;
|
|
154
|
-
return a.path.localeCompare(b.path);
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
function analyzeTypeRank(type: AnalyzeResult['files'][number]['type']) {
|
|
159
|
-
switch (type) {
|
|
160
|
-
case 'html':
|
|
161
|
-
return 0;
|
|
162
|
-
case 'css':
|
|
163
|
-
return 1;
|
|
164
|
-
case 'js':
|
|
165
|
-
return 2;
|
|
166
|
-
case 'asset':
|
|
167
|
-
return 3;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function formatBytes(bytes: number) {
|
|
172
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
173
|
-
const units = ['KB', 'MB', 'GB', 'TB'] as const;
|
|
174
|
-
let value = bytes / 1024;
|
|
175
|
-
let unitIndex = 0;
|
|
176
|
-
while (value >= 1024 && unitIndex < units.length - 1) {
|
|
177
|
-
value /= 1024;
|
|
178
|
-
unitIndex += 1;
|
|
179
|
-
}
|
|
180
|
-
return `${value >= 10 ? value.toFixed(1) : value.toFixed(2)} ${units[unitIndex]}`;
|
|
181
|
-
}
|
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
// Middleware manifest emission (COMPAT - may import core freely).
|
|
2
|
-
//
|
|
3
|
-
// Writes the two Next-shaped manifests a few suites read directly from the build output:
|
|
4
|
-
// - `<out>/server/middleware-manifest.json`: the edge-middleware entry with its compiled matchers,
|
|
5
|
-
// entrypoint and files list.
|
|
6
|
-
// - `<out>/server/functions-config-manifest.json`: the node-runtime variant, when the middleware opts
|
|
7
|
-
// into `runtime: 'nodejs'`.
|
|
8
|
-
//
|
|
9
|
-
// Only the fields the tests read are populated. A pure-core app writes neither.
|
|
10
|
-
|
|
11
|
-
import path from 'node:path';
|
|
12
|
-
import { mkdir, writeFile } from 'node:fs/promises';
|
|
13
|
-
import { findProxyFile, type ProxyConfig, type ProxyModule } from '../../proxy';
|
|
14
|
-
import { pathToFileHref, type ResolvedConfig } from '../../config';
|
|
15
|
-
import { toPosixPath } from '../../utils/fs';
|
|
16
|
-
import type { RouteManifestEntry } from '../../types';
|
|
17
|
-
import { readMiddlewareWasmBindingsForOutPath } from '../bundler/wasm';
|
|
18
|
-
import { preferredRegionForRoute } from '../next/preferred-region';
|
|
19
|
-
|
|
20
|
-
interface ManifestMatcher {
|
|
21
|
-
regexp: string;
|
|
22
|
-
originalSource: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
interface MiddlewareEntry {
|
|
26
|
-
name: string;
|
|
27
|
-
page: string;
|
|
28
|
-
matchers: ManifestMatcher[];
|
|
29
|
-
wasm: { name: string; filePath: string }[];
|
|
30
|
-
assets: never[];
|
|
31
|
-
files: string[];
|
|
32
|
-
entrypoint: string;
|
|
33
|
-
env: Record<string, string>;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
interface MiddlewareManifest {
|
|
37
|
-
version: number;
|
|
38
|
-
sortedMiddleware: string[];
|
|
39
|
-
middleware: Record<string, MiddlewareEntry>;
|
|
40
|
-
functions: Record<string, unknown>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
interface FunctionsConfigManifest {
|
|
44
|
-
version: number;
|
|
45
|
-
functions: Record<string, { runtime: string; matchers: ManifestMatcher[] }>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Emit the middleware manifests for the resolved proxy file, if any. `entryFile`
|
|
50
|
-
* is the compiled proxy module path (relative to `outPath`, posix) produced by
|
|
51
|
-
* the build; it is recorded as the manifest `entrypoint` under `server/`.
|
|
52
|
-
*/
|
|
53
|
-
export async function writeMiddlewareManifests(
|
|
54
|
-
config: ResolvedConfig,
|
|
55
|
-
entryFile: string | undefined,
|
|
56
|
-
routes: RouteManifestEntry[] = [],
|
|
57
|
-
): Promise<void> {
|
|
58
|
-
const source = findProxyFile(config);
|
|
59
|
-
// Edge-runtime app segments are manifest `functions` entries alongside the
|
|
60
|
-
// middleware, keyed by their app path (route groups included) — an app with
|
|
61
|
-
// an edge page and no middleware still writes the manifest for them.
|
|
62
|
-
const functions = edgeFunctionEntries(config, routes);
|
|
63
|
-
if (!source || !entryFile) {
|
|
64
|
-
if (Object.keys(functions).length === 0) return;
|
|
65
|
-
const serverDir = path.join(config.outPath, 'server');
|
|
66
|
-
await mkdir(serverDir, { recursive: true });
|
|
67
|
-
await writeFile(
|
|
68
|
-
path.join(serverDir, 'middleware-manifest.json'),
|
|
69
|
-
`${JSON.stringify({ ...emptyMiddlewareManifest(), functions }, null, 2)}\n`,
|
|
70
|
-
);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const moduleFile = path.resolve(config.outPath, entryFile);
|
|
75
|
-
const module = (await import(pathToFileHref(moduleFile))) as ProxyModule;
|
|
76
|
-
const matchers = manifestMatchers(module.config);
|
|
77
|
-
const runtime = proxyRuntime(module.config);
|
|
78
|
-
const entrypoint = toServerEntrypoint(entryFile);
|
|
79
|
-
|
|
80
|
-
const serverDir = path.join(config.outPath, 'server');
|
|
81
|
-
await mkdir(serverDir, { recursive: true });
|
|
82
|
-
|
|
83
|
-
if (runtime === 'nodejs') {
|
|
84
|
-
const functionsConfig: FunctionsConfigManifest = {
|
|
85
|
-
version: 1,
|
|
86
|
-
functions: { '/_middleware': { runtime: 'nodejs', matchers } },
|
|
87
|
-
};
|
|
88
|
-
await writeFile(
|
|
89
|
-
path.join(serverDir, 'functions-config-manifest.json'),
|
|
90
|
-
`${JSON.stringify(functionsConfig, null, 2)}\n`,
|
|
91
|
-
);
|
|
92
|
-
// A node-runtime middleware still lists an empty edge middleware manifest so
|
|
93
|
-
// consumers that always read it find a valid (empty) shape.
|
|
94
|
-
await writeFile(
|
|
95
|
-
path.join(serverDir, 'middleware-manifest.json'),
|
|
96
|
-
`${JSON.stringify({ ...emptyMiddlewareManifest(), functions }, null, 2)}\n`,
|
|
97
|
-
);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const entry: MiddlewareEntry = {
|
|
102
|
-
name: 'middleware',
|
|
103
|
-
page: '/',
|
|
104
|
-
matchers,
|
|
105
|
-
wasm: readMiddlewareWasmBindingsForOutPath(config.outPath),
|
|
106
|
-
assets: [],
|
|
107
|
-
files: [entrypoint],
|
|
108
|
-
entrypoint,
|
|
109
|
-
env: {},
|
|
110
|
-
};
|
|
111
|
-
const manifest: MiddlewareManifest = {
|
|
112
|
-
version: 3,
|
|
113
|
-
sortedMiddleware: ['/'],
|
|
114
|
-
middleware: { '/': entry },
|
|
115
|
-
functions,
|
|
116
|
-
};
|
|
117
|
-
await writeFile(
|
|
118
|
-
path.join(serverDir, 'middleware-manifest.json'),
|
|
119
|
-
`${JSON.stringify(manifest, null, 2)}\n`,
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function emptyMiddlewareManifest(): MiddlewareManifest {
|
|
124
|
-
return { version: 3, sortedMiddleware: [], middleware: {}, functions: {} };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Manifest `functions` entries for app segments that declared
|
|
129
|
-
* `export const runtime = 'edge'`. Next keys them by the segment's app path
|
|
130
|
-
* (route groups kept, e.g. `/(group)/group/page`) and records the URL the
|
|
131
|
-
* segment answers as its matcher.
|
|
132
|
-
*/
|
|
133
|
-
function edgeFunctionEntries(
|
|
134
|
-
config: ResolvedConfig,
|
|
135
|
-
routes: RouteManifestEntry[],
|
|
136
|
-
): Record<string, unknown> {
|
|
137
|
-
const entries: Record<string, unknown> = {};
|
|
138
|
-
if (!config.appPath) return entries;
|
|
139
|
-
for (const route of routes) {
|
|
140
|
-
const runtime = route.segmentConfig?.runtime;
|
|
141
|
-
if (runtime !== 'edge' && runtime !== 'experimental-edge') continue;
|
|
142
|
-
const page = appManifestKey(config.appPath, route.file);
|
|
143
|
-
if (!page) continue;
|
|
144
|
-
const regions = preferredRegionForRoute(route);
|
|
145
|
-
entries[page] = {
|
|
146
|
-
files: [],
|
|
147
|
-
name: `app${page}`,
|
|
148
|
-
page,
|
|
149
|
-
matchers: [{ regexp: `^${routeMatcherRegexp(route.route)}$`, originalSource: route.route }],
|
|
150
|
-
wasm: [],
|
|
151
|
-
assets: [],
|
|
152
|
-
env: {},
|
|
153
|
-
...(regions ? { regions } : {}),
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
return entries;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// `<app>/(group)/group/page.tsx` → `/(group)/group/page`.
|
|
160
|
-
function appManifestKey(appPath: string, file: string): string | undefined {
|
|
161
|
-
const relative = toPosixPath(path.relative(appPath, file));
|
|
162
|
-
if (!relative || relative.startsWith('..')) return undefined;
|
|
163
|
-
return `/${relative.replace(/\.[^./]+$/, '')}`;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// The URL regexp Next records for a segment: literal path with each dynamic
|
|
167
|
-
// segment widened to a single path part.
|
|
168
|
-
function routeMatcherRegexp(route: string): string {
|
|
169
|
-
return route.replace(/[|\\{}()[\]^$+*?.]/g, '\\$&').replace(/:([^/\\]+)/g, '[^/]+');
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Compile config.matcher entries into { regexp, originalSource } pairs. With no
|
|
173
|
-
// matcher, the middleware runs on every path: Next records the `/:path*` source
|
|
174
|
-
// and its `^/.*$` regexp.
|
|
175
|
-
function manifestMatchers(config: ProxyConfig | undefined): ManifestMatcher[] {
|
|
176
|
-
const matcher = config?.matcher;
|
|
177
|
-
if (!matcher) return [{ regexp: '^/.*$', originalSource: '/:path*' }];
|
|
178
|
-
const list = Array.isArray(matcher) ? matcher : [matcher];
|
|
179
|
-
return list.map(item => {
|
|
180
|
-
const originalSource = typeof item === 'string' ? item : item.source;
|
|
181
|
-
return { regexp: `^${matcherRegexp(originalSource)}$`, originalSource };
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Mirror src/proxy.ts matcherPattern for the manifest regexp string (kept in
|
|
186
|
-
// sync with the runtime matcher). Raw regex sources pass through unchanged.
|
|
187
|
-
function matcherRegexp(matcher: string): string {
|
|
188
|
-
if (matcher.includes('(')) return matcher;
|
|
189
|
-
if (matcher === '/') return '/';
|
|
190
|
-
let source = '';
|
|
191
|
-
for (const segment of matcher.split('/').filter(Boolean)) {
|
|
192
|
-
if (/^:[^/]+\*$/.test(segment)) source += '(?:/.*)?';
|
|
193
|
-
else if (/^:[^/]+$/.test(segment)) source += '/[^/]+';
|
|
194
|
-
else source += `/${segment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}`;
|
|
195
|
-
}
|
|
196
|
-
return source || '/';
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function proxyRuntime(config: ProxyConfig | undefined): 'edge' | 'nodejs' {
|
|
200
|
-
const runtime = (config as { runtime?: unknown } | undefined)?.runtime;
|
|
201
|
-
return runtime === 'nodejs' ? 'nodejs' : 'edge';
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Record the compiled entry under the `server/` prefix Next uses, forcing a
|
|
205
|
-
// `.js` extension (the manifest tests assert `^server/.+\.(js|mjs|cjs)$`).
|
|
206
|
-
function toServerEntrypoint(entryFile: string): string {
|
|
207
|
-
const posix = toPosixPath(entryFile).replace(/^\.?\//, '');
|
|
208
|
-
const withinServer = posix.startsWith('server/') ? posix : `server/${path.posix.basename(posix)}`;
|
|
209
|
-
return withinServer.replace(/\.[^./]+$/, '.js');
|
|
210
|
-
}
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
forwardRef,
|
|
5
|
-
useCallback,
|
|
6
|
-
useEffect,
|
|
7
|
-
useLayoutEffect,
|
|
8
|
-
useRef,
|
|
9
|
-
useState,
|
|
10
|
-
} from 'preact/compat';
|
|
11
|
-
import type { Ref } from 'preact/compat';
|
|
12
|
-
import type { JSX } from 'preact';
|
|
13
|
-
import { getImagesConfig, resolveImageProps } from './image-props';
|
|
14
|
-
import type { ImageProps, ResolvedImagesConfig } from './image-props';
|
|
15
|
-
|
|
16
|
-
const useSettleEffect = (!process.browser && typeof window === 'undefined') ? useEffect : useLayoutEffect;
|
|
17
|
-
|
|
18
|
-
// The initial hydration pass, before the entry flips __NEXT_HYDRATED (a
|
|
19
|
-
// microtask after the island mounts). Layout effects run inside it, so an image
|
|
20
|
-
// seen here came from the server document — one rendered by a later client
|
|
21
|
-
// update (a click) did not.
|
|
22
|
-
function hydrating(): boolean {
|
|
23
|
-
return (
|
|
24
|
-
(process.browser || typeof window !== 'undefined') &&
|
|
25
|
-
!(window as { __NEXT_HYDRATED?: boolean }).__NEXT_HYDRATED
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
type OnLoad = NonNullable<ImageProps['onLoad']>;
|
|
30
|
-
type OnLoadingComplete = NonNullable<ImageProps['onLoadingComplete']>;
|
|
31
|
-
type ImageClientProps = ImageProps & { __pnextConfig?: ResolvedImagesConfig };
|
|
32
|
-
|
|
33
|
-
function handleLoading(
|
|
34
|
-
img: HTMLImageElement | null,
|
|
35
|
-
placeholder: string,
|
|
36
|
-
onLoadRef: { current: OnLoad | undefined },
|
|
37
|
-
onLoadingCompleteRef: { current: OnLoadingComplete | undefined },
|
|
38
|
-
setBlurComplete: (b: boolean) => void,
|
|
39
|
-
): void {
|
|
40
|
-
if (!img) return;
|
|
41
|
-
const src = img.src;
|
|
42
|
-
const marker = img as HTMLImageElement & { 'data-loaded-src'?: string };
|
|
43
|
-
if (marker['data-loaded-src'] === src) return;
|
|
44
|
-
marker['data-loaded-src'] = src;
|
|
45
|
-
const p = 'decode' in img ? img.decode() : Promise.resolve();
|
|
46
|
-
void p.catch(() => undefined).then(() => {
|
|
47
|
-
if (!img.parentElement || !img.isConnected) return;
|
|
48
|
-
if (placeholder !== 'empty') setBlurComplete(true);
|
|
49
|
-
if (onLoadRef.current) {
|
|
50
|
-
const event = new Event('load');
|
|
51
|
-
Object.defineProperty(event, 'target', { writable: false, value: img });
|
|
52
|
-
let prevented = false;
|
|
53
|
-
let stopped = false;
|
|
54
|
-
onLoadRef.current({
|
|
55
|
-
...(event as unknown as Record<string, unknown>),
|
|
56
|
-
nativeEvent: event,
|
|
57
|
-
currentTarget: img,
|
|
58
|
-
target: img,
|
|
59
|
-
isDefaultPrevented: () => prevented,
|
|
60
|
-
isPropagationStopped: () => stopped,
|
|
61
|
-
persist: () => undefined,
|
|
62
|
-
preventDefault: () => {
|
|
63
|
-
prevented = true;
|
|
64
|
-
event.preventDefault();
|
|
65
|
-
},
|
|
66
|
-
stopPropagation: () => {
|
|
67
|
-
stopped = true;
|
|
68
|
-
event.stopPropagation();
|
|
69
|
-
},
|
|
70
|
-
} as unknown as JSX.TargetedEvent<HTMLImageElement, Event>);
|
|
71
|
-
}
|
|
72
|
-
if (onLoadingCompleteRef.current) onLoadingCompleteRef.current(img);
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function useMergedRef<T>(refA: Ref<T> | undefined, refB: Ref<T> | undefined): (el: T | null) => void {
|
|
77
|
-
const cleanupA = useRef<(() => void) | null>(null);
|
|
78
|
-
const cleanupB = useRef<(() => void) | null>(null);
|
|
79
|
-
return useCallback(
|
|
80
|
-
(current: T | null) => {
|
|
81
|
-
if (current === null) {
|
|
82
|
-
cleanupA.current?.();
|
|
83
|
-
cleanupA.current = null;
|
|
84
|
-
cleanupB.current?.();
|
|
85
|
-
cleanupB.current = null;
|
|
86
|
-
} else {
|
|
87
|
-
if (refA) cleanupA.current = applyRef(refA, current);
|
|
88
|
-
if (refB) cleanupB.current = applyRef(refB, current);
|
|
89
|
-
}
|
|
90
|
-
},
|
|
91
|
-
[refA, refB],
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function applyRef<T>(ref: NonNullable<Ref<T>>, current: T): () => void {
|
|
96
|
-
if (typeof ref === 'function') {
|
|
97
|
-
const cleanup = ref(current);
|
|
98
|
-
return typeof cleanup === 'function' ? cleanup : () => (ref as (v: T | null) => void)(null);
|
|
99
|
-
}
|
|
100
|
-
(ref as { current: T | null }).current = current;
|
|
101
|
-
return () => {
|
|
102
|
-
(ref as { current: T | null }).current = null;
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const Image = forwardRef<HTMLImageElement, ImageClientProps>(function Image(
|
|
107
|
-
{ __pnextConfig, ...imageProps },
|
|
108
|
-
forwardedRef,
|
|
109
|
-
) {
|
|
110
|
-
const config = __pnextConfig ?? getImagesConfig();
|
|
111
|
-
const [blurComplete, setBlurComplete] = useState(false);
|
|
112
|
-
const [showAltText, setShowAltText] = useState(false);
|
|
113
|
-
const { props, meta } = resolveImageProps(imageProps, config, blurComplete, showAltText);
|
|
114
|
-
|
|
115
|
-
const { onLoad, onError, onLoadingComplete } = imageProps;
|
|
116
|
-
const onLoadRef = useRef(onLoad);
|
|
117
|
-
useEffect(() => {
|
|
118
|
-
onLoadRef.current = onLoad;
|
|
119
|
-
}, [onLoad]);
|
|
120
|
-
const onLoadingCompleteRef = useRef(onLoadingComplete);
|
|
121
|
-
useEffect(() => {
|
|
122
|
-
onLoadingCompleteRef.current = onLoadingComplete;
|
|
123
|
-
}, [onLoadingComplete]);
|
|
124
|
-
|
|
125
|
-
const placeholder = meta.placeholder;
|
|
126
|
-
const renderedSrc = typeof props.src === 'string' ? props.src : '';
|
|
127
|
-
const insertedImgRef = useRef<HTMLImageElement | null>(null);
|
|
128
|
-
const settledSrcRef = useRef<string | undefined>(undefined);
|
|
129
|
-
// True while an error the app must not see is outstanding: the server-rendered
|
|
130
|
-
// request that was already in flight when this component mounted. See below.
|
|
131
|
-
const swallowErrorRef = useRef(false);
|
|
132
|
-
useSettleEffect(() => {
|
|
133
|
-
const img = insertedImgRef.current;
|
|
134
|
-
if (img === null || settledSrcRef.current === renderedSrc) return;
|
|
135
|
-
settledSrcRef.current = renderedSrc;
|
|
136
|
-
// An error on a server-rendered image happens before onError is attached,
|
|
137
|
-
// so it is lost — Next re-issues the request once at mount to surface it.
|
|
138
|
-
if (onError) {
|
|
139
|
-
if (img.complete) {
|
|
140
|
-
const currentSrc = img.src;
|
|
141
|
-
img.src = currentSrc;
|
|
142
|
-
} else if (hydrating()) {
|
|
143
|
-
// Same situation, mid-flight: the request started with the document,
|
|
144
|
-
// so its outcome still predates this mount. Swallow it and re-issue
|
|
145
|
-
// once it lands, so onError sees an error raised against this mount.
|
|
146
|
-
swallowErrorRef.current = true;
|
|
147
|
-
img.addEventListener(
|
|
148
|
-
'error',
|
|
149
|
-
() => {
|
|
150
|
-
swallowErrorRef.current = false;
|
|
151
|
-
const failedSrc = img.src;
|
|
152
|
-
img.src = failedSrc;
|
|
153
|
-
},
|
|
154
|
-
{ once: true },
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
const settle = () =>
|
|
159
|
-
handleLoading(img, placeholder, onLoadRef, onLoadingCompleteRef, setBlurComplete);
|
|
160
|
-
if (img.complete) settle();
|
|
161
|
-
}, [renderedSrc, placeholder, onError]);
|
|
162
|
-
|
|
163
|
-
const ref = useMergedRef<HTMLImageElement>(forwardedRef, insertedImgRef);
|
|
164
|
-
const extra = imageProps as unknown as {
|
|
165
|
-
crossOrigin?: string;
|
|
166
|
-
referrerPolicy?: string;
|
|
167
|
-
fetchPriority?: string;
|
|
168
|
-
};
|
|
169
|
-
const preloadLink =
|
|
170
|
-
meta.preload ? (
|
|
171
|
-
<link
|
|
172
|
-
rel="preload"
|
|
173
|
-
as="image"
|
|
174
|
-
href={meta.imgAttributes.srcSet ? undefined : meta.imgAttributes.src}
|
|
175
|
-
{...({
|
|
176
|
-
imagesrcset: meta.imgAttributes.srcSet,
|
|
177
|
-
imagesizes: meta.imgAttributes.sizes,
|
|
178
|
-
crossOrigin: extra.crossOrigin,
|
|
179
|
-
referrerPolicy: extra.referrerPolicy,
|
|
180
|
-
fetchpriority: extra.fetchPriority,
|
|
181
|
-
} as Record<string, unknown>)}
|
|
182
|
-
/>
|
|
183
|
-
) : null;
|
|
184
|
-
|
|
185
|
-
return (
|
|
186
|
-
<>
|
|
187
|
-
{preloadLink}
|
|
188
|
-
<img
|
|
189
|
-
{...props}
|
|
190
|
-
data-nimg={meta.fill ? 'fill' : '1'}
|
|
191
|
-
ref={ref}
|
|
192
|
-
onLoad={event => {
|
|
193
|
-
handleLoading(
|
|
194
|
-
event.currentTarget,
|
|
195
|
-
placeholder,
|
|
196
|
-
onLoadRef,
|
|
197
|
-
onLoadingCompleteRef,
|
|
198
|
-
setBlurComplete,
|
|
199
|
-
);
|
|
200
|
-
}}
|
|
201
|
-
onError={event => {
|
|
202
|
-
setShowAltText(true);
|
|
203
|
-
if (placeholder !== 'empty') setBlurComplete(true);
|
|
204
|
-
// The pre-mount failure is re-issued by the settle effect; the app
|
|
205
|
-
// hears about the retry, not the request that predated its handler.
|
|
206
|
-
if (swallowErrorRef.current) return;
|
|
207
|
-
onError?.(event);
|
|
208
|
-
}}
|
|
209
|
-
/>
|
|
210
|
-
</>
|
|
211
|
-
);
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
export default Image;
|
|
215
|
-
export { Image };
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { scanFirstPartySource } from './image-usage';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Build-time app fact: can any first-party source render `<Link legacyBehavior>`? The legacy child path
|
|
5
|
-
* (child validation, the deprecation notice, the server/lazy child diagnostics, cloneElement) is a
|
|
6
|
-
* meaningful slice of `next/link`, and next/link is initial on every page that links anywhere.
|
|
7
|
-
*
|
|
8
|
-
* One-sided like the blur gate: every unreadable case answers "yes". A wrong "no" renders the legacy
|
|
9
|
-
* child shape on the server and a plain anchor on the client - a hydration mismatch. The scan sees the
|
|
10
|
-
* app and its workspace packages, not registry dependencies.
|
|
11
|
-
*/
|
|
12
|
-
const legacyProp = /\blegacyBehavior\b/;
|
|
13
|
-
|
|
14
|
-
/** A Link re-exported from here can be rendered by a file this scan can't tie
|
|
15
|
-
* back to `next/link`, so treat the re-export itself as usage. */
|
|
16
|
-
const reexportedLink = /export\s[^;]*from\s*['"]next\/link['"]/;
|
|
17
|
-
|
|
18
|
-
const cache = new Map<string, boolean>();
|
|
19
|
-
|
|
20
|
-
export function appUsesLegacyLink(root: string) {
|
|
21
|
-
const cached = cache.get(root);
|
|
22
|
-
if (cached !== undefined) return cached;
|
|
23
|
-
const used = scanFirstPartySource(
|
|
24
|
-
root,
|
|
25
|
-
source => legacyProp.test(source) || reexportedLink.test(source),
|
|
26
|
-
);
|
|
27
|
-
cache.set(root, used);
|
|
28
|
-
return used;
|
|
29
|
-
}
|
package/src/css/index.ts
DELETED
package/src/render/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './renderer';
|