@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
|
@@ -2,27 +2,27 @@
|
|
|
2
2
|
// compat hooks subscribe to, plus the post-navigation scroll action. All share one tier - an entry
|
|
3
3
|
// that reads router state pulls this in at first paint, one that only has a <Link> gets it with the
|
|
4
4
|
// runtime chunk - and none may sit in ./hub, which is a chunk shared with the runtime.
|
|
5
|
-
import { locationKey, routerState } from './hub'
|
|
6
|
-
import type { NavigationScrollAction, NavigationScrollOptions } from './types'
|
|
5
|
+
import { locationKey, routerState } from './hub'
|
|
6
|
+
import type { NavigationScrollAction, NavigationScrollOptions } from './types'
|
|
7
7
|
|
|
8
|
-
export let navigationScrollAction: NavigationScrollAction | undefined
|
|
8
|
+
export let navigationScrollAction: NavigationScrollAction | undefined
|
|
9
9
|
|
|
10
10
|
export function setNavigationScrollAction(action: NavigationScrollAction | undefined) {
|
|
11
|
-
navigationScrollAction = action
|
|
11
|
+
navigationScrollAction = action
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export function scheduleNavigationScroll(url: URL, options: NavigationScrollOptions = {}) {
|
|
15
|
-
navigationScrollAction?.(url, options)
|
|
15
|
+
navigationScrollAction?.(url, options)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export function locationListeners() {
|
|
19
|
-
window.__PNEXT_LOCATION_LISTENERS__ ??= new Set()
|
|
20
|
-
return window.__PNEXT_LOCATION_LISTENERS__
|
|
19
|
+
window.__PNEXT_LOCATION_LISTENERS__ ??= new Set()
|
|
20
|
+
return window.__PNEXT_LOCATION_LISTENERS__
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export function emitLocationChange() {
|
|
24
|
-
routerState.observedLocationKey = locationKey()
|
|
25
|
-
for (const listener of [...locationListeners()]) listener()
|
|
24
|
+
routerState.observedLocationKey = locationKey()
|
|
25
|
+
for (const listener of [...locationListeners()]) listener()
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
// Fires at the start of every soft navigation (link click, router.push,
|
|
@@ -30,24 +30,24 @@ export function emitLocationChange() {
|
|
|
30
30
|
// different navigation supersedes it.
|
|
31
31
|
// Annotated pure so an entry that subscribes to nothing (a link-only page)
|
|
32
32
|
// shakes the whole seam out of its first-paint closure.
|
|
33
|
-
export const navigationStartListeners = /* @__PURE__ */ new Set<() => void>()
|
|
33
|
+
export const navigationStartListeners = /* @__PURE__ */ new Set<() => void>()
|
|
34
34
|
|
|
35
35
|
export function onNavigationStart(listener: () => void) {
|
|
36
|
-
navigationStartListeners.add(listener)
|
|
37
|
-
return () => navigationStartListeners.delete(listener)
|
|
36
|
+
navigationStartListeners.add(listener)
|
|
37
|
+
return () => navigationStartListeners.delete(listener)
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export function emitNavigationStart() {
|
|
41
|
-
for (const listener of [...navigationStartListeners]) listener()
|
|
41
|
+
for (const listener of [...navigationStartListeners]) listener()
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export const navigationCommitListeners = /* @__PURE__ */ new Set<() => void>()
|
|
44
|
+
export const navigationCommitListeners = /* @__PURE__ */ new Set<() => void>()
|
|
45
45
|
|
|
46
46
|
export function onNavigationCommit(listener: () => void) {
|
|
47
|
-
navigationCommitListeners.add(listener)
|
|
48
|
-
return () => navigationCommitListeners.delete(listener)
|
|
47
|
+
navigationCommitListeners.add(listener)
|
|
48
|
+
return () => navigationCommitListeners.delete(listener)
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export function emitNavigationCommit() {
|
|
52
|
-
for (const listener of [...navigationCommitListeners]) listener()
|
|
52
|
+
for (const listener of [...navigationCommitListeners]) listener()
|
|
53
53
|
}
|
|
@@ -5,32 +5,32 @@
|
|
|
5
5
|
// page whose client graph reads router state (`api/client-navigation`) seeds at
|
|
6
6
|
// first paint and pulls this in; a page that only has a <Link> never reads an id
|
|
7
7
|
// before the navigation runtime lands, so this rides the idle chunk with it.
|
|
8
|
-
import { routerState } from './hub'
|
|
8
|
+
import { routerState } from './hub'
|
|
9
9
|
|
|
10
|
-
export const HISTORY_BFCACHE_ID_KEY = '__pnextBfcacheId'
|
|
10
|
+
export const HISTORY_BFCACHE_ID_KEY = '__pnextBfcacheId'
|
|
11
11
|
|
|
12
12
|
export function historyState(): Record<string, unknown> {
|
|
13
|
-
const state = history.state as Record<string, unknown> | null
|
|
14
|
-
return state && typeof state === 'object' ? state : {}
|
|
13
|
+
const state = history.state as Record<string, unknown> | null
|
|
14
|
+
return state && typeof state === 'object' ? state : {}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export function historyBfcacheId(
|
|
18
18
|
state: Record<string, unknown> = historyState(),
|
|
19
19
|
): string | undefined {
|
|
20
|
-
const value = state[HISTORY_BFCACHE_ID_KEY]
|
|
21
|
-
return typeof value === 'string' ? value : undefined
|
|
20
|
+
const value = state[HISTORY_BFCACHE_ID_KEY]
|
|
21
|
+
return typeof value === 'string' ? value : undefined
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function newHistoryId(prefix: string) {
|
|
25
|
-
return `${prefix}${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}
|
|
25
|
+
return `${prefix}${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export function newBfcacheId() {
|
|
29
|
-
return newHistoryId('b_')
|
|
29
|
+
return newHistoryId('b_')
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export function newEntryId() {
|
|
33
|
-
return newHistoryId('e')
|
|
33
|
+
return newHistoryId('e')
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -48,12 +48,12 @@ export function newEntryId() {
|
|
|
48
48
|
* before it can navigate away.
|
|
49
49
|
*/
|
|
50
50
|
export function seedHistoryEntry() {
|
|
51
|
-
if (!process.browser && typeof window === 'undefined') return
|
|
52
|
-
const state = historyState()
|
|
53
|
-
const entryId = state.__pnextEntry
|
|
54
|
-
const hasEntryId = typeof entryId === 'string'
|
|
55
|
-
routerState.renderedEntryId = hasEntryId ? entryId : newEntryId()
|
|
56
|
-
if (historyBfcacheId(state) && hasEntryId) return
|
|
51
|
+
if (!process.browser && typeof window === 'undefined') return
|
|
52
|
+
const state = historyState()
|
|
53
|
+
const entryId = state.__pnextEntry
|
|
54
|
+
const hasEntryId = typeof entryId === 'string'
|
|
55
|
+
routerState.renderedEntryId = hasEntryId ? entryId : newEntryId()
|
|
56
|
+
if (historyBfcacheId(state) && hasEntryId) return
|
|
57
57
|
try {
|
|
58
58
|
history.replaceState(
|
|
59
59
|
{
|
|
@@ -63,7 +63,7 @@ export function seedHistoryEntry() {
|
|
|
63
63
|
},
|
|
64
64
|
'',
|
|
65
65
|
location.href,
|
|
66
|
-
)
|
|
66
|
+
)
|
|
67
67
|
} catch {
|
|
68
68
|
// Without a stable id, bfcache-keyed subtrees fall back to remounting.
|
|
69
69
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// out of an entry: this module is a chunk SHARED with the runtime chunk, so anything the runtime
|
|
9
9
|
// imports from here is kept in the first-paint chunk regardless. ./policies, ./history, ./events and
|
|
10
10
|
// the bfcache route key all ride the idle chunk for that reason.
|
|
11
|
-
import type { EntryModule } from './types'
|
|
11
|
+
import type { EntryModule } from './types'
|
|
12
12
|
|
|
13
13
|
// Router-wide mutable state SHARED BY BOTH TIERS. Every field here is committed by more than one
|
|
14
14
|
// region (install, soft nav, popstate), so it lives on one record: a module-level `let` can only be
|
|
@@ -28,24 +28,24 @@ export const routerState = {
|
|
|
28
28
|
// same id — an app-level shallow pushState now carries the id forward — needs
|
|
29
29
|
// no fetch and no swap: the DOM already is this entry's.
|
|
30
30
|
renderedEntryId: undefined as string | undefined,
|
|
31
|
-
}
|
|
31
|
+
}
|
|
32
32
|
|
|
33
33
|
export function locationKey() {
|
|
34
|
-
return typeof location === 'undefined' ? '' : location.pathname + location.search
|
|
34
|
+
return typeof location === 'undefined' ? '' : location.pathname + location.search
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
// Installers that only the navigation runtime ever observes — compat's policy
|
|
38
38
|
// seams (segment cache, prefetch windows, scroll, stylesheet order). Registering
|
|
39
39
|
// one costs first paint a closure holding an `import()`; the facade runs them
|
|
40
40
|
// while the runtime chunk loads, so a policy is in place before the first fetch.
|
|
41
|
-
const deferredInstalls: (() => unknown)[] = []
|
|
41
|
+
const deferredInstalls: (() => unknown)[] = []
|
|
42
42
|
|
|
43
43
|
export function registerDeferredInstall(install: () => unknown): void {
|
|
44
|
-
deferredInstalls.push(install)
|
|
44
|
+
deferredInstalls.push(install)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
export function takeDeferredInstalls(): (() => unknown)[] {
|
|
48
|
-
return deferredInstalls.splice(0)
|
|
48
|
+
return deferredInstalls.splice(0)
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// Compat-registered policy seams FIRST PAINT ITSELF READS. The rest (prefetch
|
|
@@ -55,55 +55,55 @@ export function takeDeferredInstalls(): (() => unknown)[] {
|
|
|
55
55
|
// `javascript:` URLs are a navigation-time XSS vector; the router refuses them
|
|
56
56
|
// at every entry point. The generic block lives in core; the user-facing
|
|
57
57
|
// message is framework-specific, so compat supplies a reporter/thrower.
|
|
58
|
-
export let blockedJsUrlReporter: ((url: string) => void) | undefined
|
|
58
|
+
export let blockedJsUrlReporter: ((url: string) => void) | undefined
|
|
59
59
|
|
|
60
60
|
export function setBlockedJavascriptUrlReporter(reporter: (url: string) => void) {
|
|
61
|
-
blockedJsUrlReporter = reporter
|
|
61
|
+
blockedJsUrlReporter = reporter
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
// basePath boundary: under a configured basePath a same-origin URL OUTSIDE the
|
|
65
65
|
// basePath (a `basePath:false` target) must hard-navigate, not soft-swap. The
|
|
66
66
|
// check is a next.config concern, so compat registers it; pure core returns
|
|
67
67
|
// false (every same-origin URL stays soft-navigable).
|
|
68
|
-
export let softNavBoundary: ((url: URL) => boolean) | undefined
|
|
68
|
+
export let softNavBoundary: ((url: URL) => boolean) | undefined
|
|
69
69
|
|
|
70
70
|
/** Register the compat soft-nav boundary predicate (true → hard navigate). */
|
|
71
71
|
export function setSoftNavBoundary(predicate: (url: URL) => boolean) {
|
|
72
|
-
softNavBoundary = predicate
|
|
72
|
+
softNavBoundary = predicate
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
export function isJavascriptUrl(href: string) {
|
|
76
76
|
// eslint-disable-next-line no-control-regex
|
|
77
|
-
return /^[\u0000-\u0020]*javascript:/i.test(href)
|
|
77
|
+
return /^[\u0000-\u0020]*javascript:/i.test(href)
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
/** True when the URL was a blocked javascript: URL (caller must not navigate). */
|
|
81
81
|
export function blockJavascriptUrl(href: string): boolean {
|
|
82
|
-
if (!isJavascriptUrl(href)) return false
|
|
83
|
-
if (blockedJsUrlReporter) blockedJsUrlReporter(href)
|
|
82
|
+
if (!isJavascriptUrl(href)) return false
|
|
83
|
+
if (blockedJsUrlReporter) blockedJsUrlReporter(href)
|
|
84
84
|
else if (process.browser || typeof window !== 'undefined') {
|
|
85
|
-
window.dispatchEvent(new CustomEvent('pnext:blocked-javascript-url', { detail: href }))
|
|
85
|
+
window.dispatchEvent(new CustomEvent('pnext:blocked-javascript-url', { detail: href }))
|
|
86
86
|
}
|
|
87
|
-
return true
|
|
87
|
+
return true
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// Whether a href is soft-navigable at all — the one navigation decision the
|
|
91
91
|
// first-paint hub has to make synchronously, before the router chunk lands.
|
|
92
92
|
|
|
93
93
|
export function resolveSoftUrl(href: string) {
|
|
94
|
-
let url: URL
|
|
94
|
+
let url: URL
|
|
95
95
|
try {
|
|
96
|
-
url = new URL(href, location.href)
|
|
96
|
+
url = new URL(href, location.href)
|
|
97
97
|
} catch {
|
|
98
|
-
return null
|
|
98
|
+
return null
|
|
99
99
|
}
|
|
100
|
-
if (url.origin !== location.origin) return null
|
|
100
|
+
if (url.origin !== location.origin) return null
|
|
101
101
|
// Under a configured basePath, a same-origin URL that falls OUTSIDE the
|
|
102
102
|
// basePath (a `basePath:false` target) is not part of the app — it must be a
|
|
103
103
|
// real browser navigation, not a soft swap. Pure core / no-basePath: never
|
|
104
104
|
// outside (predicate returns false), so behavior is unchanged.
|
|
105
|
-
if (softNavBoundary?.(url)) return null
|
|
106
|
-
return url
|
|
105
|
+
if (softNavBoundary?.(url)) return null
|
|
106
|
+
return url
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
// The synchronous half of link interception: everything a click's default
|
|
@@ -113,16 +113,16 @@ export function resolveSoftUrl(href: string) {
|
|
|
113
113
|
// and commits immediately.
|
|
114
114
|
|
|
115
115
|
export interface LinkClickTarget {
|
|
116
|
-
link: HTMLAnchorElement
|
|
117
|
-
url: URL
|
|
118
|
-
replace: boolean
|
|
119
|
-
scroll: boolean
|
|
116
|
+
link: HTMLAnchorElement
|
|
117
|
+
url: URL
|
|
118
|
+
replace: boolean
|
|
119
|
+
scroll: boolean
|
|
120
120
|
}
|
|
121
121
|
|
|
122
122
|
export function linkFromEvent(event: Event) {
|
|
123
|
-
const target = event.target
|
|
124
|
-
if (!(target instanceof Element)) return null
|
|
125
|
-
return target.closest<HTMLAnchorElement>('a[data-pnext-link]')
|
|
123
|
+
const target = event.target
|
|
124
|
+
if (!(target instanceof Element)) return null
|
|
125
|
+
return target.closest<HTMLAnchorElement>('a[data-pnext-link]')
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
/**
|
|
@@ -132,51 +132,51 @@ export function linkFromEvent(event: Event) {
|
|
|
132
132
|
* link pointing outside the app (both return null having acted).
|
|
133
133
|
*/
|
|
134
134
|
export function linkClickTarget(event: MouseEvent): LinkClickTarget | null {
|
|
135
|
-
if (event.defaultPrevented) return null
|
|
135
|
+
if (event.defaultPrevented) return null
|
|
136
136
|
if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
|
|
137
|
-
return null
|
|
138
|
-
const link = linkFromEvent(event)
|
|
139
|
-
if (!link) return null
|
|
140
|
-
if (link.target && link.target !== '_self') return null
|
|
141
|
-
if (link.hasAttribute('download')) return null
|
|
142
|
-
const href = link.getAttribute('data-pnext-blocked-href') ?? link.getAttribute('href')
|
|
143
|
-
if (!href) return null
|
|
137
|
+
return null
|
|
138
|
+
const link = linkFromEvent(event)
|
|
139
|
+
if (!link) return null
|
|
140
|
+
if (link.target && link.target !== '_self') return null
|
|
141
|
+
if (link.hasAttribute('download')) return null
|
|
142
|
+
const href = link.getAttribute('data-pnext-blocked-href') ?? link.getAttribute('href')
|
|
143
|
+
if (!href) return null
|
|
144
144
|
// Refuse javascript: URLs before the browser can run them (the anchor's
|
|
145
145
|
// default action is cancellable from this bubble-phase listener).
|
|
146
146
|
if (blockJavascriptUrl(href)) {
|
|
147
|
-
event.preventDefault()
|
|
148
|
-
return null
|
|
147
|
+
event.preventDefault()
|
|
148
|
+
return null
|
|
149
149
|
}
|
|
150
|
-
const replace = link.getAttribute('data-pnext-replace') === 'true'
|
|
151
|
-
const url = resolveSoftUrl(href)
|
|
150
|
+
const replace = link.getAttribute('data-pnext-replace') === 'true'
|
|
151
|
+
const url = resolveSoftUrl(href)
|
|
152
152
|
if (!url) {
|
|
153
153
|
if (replace) {
|
|
154
|
-
event.preventDefault()
|
|
155
|
-
window.location.replace(href)
|
|
154
|
+
event.preventDefault()
|
|
155
|
+
window.location.replace(href)
|
|
156
156
|
}
|
|
157
|
-
return null
|
|
157
|
+
return null
|
|
158
158
|
}
|
|
159
|
-
return { link, url, replace, scroll: link.getAttribute('data-pnext-scroll') !== 'false' }
|
|
159
|
+
return { link, url, replace, scroll: link.getAttribute('data-pnext-scroll') !== 'false' }
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
// Route entry modules: the cache of imported entries plus the guard that keeps
|
|
163
163
|
// a router-triggered import from auto-mounting into the live document.
|
|
164
164
|
|
|
165
|
-
export const entryModuleCache = new Map<string, EntryModule>()
|
|
165
|
+
export const entryModuleCache = new Map<string, EntryModule>()
|
|
166
166
|
|
|
167
167
|
// The document's own entry module registers itself at boot. Without this, the first history
|
|
168
168
|
// traversal back to the hard-loaded route pays a real import() - one task yield - and a test reading
|
|
169
169
|
// the DOM right after history.back() catches the DEPARTING page. With every step of the cached-entry
|
|
170
170
|
// restore microtask-only, the commit lands before any post-traversal task can read.
|
|
171
171
|
if (process.browser || typeof window !== 'undefined') {
|
|
172
|
-
(
|
|
172
|
+
;(
|
|
173
173
|
window as unknown as {
|
|
174
|
-
__PNEXT_REGISTER_ENTRY__?: (src: string, module: EntryModule) => void
|
|
174
|
+
__PNEXT_REGISTER_ENTRY__?: (src: string, module: EntryModule) => void
|
|
175
175
|
}
|
|
176
176
|
).__PNEXT_REGISTER_ENTRY__ = (src, module) => {
|
|
177
|
-
const href = entryModuleHref(src)
|
|
178
|
-
if (!entryModuleCache.has(href)) entryModuleCache.set(href, module)
|
|
179
|
-
}
|
|
177
|
+
const href = entryModuleHref(src)
|
|
178
|
+
if (!entryModuleCache.has(href)) entryModuleCache.set(href, module)
|
|
179
|
+
}
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
// Entries auto-mount when the browser loads them as the document's module
|
|
@@ -185,10 +185,9 @@ if (process.browser || typeof window !== 'undefined') {
|
|
|
185
185
|
// counter is only ever non-zero while a router-triggered import is in flight,
|
|
186
186
|
// and hard document loads can never overlap one.
|
|
187
187
|
export function routerImportActive() {
|
|
188
|
-
return (window.__PNEXT_ROUTER_IMPORTS__ ?? 0) > 0
|
|
188
|
+
return (window.__PNEXT_ROUTER_IMPORTS__ ?? 0) > 0
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
export function entryModuleHref(src: string) {
|
|
192
|
-
return new URL(src, location.href).href
|
|
192
|
+
return new URL(src, location.href).href
|
|
193
193
|
}
|
|
194
|
-
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// First-paint router hub. Generated client entries import this module, so every byte it statically
|
|
2
2
|
// reaches is on the critical path of every route: keep it to link interception, history events and
|
|
3
|
-
// the seams compat registers into, all of which live in ./
|
|
4
|
-
// sits behind ./
|
|
3
|
+
// the seams compat registers into, all of which live in ./hub. The navigation runtime itself
|
|
4
|
+
// sits behind ./runtime and is import()ed on idle into its own chunk.
|
|
5
5
|
//
|
|
6
6
|
// Everything routed through this file is a facade over that chunk. That is the point: a static
|
|
7
7
|
// import of softNavigate anywhere in core or compat would otherwise pull the whole runtime back into
|
|
8
|
-
// first paint. State BOTH tiers touch lives in ./
|
|
8
|
+
// first paint. State BOTH tiers touch lives in ./hub and is imported by both, so a setter
|
|
9
9
|
// called before the chunk lands is not replayed - it is already in place when the runtime reads it.
|
|
10
10
|
// Chunk membership is decided per module, so each seam is its own module.
|
|
11
11
|
import {
|
|
@@ -14,9 +14,9 @@ import {
|
|
|
14
14
|
resolveSoftUrl,
|
|
15
15
|
routerState,
|
|
16
16
|
takeDeferredInstalls,
|
|
17
|
-
} from './
|
|
18
|
-
import type { LinkClickTarget } from './
|
|
19
|
-
import type { PrefetchOptions, SoftNavigateOptions } from './
|
|
17
|
+
} from './hub'
|
|
18
|
+
import type { LinkClickTarget } from './hub'
|
|
19
|
+
import type { PrefetchOptions, SoftNavigateOptions } from './types'
|
|
20
20
|
|
|
21
21
|
export {
|
|
22
22
|
blockJavascriptUrl,
|
|
@@ -25,8 +25,8 @@ export {
|
|
|
25
25
|
routerImportActive,
|
|
26
26
|
setBlockedJavascriptUrlReporter,
|
|
27
27
|
setSoftNavBoundary,
|
|
28
|
-
} from './
|
|
29
|
-
// NOTE: ./
|
|
28
|
+
} from './hub'
|
|
29
|
+
// NOTE: ./policies, ./history and ./events are deliberately NOT re-exported
|
|
30
30
|
// here. esbuild assigns a chunk per set-of-reaching-entries, computed on the module graph, so a
|
|
31
31
|
// re-export edge from this file lands any of them in the first-paint chunk even though every symbol
|
|
32
32
|
// tree-shakes away. Their consumers import them directly.
|
|
@@ -40,11 +40,11 @@ export type {
|
|
|
40
40
|
SegmentCachePolicy,
|
|
41
41
|
SegmentCacheRecord,
|
|
42
42
|
StylesheetReconciler,
|
|
43
|
-
} from './
|
|
43
|
+
} from './types'
|
|
44
44
|
|
|
45
|
-
type RouterRuntime = typeof import('./
|
|
45
|
+
type RouterRuntime = typeof import('./runtime')
|
|
46
46
|
|
|
47
|
-
let runtime: Promise<RouterRuntime> | undefined
|
|
47
|
+
let runtime: Promise<RouterRuntime> | undefined
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Load (once) and run against the idle tier. Every facade export chains off
|
|
@@ -55,15 +55,15 @@ function withRouter<T>(use: (module: RouterRuntime) => T): Promise<Awaited<T>> {
|
|
|
55
55
|
// Deferred installers land with the runtime chunk, before anything reads a
|
|
56
56
|
// policy. Drained inside the chain (not at call time) so an installer any
|
|
57
57
|
// entry registers after the first facade call still runs.
|
|
58
|
-
runtime ??= import('./
|
|
59
|
-
await Promise.all(takeDeferredInstalls().map(install => install()))
|
|
60
|
-
return module
|
|
61
|
-
})
|
|
62
|
-
return runtime.then(use) as Promise<Awaited<T
|
|
58
|
+
runtime ??= import('./runtime').then(async module => {
|
|
59
|
+
await Promise.all(takeDeferredInstalls().map(install => install()))
|
|
60
|
+
return module
|
|
61
|
+
})
|
|
62
|
+
return runtime.then(use) as Promise<Awaited<T>>
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
export function softNavigate(href: string, options?: SoftNavigateOptions) {
|
|
66
|
-
return withRouter(module => module.softNavigate(href, options))
|
|
66
|
+
return withRouter(module => module.softNavigate(href, options))
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
export function prefetchRoute(href: string, options?: PrefetchOptions) {
|
|
@@ -72,49 +72,49 @@ export function prefetchRoute(href: string, options?: PrefetchOptions) {
|
|
|
72
72
|
// the runtime. The throw is spelled out here rather than in the hub because the hub is a chunk
|
|
73
73
|
// shared with the runtime. Only an unparseable href throws - a cross-origin or out-of-basePath one
|
|
74
74
|
// is a silent miss.
|
|
75
|
-
const url = resolveSoftUrl(href)
|
|
75
|
+
const url = resolveSoftUrl(href)
|
|
76
76
|
if (!url) {
|
|
77
77
|
if (options?.strict) {
|
|
78
78
|
try {
|
|
79
|
-
new URL(href, location.href)
|
|
79
|
+
new URL(href, location.href)
|
|
80
80
|
} catch {
|
|
81
|
-
throw new Error(`Cannot prefetch '${href}' because it cannot be converted to a URL.`)
|
|
81
|
+
throw new Error(`Cannot prefetch '${href}' because it cannot be converted to a URL.`)
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
return Promise.resolve(null)
|
|
84
|
+
return Promise.resolve(null)
|
|
85
85
|
}
|
|
86
|
-
return withRouter(module => module.prefetchRoute(url.href, options))
|
|
86
|
+
return withRouter(module => module.prefetchRoute(url.href, options))
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
export function evictClientRouterCache(options?: { rearmVisiblePrefetches?: boolean }) {
|
|
90
|
-
return withRouter(module => module.evictClientRouterCache(options))
|
|
90
|
+
return withRouter(module => module.evictClientRouterCache(options))
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
export function rearmVisiblePrefetches() {
|
|
94
|
-
return withRouter(module => module.rearmVisiblePrefetches())
|
|
94
|
+
return withRouter(module => module.rearmVisiblePrefetches())
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
// A click intercepted before the runtime lands waits for it. The wait is
|
|
98
98
|
// bounded: a chunk that never arrives (offline, a failed deploy) must still
|
|
99
99
|
// navigate, so the queued click falls back to a real browser navigation rather
|
|
100
100
|
// than leaving the user on a dead link.
|
|
101
|
-
const QUEUED_CLICK_TIMEOUT_MS = 3_000
|
|
101
|
+
const QUEUED_CLICK_TIMEOUT_MS = 3_000
|
|
102
102
|
|
|
103
|
-
let pendingClicks: LinkClickTarget[] = []
|
|
104
|
-
let pendingPop = false
|
|
105
|
-
let installedFull = false
|
|
106
|
-
let hardNavTimer: ReturnType<typeof setTimeout> | undefined
|
|
103
|
+
let pendingClicks: LinkClickTarget[] = []
|
|
104
|
+
let pendingPop = false
|
|
105
|
+
let installedFull = false
|
|
106
|
+
let hardNavTimer: ReturnType<typeof setTimeout> | undefined
|
|
107
107
|
|
|
108
108
|
function hubLinkClick(event: MouseEvent) {
|
|
109
|
-
const target = linkClickTarget(event)
|
|
110
|
-
if (!target) return
|
|
111
|
-
event.preventDefault()
|
|
112
|
-
pendingClicks.push(target)
|
|
109
|
+
const target = linkClickTarget(event)
|
|
110
|
+
if (!target) return
|
|
111
|
+
event.preventDefault()
|
|
112
|
+
pendingClicks.push(target)
|
|
113
113
|
hardNavTimer ??= setTimeout(() => {
|
|
114
|
-
const queued = pendingClicks[0]
|
|
115
|
-
if (queued) location.href = queued.url.href
|
|
116
|
-
}, QUEUED_CLICK_TIMEOUT_MS)
|
|
117
|
-
void loadRuntime()
|
|
114
|
+
const queued = pendingClicks[0]
|
|
115
|
+
if (queued) location.href = queued.url.href
|
|
116
|
+
}, QUEUED_CLICK_TIMEOUT_MS)
|
|
117
|
+
void loadRuntime()
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
// The browser has already committed the traversal (URL and history state are
|
|
@@ -122,46 +122,47 @@ function hubLinkClick(event: MouseEvent) {
|
|
|
122
122
|
// popstate; broadcasting here would move `observedLocationKey` and make that
|
|
123
123
|
// handler read the traversal as a shallow one that needs no document.
|
|
124
124
|
function hubPopState() {
|
|
125
|
-
pendingPop = true
|
|
126
|
-
void loadRuntime()
|
|
125
|
+
pendingPop = true
|
|
126
|
+
void loadRuntime()
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function loadRuntime() {
|
|
130
130
|
return withRouter(module => {
|
|
131
131
|
if (!installedFull) {
|
|
132
|
-
installedFull = true
|
|
133
|
-
document.removeEventListener('click', hubLinkClick)
|
|
134
|
-
window.removeEventListener('popstate', hubPopState)
|
|
135
|
-
module.installRouterFull()
|
|
132
|
+
installedFull = true
|
|
133
|
+
document.removeEventListener('click', hubLinkClick)
|
|
134
|
+
window.removeEventListener('popstate', hubPopState)
|
|
135
|
+
module.installRouterFull()
|
|
136
136
|
}
|
|
137
|
-
clearTimeout(hardNavTimer)
|
|
138
|
-
hardNavTimer = undefined
|
|
139
|
-
const clicks = pendingClicks
|
|
140
|
-
pendingClicks = []
|
|
141
|
-
for (const click of clicks) module.commitLinkNavigation(click)
|
|
137
|
+
clearTimeout(hardNavTimer)
|
|
138
|
+
hardNavTimer = undefined
|
|
139
|
+
const clicks = pendingClicks
|
|
140
|
+
pendingClicks = []
|
|
141
|
+
for (const click of clicks) module.commitLinkNavigation(click)
|
|
142
142
|
if (pendingPop) {
|
|
143
|
-
pendingPop = false
|
|
144
|
-
module.onPopState()
|
|
143
|
+
pendingPop = false
|
|
144
|
+
module.onPopState()
|
|
145
145
|
}
|
|
146
|
-
})
|
|
146
|
+
})
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
function whenIdle(run: () => void) {
|
|
150
|
-
if (typeof requestIdleCallback === 'function') requestIdleCallback(() => run(), { timeout: 1000 })
|
|
151
|
-
else setTimeout(run, 1)
|
|
150
|
+
if (typeof requestIdleCallback === 'function') requestIdleCallback(() => run(), { timeout: 1000 })
|
|
151
|
+
else setTimeout(run, 1)
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
export function installRouter() {
|
|
155
|
-
if ((!process.browser && typeof window === 'undefined') || window.__PNEXT_ROUTER_INSTALLED__)
|
|
156
|
-
|
|
157
|
-
|
|
155
|
+
if ((!process.browser && typeof window === 'undefined') || window.__PNEXT_ROUTER_INSTALLED__)
|
|
156
|
+
return
|
|
157
|
+
window.__PNEXT_ROUTER_INSTALLED__ = true
|
|
158
|
+
if ('scrollRestoration' in history) history.scrollRestoration = 'manual'
|
|
158
159
|
// Seed the bfcache departing key with the hard-loaded route so the first
|
|
159
160
|
// navigation away stashes this route's island state under the right key.
|
|
160
161
|
// `locationKey()` IS `bfRouteKey(location.pathname, location.search)` — the
|
|
161
162
|
// hub's own definition — and it is already on the first-paint graph.
|
|
162
|
-
routerState.activeRouteKey = locationKey()
|
|
163
|
+
routerState.activeRouteKey = locationKey()
|
|
163
164
|
|
|
164
|
-
document.addEventListener('click', hubLinkClick)
|
|
165
|
-
window.addEventListener('popstate', hubPopState)
|
|
166
|
-
whenIdle(() => void loadRuntime())
|
|
165
|
+
document.addEventListener('click', hubLinkClick)
|
|
166
|
+
window.addEventListener('popstate', hubPopState)
|
|
167
|
+
whenIdle(() => void loadRuntime())
|
|
167
168
|
}
|