@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
|
@@ -7,18 +7,18 @@
|
|
|
7
7
|
* they were revalidated; consumers compare against their stored-at time.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
11
|
-
import { currentRequest, getWorkUnit } from '../../request/context'
|
|
12
|
-
import { realNow, trackPrerenderCacheFill } from '../../ppr'
|
|
13
|
-
import { cacheHandlerRevalidateTag } from './handler'
|
|
14
|
-
import { modernCacheUpdateTags } from './modern-handler'
|
|
15
|
-
import { escapeRegex } from '../../utils/
|
|
10
|
+
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
11
|
+
import { currentRequest, getWorkUnit } from '../../request/context'
|
|
12
|
+
import { realNow, trackPrerenderCacheFill } from '../../render/ppr'
|
|
13
|
+
import { cacheHandlerRevalidateTag } from './handler'
|
|
14
|
+
import { modernCacheUpdateTags } from './modern-handler'
|
|
15
|
+
import { escapeRegex } from '../../utils/code'
|
|
16
16
|
import {
|
|
17
17
|
prerenderErrorCollectionActive,
|
|
18
18
|
recordPrerenderError,
|
|
19
19
|
unstableCacheDynamicApiMessage,
|
|
20
20
|
useCacheDynamicApiMessage,
|
|
21
|
-
} from './build-prerender-errors'
|
|
21
|
+
} from './build-prerender-errors'
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Draft mode (a __prerender_bypass cookie on the active request) bypasses
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
* cached values untouched (Next semantics).
|
|
27
27
|
*/
|
|
28
28
|
export function draftModeBypassActive() {
|
|
29
|
-
return currentRequest()?.cookies?.has('__prerender_bypass') ?? false
|
|
29
|
+
return currentRequest()?.cookies?.has('__prerender_bypass') ?? false
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// Cross-instance singletons. The `'use cache'` transform pulls this module (and use-cache.ts) into the
|
|
@@ -35,22 +35,22 @@ export function draftModeBypassActive() {
|
|
|
35
35
|
// module-level Map/counter/ALS - the producer scope a cached render enters would be invisible to the
|
|
36
36
|
// runtime fetch patch, and a revalidatePath() written by one copy's registry would never be seen by the
|
|
37
37
|
// other's staleness reader. Anchor all process-wide state on globalThis so both copies share it.
|
|
38
|
-
const REVALIDATE_GLOBALS = Symbol.for('pnext.compat.revalidateGlobals')
|
|
39
|
-
const USE_CACHE_ENTRIES = Symbol.for('pnext.compat.useCacheEntries')
|
|
38
|
+
const REVALIDATE_GLOBALS = Symbol.for('pnext.compat.revalidateGlobals')
|
|
39
|
+
const USE_CACHE_ENTRIES = Symbol.for('pnext.compat.useCacheEntries')
|
|
40
40
|
|
|
41
41
|
function revalidateGlobal<T>(name: string, create: () => T): T {
|
|
42
|
-
const root = globalThis as Record<PropertyKey, unknown
|
|
43
|
-
const container = (root[REVALIDATE_GLOBALS] ??= {}) as Record<string, unknown
|
|
44
|
-
if (!(name in container)) container[name] = create()
|
|
45
|
-
return container[name] as T
|
|
42
|
+
const root = globalThis as Record<PropertyKey, unknown>
|
|
43
|
+
const container = (root[REVALIDATE_GLOBALS] ??= {}) as Record<string, unknown>
|
|
44
|
+
if (!(name in container)) container[name] = create()
|
|
45
|
+
return container[name] as T
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
const revalidatedPaths = revalidateGlobal('revalidatedPaths', () => new Map<string, number>())
|
|
48
|
+
const revalidatedPaths = revalidateGlobal('revalidatedPaths', () => new Map<string, number>())
|
|
49
49
|
const revalidatedPathReasons = revalidateGlobal(
|
|
50
50
|
'revalidatedPathReasons',
|
|
51
51
|
() => new Map<string, 'stale' | 'on-demand'>(),
|
|
52
|
-
)
|
|
53
|
-
const revalidatedTags = revalidateGlobal('revalidatedTags', () => new Map<string, number>())
|
|
52
|
+
)
|
|
53
|
+
const revalidatedTags = revalidateGlobal('revalidatedTags', () => new Map<string, number>())
|
|
54
54
|
// Monotonic counters stamped/sampled across the module. Held on a shared object
|
|
55
55
|
// (not module `let`s) so both module copies read and bump the same values:
|
|
56
56
|
// - tagSeq: stamped on every hard tag revalidation. In-memory cache entries
|
|
@@ -64,40 +64,38 @@ const revalidatedTags = revalidateGlobal('revalidatedTags', () => new Map<string
|
|
|
64
64
|
// - events: monotonic count of revalidation events (path or tag). Server
|
|
65
65
|
// actions sample it before/after an action to decide whether the client's
|
|
66
66
|
// view needs a refresh (Next invalidates its client router cache).
|
|
67
|
-
const counters = revalidateGlobal('counters', () => ({ tagSeq: 0, lastPathAt: 0, events: 0 }))
|
|
68
|
-
const revalidatedTagSeq = revalidateGlobal('revalidatedTagSeq', () => new Map<string, number>())
|
|
67
|
+
const counters = revalidateGlobal('counters', () => ({ tagSeq: 0, lastPathAt: 0, events: 0 }))
|
|
68
|
+
const revalidatedTagSeq = revalidateGlobal('revalidatedTagSeq', () => new Map<string, number>())
|
|
69
69
|
const revalidatedTagReasons = revalidateGlobal(
|
|
70
70
|
'revalidatedTagReasons',
|
|
71
71
|
() => new Map<string, 'stale' | 'on-demand'>(),
|
|
72
|
-
)
|
|
73
|
-
const staleTags = revalidateGlobal('staleTags', () => new Map<string, number>())
|
|
74
|
-
const dataCacheInvalidators = revalidateGlobal('dataCacheInvalidators', () => new Set<() => void>())
|
|
72
|
+
)
|
|
73
|
+
const staleTags = revalidateGlobal('staleTags', () => new Map<string, number>())
|
|
74
|
+
const dataCacheInvalidators = revalidateGlobal('dataCacheInvalidators', () => new Set<() => void>())
|
|
75
75
|
export type RevalidationInvalidation =
|
|
76
|
-
|
|
77
|
-
| { kind: 'tag'; tag: string; stale: boolean };
|
|
76
|
+
{ kind: 'path'; path: string } | { kind: 'tag'; tag: string; stale: boolean }
|
|
78
77
|
|
|
79
78
|
const revalidationInvalidators = revalidateGlobal(
|
|
80
79
|
'revalidationInvalidators',
|
|
81
80
|
() => new Set<(invalidation: RevalidationInvalidation) => void>(),
|
|
82
|
-
)
|
|
81
|
+
)
|
|
83
82
|
|
|
84
83
|
interface RevalidatableUseCacheEntry {
|
|
85
|
-
tags: string[]
|
|
86
|
-
route?: string
|
|
87
|
-
storedAt: number
|
|
84
|
+
tags: string[]
|
|
85
|
+
route?: string
|
|
86
|
+
storedAt: number
|
|
88
87
|
}
|
|
89
88
|
|
|
90
89
|
function evictUseCacheEntries(invalidation: RevalidationInvalidation) {
|
|
91
90
|
const entries = (globalThis as Record<PropertyKey, unknown>)[USE_CACHE_ENTRIES] as
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
if (!entries || (invalidation.kind === 'tag' && invalidation.stale)) return;
|
|
91
|
+
Map<string, RevalidatableUseCacheEntry> | undefined
|
|
92
|
+
if (!entries || (invalidation.kind === 'tag' && invalidation.stale)) return
|
|
95
93
|
for (const [key, entry] of entries) {
|
|
96
94
|
const matches =
|
|
97
95
|
invalidation.kind === 'tag'
|
|
98
96
|
? entry.tags.includes(invalidation.tag)
|
|
99
|
-
: pathScopeRevalidated(entry.route, entry.storedAt)
|
|
100
|
-
if (matches) entries.delete(key)
|
|
97
|
+
: pathScopeRevalidated(entry.route, entry.storedAt)
|
|
98
|
+
if (matches) entries.delete(key)
|
|
101
99
|
}
|
|
102
100
|
}
|
|
103
101
|
// Pattern marks: revalidatePath('/x', 'layout') covers the whole subtree, and
|
|
@@ -105,11 +103,11 @@ function evictUseCacheEntries(invalidation: RevalidationInvalidation) {
|
|
|
105
103
|
const revalidatedPatterns = revalidateGlobal(
|
|
106
104
|
'revalidatedPatterns',
|
|
107
105
|
() => [] as { regex: RegExp; at: number; reason: 'stale' | 'on-demand' }[],
|
|
108
|
-
)
|
|
109
|
-
const revalidatedPatternsLimit = 256
|
|
106
|
+
)
|
|
107
|
+
const revalidatedPatternsLimit = 256
|
|
110
108
|
|
|
111
109
|
export function revalidationEventCount() {
|
|
112
|
-
return counters.events
|
|
110
|
+
return counters.events
|
|
113
111
|
}
|
|
114
112
|
|
|
115
113
|
/**
|
|
@@ -119,66 +117,69 @@ export function revalidationEventCount() {
|
|
|
119
117
|
* header, so bumping the counter is enough.
|
|
120
118
|
*/
|
|
121
119
|
export function bumpRevalidationEvent() {
|
|
122
|
-
counters.events += 1
|
|
120
|
+
counters.events += 1
|
|
123
121
|
}
|
|
124
122
|
|
|
125
123
|
export function normalizeRevalidatePath(path: string) {
|
|
126
|
-
let pathname = path.split('?')[0] ?? path
|
|
124
|
+
let pathname = path.split('?')[0] ?? path
|
|
127
125
|
try {
|
|
128
|
-
pathname = decodeURI(pathname)
|
|
126
|
+
pathname = decodeURI(pathname)
|
|
129
127
|
} catch {
|
|
130
128
|
// Keep malformed escape sequences unchanged.
|
|
131
129
|
}
|
|
132
|
-
const trimmed = pathname.replace(/\/+$/, '')
|
|
133
|
-
return trimmed === '' ? '/' : trimmed
|
|
130
|
+
const trimmed = pathname.replace(/\/+$/, '')
|
|
131
|
+
return trimmed === '' ? '/' : trimmed
|
|
134
132
|
}
|
|
135
133
|
|
|
136
134
|
export function markPathRevalidated(path: string, type?: 'page' | 'layout') {
|
|
137
|
-
counters.events += 1
|
|
135
|
+
counters.events += 1
|
|
138
136
|
// fetch/data cache entries carry the route they were produced under (Next's
|
|
139
137
|
// implicit `_N_T_/route` soft tag). Revalidating a path only invalidates the
|
|
140
138
|
// entries owned by matching routes (see pathScopeRevalidated); route-less
|
|
141
139
|
// entries (produced outside a render) fall back to this global timestamp.
|
|
142
|
-
counters.lastPathAt = Date.now()
|
|
143
|
-
const normalized = normalizeRevalidatePath(path)
|
|
144
|
-
void modernCacheUpdateTags([`_N_T_${normalized}`])
|
|
145
|
-
const reason = getWorkUnit()?.phase === 'action' ? 'stale' : 'on-demand'
|
|
140
|
+
counters.lastPathAt = Date.now()
|
|
141
|
+
const normalized = normalizeRevalidatePath(path)
|
|
142
|
+
void modernCacheUpdateTags([`_N_T_${normalized}`])
|
|
143
|
+
const reason = getWorkUnit()?.phase === 'action' ? 'stale' : 'on-demand'
|
|
146
144
|
if (normalized.includes('[') || type === 'layout') {
|
|
147
145
|
const source = normalized
|
|
148
146
|
.split('/')
|
|
149
147
|
.map(segment =>
|
|
150
|
-
/^\[?\[\.\.\./.test(segment)
|
|
148
|
+
/^\[?\[\.\.\./.test(segment)
|
|
149
|
+
? '.+'
|
|
150
|
+
: segment.startsWith('[')
|
|
151
|
+
? '[^/]+'
|
|
152
|
+
: escapeRegex(segment),
|
|
151
153
|
)
|
|
152
|
-
.join('/')
|
|
153
|
-
const base = normalized === '/' ? '' : source
|
|
154
|
-
const regex =
|
|
155
|
-
|
|
156
|
-
revalidatedPatterns.
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return;
|
|
154
|
+
.join('/')
|
|
155
|
+
const base = normalized === '/' ? '' : source
|
|
156
|
+
const regex = type === 'layout' ? new RegExp(`^${base}(?:/.*)?$`) : new RegExp(`^${source}$`)
|
|
157
|
+
revalidatedPatterns.push({ regex, at: Date.now(), reason })
|
|
158
|
+
if (revalidatedPatterns.length > revalidatedPatternsLimit) revalidatedPatterns.shift()
|
|
159
|
+
const invalidation = { kind: 'path', path: normalized } as const
|
|
160
|
+
evictUseCacheEntries(invalidation)
|
|
161
|
+
notifyRevalidationInvalidators(invalidation)
|
|
162
|
+
return
|
|
162
163
|
}
|
|
163
|
-
revalidatedPaths.set(normalized, Date.now())
|
|
164
|
-
revalidatedPathReasons.set(normalized, reason)
|
|
165
|
-
const invalidation = { kind: 'path', path: normalized } as const
|
|
166
|
-
evictUseCacheEntries(invalidation)
|
|
167
|
-
notifyRevalidationInvalidators(invalidation)
|
|
164
|
+
revalidatedPaths.set(normalized, Date.now())
|
|
165
|
+
revalidatedPathReasons.set(normalized, reason)
|
|
166
|
+
const invalidation = { kind: 'path', path: normalized } as const
|
|
167
|
+
evictUseCacheEntries(invalidation)
|
|
168
|
+
notifyRevalidationInvalidators(invalidation)
|
|
168
169
|
}
|
|
169
170
|
|
|
170
171
|
export function markTagRevalidated(tag: string) {
|
|
171
|
-
counters.events += 1
|
|
172
|
-
revalidatedTags.set(tag, Date.now())
|
|
173
|
-
revalidatedTagSeq.set(tag, ++counters.tagSeq)
|
|
174
|
-
revalidatedTagReasons.set(tag, getWorkUnit()?.phase === 'action' ? 'stale' : 'on-demand')
|
|
172
|
+
counters.events += 1
|
|
173
|
+
revalidatedTags.set(tag, Date.now())
|
|
174
|
+
revalidatedTagSeq.set(tag, ++counters.tagSeq)
|
|
175
|
+
revalidatedTagReasons.set(tag, getWorkUnit()?.phase === 'action' ? 'stale' : 'on-demand')
|
|
175
176
|
// Forward to a configured cache handler so a persistent backend drops the
|
|
176
177
|
// entry too (best-effort; the in-memory marks are authoritative).
|
|
177
|
-
void cacheHandlerRevalidateTag(tag)
|
|
178
|
-
void modernCacheUpdateTags([tag])
|
|
179
|
-
const invalidation = { kind: 'tag', tag, stale: false } as const
|
|
180
|
-
evictUseCacheEntries(invalidation)
|
|
181
|
-
notifyRevalidationInvalidators(invalidation)
|
|
178
|
+
void cacheHandlerRevalidateTag(tag)
|
|
179
|
+
void modernCacheUpdateTags([tag])
|
|
180
|
+
const invalidation = { kind: 'tag', tag, stale: false } as const
|
|
181
|
+
evictUseCacheEntries(invalidation)
|
|
182
|
+
notifyRevalidationInvalidators(invalidation)
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
export function markTagStale(tag: string) {
|
|
@@ -186,38 +187,38 @@ export function markTagStale(tag: string) {
|
|
|
186
187
|
// stale-while-revalidate - the client keeps showing its current (stale) view and must NOT be told to
|
|
187
188
|
// refresh after the action. Fresh data appears only on the next navigation/refresh, which serves stale
|
|
188
189
|
// and regenerates in the background.
|
|
189
|
-
staleTags.set(tag, Date.now())
|
|
190
|
-
void cacheHandlerRevalidateTag(tag)
|
|
191
|
-
void modernCacheUpdateTags([tag])
|
|
192
|
-
notifyRevalidationInvalidators({ kind: 'tag', tag, stale: true })
|
|
190
|
+
staleTags.set(tag, Date.now())
|
|
191
|
+
void cacheHandlerRevalidateTag(tag)
|
|
192
|
+
void modernCacheUpdateTags([tag])
|
|
193
|
+
notifyRevalidationInvalidators({ kind: 'tag', tag, stale: true })
|
|
193
194
|
}
|
|
194
195
|
|
|
195
196
|
// Marks are integer Date.now() while file mtimes carry fractional
|
|
196
197
|
// milliseconds; truncate so a mark landing in the same millisecond as the
|
|
197
198
|
// write still counts as newer (worst case: one redundant regeneration).
|
|
198
199
|
function markedAfter(at: number | undefined, time: number) {
|
|
199
|
-
return at !== undefined && at >= Math.trunc(time) && at > time - 1
|
|
200
|
+
return at !== undefined && at >= Math.trunc(time) && at > time - 1
|
|
200
201
|
}
|
|
201
202
|
|
|
202
203
|
export function pathRevalidatedSince(path: string, time: number) {
|
|
203
|
-
const normalized = normalizeRevalidatePath(path)
|
|
204
|
-
if (markedAfter(revalidatedPaths.get(normalized), time)) return true
|
|
204
|
+
const normalized = normalizeRevalidatePath(path)
|
|
205
|
+
if (markedAfter(revalidatedPaths.get(normalized), time)) return true
|
|
205
206
|
return revalidatedPatterns.some(
|
|
206
207
|
pattern => markedAfter(pattern.at, time) && pattern.regex.test(normalized),
|
|
207
|
-
)
|
|
208
|
+
)
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
export function pathRevalidationReasonSince(
|
|
211
212
|
path: string,
|
|
212
213
|
time: number,
|
|
213
214
|
): 'stale' | 'on-demand' | undefined {
|
|
214
|
-
const normalized = normalizeRevalidatePath(path)
|
|
215
|
+
const normalized = normalizeRevalidatePath(path)
|
|
215
216
|
if (markedAfter(revalidatedPaths.get(normalized), time)) {
|
|
216
|
-
return revalidatedPathReasons.get(normalized) ?? 'on-demand'
|
|
217
|
+
return revalidatedPathReasons.get(normalized) ?? 'on-demand'
|
|
217
218
|
}
|
|
218
219
|
return revalidatedPatterns.find(
|
|
219
220
|
pattern => markedAfter(pattern.at, time) && pattern.regex.test(normalized),
|
|
220
|
-
)?.reason
|
|
221
|
+
)?.reason
|
|
221
222
|
}
|
|
222
223
|
|
|
223
224
|
/**
|
|
@@ -228,17 +229,17 @@ export function pathRevalidationReasonSince(
|
|
|
228
229
|
* entries are invalidated by any path revalidation.
|
|
229
230
|
*/
|
|
230
231
|
export function pathScopeRevalidated(route: string | undefined, time: number): boolean {
|
|
231
|
-
if (route === undefined) return markedAfter(counters.lastPathAt || undefined, time)
|
|
232
|
-
return pathRevalidatedSince(route, time)
|
|
232
|
+
if (route === undefined) return markedAfter(counters.lastPathAt || undefined, time)
|
|
233
|
+
return pathRevalidatedSince(route, time)
|
|
233
234
|
}
|
|
234
235
|
|
|
235
236
|
export function tagsRevalidatedSince(tags: readonly string[], time: number) {
|
|
236
|
-
return tags.some(tag => markedAfter(revalidatedTags.get(tag), time))
|
|
237
|
+
return tags.some(tag => markedAfter(revalidatedTags.get(tag), time))
|
|
237
238
|
}
|
|
238
239
|
|
|
239
240
|
/** Current hard-tag-revalidation sequence, stamped on an entry at production. */
|
|
240
241
|
export function currentTagRevalidationSeq() {
|
|
241
|
-
return counters.tagSeq
|
|
242
|
+
return counters.tagSeq
|
|
242
243
|
}
|
|
243
244
|
|
|
244
245
|
/**
|
|
@@ -250,7 +251,7 @@ export function rdcProcessId(): string {
|
|
|
250
251
|
return revalidateGlobal(
|
|
251
252
|
'rdcProcessId',
|
|
252
253
|
() => `${process.pid}:${Date.now()}:${Math.random().toString(36).slice(2)}`,
|
|
253
|
-
)
|
|
254
|
+
)
|
|
254
255
|
}
|
|
255
256
|
|
|
256
257
|
/**
|
|
@@ -267,8 +268,8 @@ export function rdcProcessId(): string {
|
|
|
267
268
|
* reset), so a shell regenerated right after a revalidation is not immediately re-invalidated by it.
|
|
268
269
|
*/
|
|
269
270
|
export function rebaseRdcTagSeq(record: { tagSeq: number; pid?: string }): number {
|
|
270
|
-
if (record.pid !== rdcProcessId()) return 0
|
|
271
|
-
return Math.min(record.tagSeq, counters.tagSeq)
|
|
271
|
+
if (record.pid !== rdcProcessId()) return 0
|
|
272
|
+
return Math.min(record.tagSeq, counters.tagSeq)
|
|
272
273
|
}
|
|
273
274
|
|
|
274
275
|
/**
|
|
@@ -279,7 +280,7 @@ export function rebaseRdcTagSeq(record: { tagSeq: number; pid?: string }): numbe
|
|
|
279
280
|
* request reliably see the invalidation exactly once.
|
|
280
281
|
*/
|
|
281
282
|
export function tagsRevalidatedAfterSeq(tags: readonly string[], seq: number) {
|
|
282
|
-
return tags.some(tag => (revalidatedTagSeq.get(tag) ?? 0) > seq)
|
|
283
|
+
return tags.some(tag => (revalidatedTagSeq.get(tag) ?? 0) > seq)
|
|
283
284
|
}
|
|
284
285
|
|
|
285
286
|
export function tagsRevalidationReasonSince(
|
|
@@ -288,46 +289,46 @@ export function tagsRevalidationReasonSince(
|
|
|
288
289
|
): 'stale' | 'on-demand' | undefined {
|
|
289
290
|
for (const tag of tags) {
|
|
290
291
|
if (markedAfter(revalidatedTags.get(tag), time)) {
|
|
291
|
-
return revalidatedTagReasons.get(tag) ?? 'on-demand'
|
|
292
|
+
return revalidatedTagReasons.get(tag) ?? 'on-demand'
|
|
292
293
|
}
|
|
293
294
|
}
|
|
294
|
-
return undefined
|
|
295
|
+
return undefined
|
|
295
296
|
}
|
|
296
297
|
|
|
297
298
|
export function tagsStaleSince(tags: readonly string[], time: number) {
|
|
298
|
-
return tags.some(tag => markedAfter(staleTags.get(tag), time))
|
|
299
|
+
return tags.some(tag => markedAfter(staleTags.get(tag), time))
|
|
299
300
|
}
|
|
300
301
|
|
|
301
302
|
interface DataCacheEntry {
|
|
302
|
-
value: Promise<unknown
|
|
303
|
-
storedAt: number
|
|
304
|
-
tags: readonly string[]
|
|
305
|
-
revalidateSeconds?: number
|
|
303
|
+
value: Promise<unknown>
|
|
304
|
+
storedAt: number
|
|
305
|
+
tags: readonly string[]
|
|
306
|
+
revalidateSeconds?: number
|
|
306
307
|
/** A background stale-while-revalidate refresh is already in flight. */
|
|
307
|
-
refreshing?: boolean
|
|
308
|
+
refreshing?: boolean
|
|
308
309
|
/** Pathname of the render that produced this entry (path-revalidation scope). */
|
|
309
|
-
route?: string
|
|
310
|
+
route?: string
|
|
310
311
|
/**
|
|
311
312
|
* The render cache-meta this entry was produced under: an on-demand
|
|
312
313
|
* regeneration (refreshFetches) re-produces each entry once per render, then
|
|
313
314
|
* repeated reads dedupe against it.
|
|
314
315
|
*/
|
|
315
|
-
refreshedIn?: object
|
|
316
|
+
refreshedIn?: object
|
|
316
317
|
}
|
|
317
318
|
|
|
318
|
-
const dataCache = revalidateGlobal('dataCache', () => new Map<string, DataCacheEntry>())
|
|
319
|
-
const dataCacheLimit = 1024
|
|
319
|
+
const dataCache = revalidateGlobal('dataCache', () => new Map<string, DataCacheEntry>())
|
|
320
|
+
const dataCacheLimit = 1024
|
|
320
321
|
|
|
321
322
|
function dataCacheEntryExpired(entry: DataCacheEntry) {
|
|
322
323
|
return (
|
|
323
324
|
entry.revalidateSeconds !== undefined &&
|
|
324
325
|
realNow() - entry.storedAt >= entry.revalidateSeconds * 1000
|
|
325
|
-
)
|
|
326
|
+
)
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
export interface DataCacheOptions {
|
|
329
|
-
tags?: string[]
|
|
330
|
-
revalidateSeconds?: number
|
|
330
|
+
tags?: string[]
|
|
331
|
+
revalidateSeconds?: number
|
|
331
332
|
}
|
|
332
333
|
|
|
333
334
|
/**
|
|
@@ -342,9 +343,9 @@ export function cachedData(
|
|
|
342
343
|
produce: () => Promise<unknown>,
|
|
343
344
|
options: DataCacheOptions = {},
|
|
344
345
|
): Promise<unknown> {
|
|
345
|
-
if (draftModeBypassActive()) return produce()
|
|
346
|
-
const entry = dataCache.get(key)
|
|
347
|
-
const meta = cacheMetaStorage.getStore()
|
|
346
|
+
if (draftModeBypassActive()) return produce()
|
|
347
|
+
const entry = dataCache.get(key)
|
|
348
|
+
const meta = cacheMetaStorage.getStore()
|
|
348
349
|
// On-demand revalidation re-produces each entry ONCE per render (Next skips the cache read entirely
|
|
349
350
|
// under isOnDemandRevalidate), then dedupes via refreshedIn - but only entries the revalidation
|
|
350
351
|
// actually reached. See the matching gate in use-cache.ts: a still-marked route re-renders many times
|
|
@@ -356,29 +357,29 @@ export function cachedData(
|
|
|
356
357
|
(tagsRevalidatedSince(entry.tags, entry.storedAt) ||
|
|
357
358
|
pathScopeRevalidated(entry.route, entry.storedAt) ||
|
|
358
359
|
tagsStaleSince(entry.tags, entry.storedAt) ||
|
|
359
|
-
dataCacheEntryExpired(entry))
|
|
360
|
+
dataCacheEntryExpired(entry))
|
|
360
361
|
if (
|
|
361
362
|
entry &&
|
|
362
363
|
!refresh &&
|
|
363
364
|
!tagsRevalidatedSince(entry.tags, entry.storedAt) &&
|
|
364
365
|
!pathScopeRevalidated(entry.route, entry.storedAt)
|
|
365
366
|
) {
|
|
366
|
-
recordCacheTags(entry.tags)
|
|
367
|
+
recordCacheTags(entry.tags)
|
|
367
368
|
if (entry.revalidateSeconds !== undefined) {
|
|
368
|
-
recordCacheRevalidate(entry.revalidateSeconds)
|
|
369
|
+
recordCacheRevalidate(entry.revalidateSeconds)
|
|
369
370
|
}
|
|
370
|
-
const tagStale = tagsStaleSince(entry.tags, entry.storedAt)
|
|
371
|
-
if (!tagStale && !dataCacheEntryExpired(entry)) return entry.value
|
|
371
|
+
const tagStale = tagsStaleSince(entry.tags, entry.storedAt)
|
|
372
|
+
if (!tagStale && !dataCacheEntryExpired(entry)) return entry.value
|
|
372
373
|
// ISR regeneration renders refetch expired entries inline.
|
|
373
374
|
if (cacheMetaStorage.getStore()?.blockingStaleFetches !== true) {
|
|
374
375
|
if (!entry.refreshing) {
|
|
375
|
-
entry.refreshing = true
|
|
376
|
-
void storeDataCacheEntry(key, produce, options, entry)
|
|
376
|
+
entry.refreshing = true
|
|
377
|
+
void storeDataCacheEntry(key, produce, options, entry)
|
|
377
378
|
}
|
|
378
|
-
return entry.value
|
|
379
|
+
return entry.value
|
|
379
380
|
}
|
|
380
381
|
}
|
|
381
|
-
return storeDataCacheEntry(key, produce, options)
|
|
382
|
+
return storeDataCacheEntry(key, produce, options)
|
|
382
383
|
}
|
|
383
384
|
|
|
384
385
|
function storeDataCacheEntry(
|
|
@@ -390,16 +391,14 @@ function storeDataCacheEntry(
|
|
|
390
391
|
// Collect the tags of fetches/nested caches produced inside this entry so it
|
|
391
392
|
// inherits them (revalidateTag can then invalidate it), and propagate the
|
|
392
393
|
// aggregate up to an enclosing producer once settled.
|
|
393
|
-
const parentProducerTags = producerTagsStorage.getStore()
|
|
394
|
-
const producerTags = new Set<string>(options.tags ?? [])
|
|
395
|
-
const value = producerTagsStorage.run(producerTags, () =>
|
|
396
|
-
runInsideUnstableCacheProducer(produce),
|
|
397
|
-
);
|
|
394
|
+
const parentProducerTags = producerTagsStorage.getStore()
|
|
395
|
+
const producerTags = new Set<string>(options.tags ?? [])
|
|
396
|
+
const value = producerTagsStorage.run(producerTags, () => runInsideUnstableCacheProducer(produce))
|
|
398
397
|
// Same contract as the 'use cache' fill: a build prerender's task boundary
|
|
399
398
|
// waits for an in-flight data-cache fill rather than cutting it short, so
|
|
400
399
|
// cached IO still lands in the static shell (core ppr).
|
|
401
|
-
void trackPrerenderCacheFill(value)
|
|
402
|
-
const producingMeta = cacheMetaStorage.getStore()
|
|
400
|
+
void trackPrerenderCacheFill(value)
|
|
401
|
+
const producingMeta = cacheMetaStorage.getStore()
|
|
403
402
|
const stored: DataCacheEntry = {
|
|
404
403
|
value,
|
|
405
404
|
storedAt: realNow(),
|
|
@@ -411,68 +410,68 @@ function storeDataCacheEntry(
|
|
|
411
410
|
: producingMeta?.route !== undefined
|
|
412
411
|
? { route: producingMeta.route }
|
|
413
412
|
: {}),
|
|
414
|
-
}
|
|
413
|
+
}
|
|
415
414
|
const applyInheritedTags = () => {
|
|
416
|
-
stored.tags = [...producerTags]
|
|
417
|
-
if (parentProducerTags) for (const tag of producerTags) parentProducerTags.add(tag)
|
|
418
|
-
}
|
|
415
|
+
stored.tags = [...producerTags]
|
|
416
|
+
if (parentProducerTags) for (const tag of producerTags) parentProducerTags.add(tag)
|
|
417
|
+
}
|
|
419
418
|
if (serveStale) {
|
|
420
419
|
// Background refresh: only replace the stale entry once the new value
|
|
421
420
|
// settles, so concurrent readers keep getting the stale value instantly.
|
|
422
421
|
value.then(
|
|
423
422
|
() => {
|
|
424
|
-
applyInheritedTags()
|
|
425
|
-
dataCache.set(key, stored)
|
|
423
|
+
applyInheritedTags()
|
|
424
|
+
dataCache.set(key, stored)
|
|
426
425
|
},
|
|
427
426
|
() => {
|
|
428
|
-
serveStale.refreshing = false
|
|
427
|
+
serveStale.refreshing = false
|
|
429
428
|
},
|
|
430
|
-
)
|
|
431
|
-
return value
|
|
429
|
+
)
|
|
430
|
+
return value
|
|
432
431
|
}
|
|
433
432
|
if (dataCache.size >= dataCacheLimit) {
|
|
434
|
-
const oldest = dataCache.keys().next().value
|
|
435
|
-
if (oldest !== undefined) dataCache.delete(oldest)
|
|
433
|
+
const oldest = dataCache.keys().next().value
|
|
434
|
+
if (oldest !== undefined) dataCache.delete(oldest)
|
|
436
435
|
}
|
|
437
|
-
dataCache.set(key, stored)
|
|
436
|
+
dataCache.set(key, stored)
|
|
438
437
|
value.then(applyInheritedTags, () => {
|
|
439
|
-
if (dataCache.get(key)?.value === value) dataCache.delete(key)
|
|
440
|
-
})
|
|
441
|
-
return value
|
|
438
|
+
if (dataCache.get(key)?.value === value) dataCache.delete(key)
|
|
439
|
+
})
|
|
440
|
+
return value
|
|
442
441
|
}
|
|
443
442
|
|
|
444
443
|
export function clearRevalidationState() {
|
|
445
|
-
revalidatedPaths.clear()
|
|
446
|
-
revalidatedPathReasons.clear()
|
|
447
|
-
revalidatedTags.clear()
|
|
448
|
-
revalidatedTagSeq.clear()
|
|
449
|
-
counters.tagSeq = 0
|
|
450
|
-
revalidatedTagReasons.clear()
|
|
451
|
-
staleTags.clear()
|
|
452
|
-
revalidatedPatterns.length = 0
|
|
453
|
-
counters.lastPathAt = 0
|
|
454
|
-
dataCache.clear()
|
|
455
|
-
for (const invalidate of dataCacheInvalidators) invalidate()
|
|
444
|
+
revalidatedPaths.clear()
|
|
445
|
+
revalidatedPathReasons.clear()
|
|
446
|
+
revalidatedTags.clear()
|
|
447
|
+
revalidatedTagSeq.clear()
|
|
448
|
+
counters.tagSeq = 0
|
|
449
|
+
revalidatedTagReasons.clear()
|
|
450
|
+
staleTags.clear()
|
|
451
|
+
revalidatedPatterns.length = 0
|
|
452
|
+
counters.lastPathAt = 0
|
|
453
|
+
dataCache.clear()
|
|
454
|
+
for (const invalidate of dataCacheInvalidators) invalidate()
|
|
456
455
|
}
|
|
457
456
|
|
|
458
457
|
export function registerDataCacheInvalidator(invalidate: () => void): () => void {
|
|
459
|
-
dataCacheInvalidators.add(invalidate)
|
|
458
|
+
dataCacheInvalidators.add(invalidate)
|
|
460
459
|
return () => {
|
|
461
|
-
dataCacheInvalidators.delete(invalidate)
|
|
462
|
-
}
|
|
460
|
+
dataCacheInvalidators.delete(invalidate)
|
|
461
|
+
}
|
|
463
462
|
}
|
|
464
463
|
|
|
465
464
|
export function registerRevalidationInvalidator(
|
|
466
465
|
invalidate: (invalidation: RevalidationInvalidation) => void,
|
|
467
466
|
): () => void {
|
|
468
|
-
revalidationInvalidators.add(invalidate)
|
|
467
|
+
revalidationInvalidators.add(invalidate)
|
|
469
468
|
return () => {
|
|
470
|
-
revalidationInvalidators.delete(invalidate)
|
|
471
|
-
}
|
|
469
|
+
revalidationInvalidators.delete(invalidate)
|
|
470
|
+
}
|
|
472
471
|
}
|
|
473
472
|
|
|
474
473
|
function notifyRevalidationInvalidators(invalidation: RevalidationInvalidation) {
|
|
475
|
-
for (const invalidate of revalidationInvalidators) invalidate(invalidation)
|
|
474
|
+
for (const invalidate of revalidationInvalidators) invalidate(invalidation)
|
|
476
475
|
}
|
|
477
476
|
|
|
478
477
|
/**
|
|
@@ -482,8 +481,8 @@ function notifyRevalidationInvalidators(invalidation: RevalidationInvalidation)
|
|
|
482
481
|
* the route's `fetchCache` segment config for cache-mode defaults.
|
|
483
482
|
*/
|
|
484
483
|
export interface RenderCacheMeta {
|
|
485
|
-
tags: Set<string
|
|
486
|
-
revalidateSeconds?: number
|
|
484
|
+
tags: Set<string>
|
|
485
|
+
revalidateSeconds?: number
|
|
487
486
|
/**
|
|
488
487
|
* Effective `use cache` cacheLife expire/stale windows aggregated across the
|
|
489
488
|
* render's cache scopes (min of each). Recorded alongside revalidateSeconds so
|
|
@@ -491,56 +490,56 @@ export interface RenderCacheMeta {
|
|
|
491
490
|
* x-nextjs-stale-time even when the work-unit stash (used by the live-render
|
|
492
491
|
* response finalizer) is not in scope during the async cache propagation.
|
|
493
492
|
*/
|
|
494
|
-
expireSeconds?: number
|
|
495
|
-
staleSeconds?: number
|
|
496
|
-
fetchCache?: string
|
|
493
|
+
expireSeconds?: number
|
|
494
|
+
staleSeconds?: number
|
|
495
|
+
fetchCache?: string
|
|
497
496
|
/** Route path label for error messages (e.g. invalid fetch revalidate). */
|
|
498
|
-
route?: string
|
|
497
|
+
route?: string
|
|
499
498
|
/** On-demand revalidation render: data caches must refetch and overwrite. */
|
|
500
|
-
refreshFetches?: boolean
|
|
499
|
+
refreshFetches?: boolean
|
|
501
500
|
/**
|
|
502
501
|
* ISR regeneration render: TTL-expired data-cache entries refetch inline
|
|
503
502
|
* (blocking) instead of serving stale, so the regenerated page carries
|
|
504
503
|
* fresh data instead of lagging one generation behind.
|
|
505
504
|
*/
|
|
506
|
-
blockingStaleFetches?: boolean
|
|
505
|
+
blockingStaleFetches?: boolean
|
|
507
506
|
/**
|
|
508
507
|
* The render used an explicit no-store signal (fetch cache:'no-store'/
|
|
509
508
|
* 'no-cache', next.revalidate 0, or unstable_noStore()): the route must not
|
|
510
509
|
* be served from prebuilt output.
|
|
511
510
|
*/
|
|
512
|
-
noStore?: boolean
|
|
511
|
+
noStore?: boolean
|
|
513
512
|
/**
|
|
514
513
|
* Static-generation render (build prerender or ISR regeneration): a plain
|
|
515
514
|
* fetch with no explicit cache option defaults to caching (Next's
|
|
516
515
|
* force-cache-during-static-generation semantics) instead of per-request.
|
|
517
516
|
*/
|
|
518
|
-
prerender?: boolean
|
|
517
|
+
prerender?: boolean
|
|
519
518
|
/**
|
|
520
519
|
* True when the surrounding render is a route handler. Route handlers are
|
|
521
520
|
* dynamic by default (Next): an explicitly-uncached fetch (cache:'default')
|
|
522
521
|
* opts the handler out of prebuilt static output, whereas a page with the
|
|
523
522
|
* same fetch simply freezes at prerender time.
|
|
524
523
|
*/
|
|
525
|
-
handler?: boolean
|
|
524
|
+
handler?: boolean
|
|
526
525
|
/** True when `dynamic = 'error'` must reject request API access. */
|
|
527
|
-
dynamicError?: boolean
|
|
526
|
+
dynamicError?: boolean
|
|
528
527
|
/**
|
|
529
528
|
* after() work queued during a static-generation render. There is no response close to flush against,
|
|
530
529
|
* so the render itself drains the queue once `produce` settles - Next's semantics: a build prerender
|
|
531
530
|
* waits for after() callbacks, and a rejection fails that page's prerender. Compat's after() enqueues;
|
|
532
531
|
* nothing in the cache layer knows what the tasks are.
|
|
533
532
|
*/
|
|
534
|
-
afterTasks?: (() => Promise<void>)[]
|
|
533
|
+
afterTasks?: (() => Promise<void>)[]
|
|
535
534
|
}
|
|
536
535
|
|
|
537
536
|
const cacheMetaStorage = revalidateGlobal(
|
|
538
537
|
'cacheMetaStorage',
|
|
539
538
|
() => new AsyncLocalStorage<RenderCacheMeta>(),
|
|
540
|
-
)
|
|
539
|
+
)
|
|
541
540
|
|
|
542
541
|
export function currentRenderCacheMeta() {
|
|
543
|
-
return cacheMetaStorage.getStore()
|
|
542
|
+
return cacheMetaStorage.getStore()
|
|
544
543
|
}
|
|
545
544
|
|
|
546
545
|
/**
|
|
@@ -549,19 +548,19 @@ export function currentRenderCacheMeta() {
|
|
|
549
548
|
* static-generation force-cache default.
|
|
550
549
|
*/
|
|
551
550
|
export function currentRenderIsStaticGeneration(): boolean {
|
|
552
|
-
const meta = cacheMetaStorage.getStore()
|
|
553
|
-
return meta?.prerender === true || meta?.blockingStaleFetches === true
|
|
551
|
+
const meta = cacheMetaStorage.getStore()
|
|
552
|
+
return meta?.prerender === true || meta?.blockingStaleFetches === true
|
|
554
553
|
}
|
|
555
554
|
|
|
556
555
|
export function recordCacheTags(tags: readonly string[]) {
|
|
557
556
|
// Inside an unstable_cache producer, inner fetch/cache tags are inherited by
|
|
558
557
|
// the producing entry (Next semantics: an unstable_cache boundary collects the
|
|
559
558
|
// tags of every fetch made inside it, so revalidateTag invalidates the entry).
|
|
560
|
-
const producerTags = producerTagsStorage.getStore()
|
|
561
|
-
if (producerTags) for (const tag of tags) producerTags.add(tag)
|
|
562
|
-
const meta = cacheMetaStorage.getStore()
|
|
563
|
-
if (!meta) return
|
|
564
|
-
for (const tag of tags) meta.tags.add(tag)
|
|
559
|
+
const producerTags = producerTagsStorage.getStore()
|
|
560
|
+
if (producerTags) for (const tag of tags) producerTags.add(tag)
|
|
561
|
+
const meta = cacheMetaStorage.getStore()
|
|
562
|
+
if (!meta) return
|
|
563
|
+
for (const tag of tags) meta.tags.add(tag)
|
|
565
564
|
}
|
|
566
565
|
|
|
567
566
|
// Hook into the active `use cache` producer scope (registered by use-cache.ts;
|
|
@@ -572,58 +571,58 @@ export function recordCacheTags(tags: readonly string[]) {
|
|
|
572
571
|
// just the surrounding route.
|
|
573
572
|
const useCacheRevalidateSink = revalidateGlobal('useCacheRevalidateSink', () => ({
|
|
574
573
|
current: undefined as ((seconds: number) => void) | undefined,
|
|
575
|
-
}))
|
|
574
|
+
}))
|
|
576
575
|
|
|
577
576
|
export function setUseCacheRevalidateSink(sink: (seconds: number) => void) {
|
|
578
|
-
useCacheRevalidateSink.current = sink
|
|
577
|
+
useCacheRevalidateSink.current = sink
|
|
579
578
|
}
|
|
580
579
|
|
|
581
580
|
export function recordCacheRevalidate(seconds: number) {
|
|
582
|
-
useCacheRevalidateSink.current?.(seconds)
|
|
583
|
-
const meta = cacheMetaStorage.getStore()
|
|
584
|
-
if (!meta) return
|
|
581
|
+
useCacheRevalidateSink.current?.(seconds)
|
|
582
|
+
const meta = cacheMetaStorage.getStore()
|
|
583
|
+
if (!meta) return
|
|
585
584
|
meta.revalidateSeconds =
|
|
586
|
-
meta.revalidateSeconds === undefined ? seconds : Math.min(meta.revalidateSeconds, seconds)
|
|
585
|
+
meta.revalidateSeconds === undefined ? seconds : Math.min(meta.revalidateSeconds, seconds)
|
|
587
586
|
}
|
|
588
587
|
|
|
589
588
|
/** Record a `use cache` entry's expire window on the render meta (min-combined). */
|
|
590
589
|
export function recordCacheExpire(seconds: number) {
|
|
591
|
-
const meta = cacheMetaStorage.getStore()
|
|
592
|
-
if (!meta) return
|
|
590
|
+
const meta = cacheMetaStorage.getStore()
|
|
591
|
+
if (!meta) return
|
|
593
592
|
meta.expireSeconds =
|
|
594
|
-
meta.expireSeconds === undefined ? seconds : Math.min(meta.expireSeconds, seconds)
|
|
593
|
+
meta.expireSeconds === undefined ? seconds : Math.min(meta.expireSeconds, seconds)
|
|
595
594
|
}
|
|
596
595
|
|
|
597
596
|
/** Record a `use cache` entry's stale window on the render meta (min-combined). */
|
|
598
597
|
export function recordCacheStale(seconds: number) {
|
|
599
|
-
const meta = cacheMetaStorage.getStore()
|
|
600
|
-
if (!meta) return
|
|
598
|
+
const meta = cacheMetaStorage.getStore()
|
|
599
|
+
if (!meta) return
|
|
601
600
|
meta.staleSeconds =
|
|
602
|
-
meta.staleSeconds === undefined ? seconds : Math.min(meta.staleSeconds, seconds)
|
|
601
|
+
meta.staleSeconds === undefined ? seconds : Math.min(meta.staleSeconds, seconds)
|
|
603
602
|
}
|
|
604
603
|
|
|
605
604
|
export function recordCacheNoStore() {
|
|
606
605
|
// Inside a data-cache producer (unstable_cache / 'use cache') the cache
|
|
607
606
|
// boundary wins: no-store signals do not leak out to the route.
|
|
608
|
-
if (insideProducerStorage.getStore()) return
|
|
609
|
-
const meta = cacheMetaStorage.getStore()
|
|
610
|
-
if (meta) meta.noStore = true
|
|
607
|
+
if (insideProducerStorage.getStore()) return
|
|
608
|
+
const meta = cacheMetaStorage.getStore()
|
|
609
|
+
if (meta) meta.noStore = true
|
|
611
610
|
}
|
|
612
611
|
|
|
613
612
|
const insideProducerStorage = revalidateGlobal(
|
|
614
613
|
'insideProducerStorage',
|
|
615
614
|
() => new AsyncLocalStorage<boolean>(),
|
|
616
|
-
)
|
|
615
|
+
)
|
|
617
616
|
const producerKindStorage = revalidateGlobal(
|
|
618
617
|
'producerKindStorage',
|
|
619
618
|
() => new AsyncLocalStorage<'use-cache' | 'unstable-cache'>(),
|
|
620
|
-
)
|
|
619
|
+
)
|
|
621
620
|
// Tags accumulated by fetches/nested caches inside the currently-producing
|
|
622
621
|
// unstable_cache entry (see recordCacheTags / storeDataCacheEntry).
|
|
623
622
|
const producerTagsStorage = revalidateGlobal(
|
|
624
623
|
'producerTagsStorage',
|
|
625
624
|
() => new AsyncLocalStorage<Set<string>>(),
|
|
626
|
-
)
|
|
625
|
+
)
|
|
627
626
|
// A dedicated marker for `unstable_cache` specifically (a subset of the general
|
|
628
627
|
// data-cache-producer scope, which `use cache` also enters). Root params read
|
|
629
628
|
// inside a `use cache` NESTED within an `unstable_cache` are E1140, which needs
|
|
@@ -631,40 +630,42 @@ const producerTagsStorage = revalidateGlobal(
|
|
|
631
630
|
const insideUnstableCacheStorage = revalidateGlobal(
|
|
632
631
|
'insideUnstableCacheStorage',
|
|
633
632
|
() => new AsyncLocalStorage<boolean>(),
|
|
634
|
-
)
|
|
633
|
+
)
|
|
635
634
|
|
|
636
635
|
/** Mark fn as running inside a data-cache producer (see recordCacheNoStore). */
|
|
637
636
|
export function runInsideDataCacheProducer<T>(
|
|
638
637
|
fn: () => T,
|
|
639
638
|
kind: 'use-cache' | 'unstable-cache' = 'use-cache',
|
|
640
639
|
): T {
|
|
641
|
-
return producerKindStorage.run(kind, () => insideProducerStorage.run(true, fn))
|
|
640
|
+
return producerKindStorage.run(kind, () => insideProducerStorage.run(true, fn))
|
|
642
641
|
}
|
|
643
642
|
|
|
644
643
|
/** Mark fn as running specifically inside an `unstable_cache` producer. */
|
|
645
644
|
export function runInsideUnstableCacheProducer<T>(fn: () => T): T {
|
|
646
|
-
return insideUnstableCacheStorage.run(true, () =>
|
|
645
|
+
return insideUnstableCacheStorage.run(true, () =>
|
|
646
|
+
runInsideDataCacheProducer(fn, 'unstable-cache'),
|
|
647
|
+
)
|
|
647
648
|
}
|
|
648
649
|
|
|
649
650
|
/** True while executing inside an unstable_cache / 'use cache' producer. */
|
|
650
651
|
export function insideDataCacheProducer(): boolean {
|
|
651
|
-
return insideProducerStorage.getStore() === true
|
|
652
|
+
return insideProducerStorage.getStore() === true
|
|
652
653
|
}
|
|
653
654
|
|
|
654
655
|
/** True while executing specifically inside an `unstable_cache` producer. */
|
|
655
656
|
export function insideUnstableCacheProducer(): boolean {
|
|
656
|
-
return insideUnstableCacheStorage.getStore() === true
|
|
657
|
+
return insideUnstableCacheStorage.getStore() === true
|
|
657
658
|
}
|
|
658
659
|
|
|
659
660
|
export function insidePublicUseCacheProducer(): boolean {
|
|
660
|
-
return producerKindStorage.getStore() === 'use-cache'
|
|
661
|
+
return producerKindStorage.getStore() === 'use-cache'
|
|
661
662
|
}
|
|
662
663
|
|
|
663
664
|
/**
|
|
664
665
|
* Fail a build prerender when a dynamic request API (`cookies()`/`headers()`/
|
|
665
666
|
* `connection()`) is invoked inside a function cached with `unstable_cache()`.
|
|
666
667
|
* Called from the compat request-API seams (next/headers, next/server). Records
|
|
667
|
-
* Next's exact E838 error so the build aborts (register-
|
|
668
|
+
* Next's exact E838 error so the build aborts (register/use-cache) and throws so
|
|
668
669
|
* the offending fill unwinds. A no-op outside an armed build prerender and
|
|
669
670
|
* outside an unstable_cache producer, so serving-runtime/dev calls are untouched
|
|
670
671
|
* (there, the same APIs simply read live request data).
|
|
@@ -672,12 +673,12 @@ export function insidePublicUseCacheProducer(): boolean {
|
|
|
672
673
|
export function assertNoDynamicApiInsideCache(
|
|
673
674
|
api: 'cookies()' | 'headers()' | 'connection()',
|
|
674
675
|
): void {
|
|
675
|
-
if (!insideDataCacheProducer()) return
|
|
676
|
-
const route = cacheMetaStorage.getStore()?.route ?? ''
|
|
677
|
-
const unstable = insideUnstableCacheProducer()
|
|
676
|
+
if (!insideDataCacheProducer()) return
|
|
677
|
+
const route = cacheMetaStorage.getStore()?.route ?? ''
|
|
678
|
+
const unstable = insideUnstableCacheProducer()
|
|
678
679
|
const message = unstable
|
|
679
680
|
? unstableCacheDynamicApiMessage(route, api)
|
|
680
|
-
: useCacheDynamicApiMessage(route, api)
|
|
681
|
+
: useCacheDynamicApiMessage(route, api)
|
|
681
682
|
// Build-time prerenders record the error for the build log; the throw itself
|
|
682
683
|
// is unconditional — Next rejects dynamic data inside a cache scope at
|
|
683
684
|
// request time too (500 / generic RSC error in prod).
|
|
@@ -686,29 +687,29 @@ export function assertNoDynamicApiInsideCache(
|
|
|
686
687
|
kind: unstable ? 'unstable-cache-dynamic' : 'use-cache-dynamic',
|
|
687
688
|
route,
|
|
688
689
|
consoleBlock: `Error: ${message}`,
|
|
689
|
-
})
|
|
690
|
+
})
|
|
690
691
|
}
|
|
691
|
-
throw new Error(message)
|
|
692
|
+
throw new Error(message)
|
|
692
693
|
}
|
|
693
694
|
|
|
694
695
|
export async function collectRenderCacheMeta<T>(
|
|
695
696
|
produce: () => Promise<T>,
|
|
696
697
|
options: {
|
|
697
|
-
fetchCache?: string
|
|
698
|
-
refreshFetches?: boolean
|
|
699
|
-
blockingStaleFetches?: boolean
|
|
700
|
-
route?: string
|
|
701
|
-
prerender?: boolean
|
|
702
|
-
handler?: boolean
|
|
703
|
-
dynamicError?: boolean
|
|
698
|
+
fetchCache?: string
|
|
699
|
+
refreshFetches?: boolean
|
|
700
|
+
blockingStaleFetches?: boolean
|
|
701
|
+
route?: string
|
|
702
|
+
prerender?: boolean
|
|
703
|
+
handler?: boolean
|
|
704
|
+
dynamicError?: boolean
|
|
704
705
|
} = {},
|
|
705
706
|
): Promise<{
|
|
706
|
-
value: T
|
|
707
|
-
tags: string[]
|
|
708
|
-
revalidateSeconds?: number
|
|
709
|
-
expireSeconds?: number
|
|
710
|
-
staleSeconds?: number
|
|
711
|
-
noStore?: boolean
|
|
707
|
+
value: T
|
|
708
|
+
tags: string[]
|
|
709
|
+
revalidateSeconds?: number
|
|
710
|
+
expireSeconds?: number
|
|
711
|
+
staleSeconds?: number
|
|
712
|
+
noStore?: boolean
|
|
712
713
|
}> {
|
|
713
714
|
const meta: RenderCacheMeta = {
|
|
714
715
|
tags: new Set(),
|
|
@@ -719,9 +720,9 @@ export async function collectRenderCacheMeta<T>(
|
|
|
719
720
|
prerender: options.prerender,
|
|
720
721
|
handler: options.handler,
|
|
721
722
|
dynamicError: options.dynamicError,
|
|
722
|
-
}
|
|
723
|
-
const value = await cacheMetaStorage.run(meta, produce)
|
|
724
|
-
await drainStaticAfterTasks(meta)
|
|
723
|
+
}
|
|
724
|
+
const value = await cacheMetaStorage.run(meta, produce)
|
|
725
|
+
await drainStaticAfterTasks(meta)
|
|
725
726
|
return {
|
|
726
727
|
value,
|
|
727
728
|
tags: [...meta.tags],
|
|
@@ -729,7 +730,7 @@ export async function collectRenderCacheMeta<T>(
|
|
|
729
730
|
...(meta.expireSeconds !== undefined ? { expireSeconds: meta.expireSeconds } : {}),
|
|
730
731
|
...(meta.staleSeconds !== undefined ? { staleSeconds: meta.staleSeconds } : {}),
|
|
731
732
|
...(meta.noStore ? { noStore: true } : {}),
|
|
732
|
-
}
|
|
733
|
+
}
|
|
733
734
|
}
|
|
734
735
|
|
|
735
736
|
/**
|
|
@@ -743,16 +744,16 @@ export async function collectRenderCacheMeta<T>(
|
|
|
743
744
|
*/
|
|
744
745
|
async function drainStaticAfterTasks(meta: RenderCacheMeta): Promise<void> {
|
|
745
746
|
while (meta.afterTasks?.length) {
|
|
746
|
-
const tasks = meta.afterTasks
|
|
747
|
-
meta.afterTasks = []
|
|
747
|
+
const tasks = meta.afterTasks
|
|
748
|
+
meta.afterTasks = []
|
|
748
749
|
for (const task of tasks) {
|
|
749
750
|
try {
|
|
750
|
-
await cacheMetaStorage.run(meta, task)
|
|
751
|
+
await cacheMetaStorage.run(meta, task)
|
|
751
752
|
} catch (error) {
|
|
752
753
|
console.error(
|
|
753
754
|
`Error occurred prerendering page "${meta.route ?? '/'}". Read more: https://nextjs.org/docs/messages/prerender-error`,
|
|
754
|
-
)
|
|
755
|
-
throw error
|
|
755
|
+
)
|
|
756
|
+
throw error
|
|
756
757
|
}
|
|
757
758
|
}
|
|
758
759
|
}
|