vinext 1.3.1 → 1.4.0
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 +5 -2
- package/THIRD_PARTY_LICENSES.md +47 -0
- package/dist/_virtual/_rolldown/runtime.js +3 -2
- package/dist/build/prerender.js +1 -1
- package/dist/build/report.d.ts +0 -14
- package/dist/build/report.js +1 -51
- package/dist/check.js +1 -1
- package/dist/cli.js +3 -0
- package/dist/client/dev-error-overlay.js +1 -1
- package/dist/client/navigation-runtime.d.ts +13 -1
- package/dist/client/navigation-runtime.js +1 -1
- package/dist/config/next-config.d.ts +19 -0
- package/dist/config/next-config.js +64 -1
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-codec.js +327 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/dbcs-data.js +123 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/index.js +29 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/internal.js +134 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-codec.js +50 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data-generated.js +455 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/sbcs-data.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/big5-added.json.js +169 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp936.json.js +2584 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp949.json.js +2220 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/cp950.json.js +227 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/eucjp.json.js +425 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gb18030-ranges.json.js +427 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/gbk-added.json.js +229 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/tables/shiftjis.json.js +292 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf16.js +106 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/encodings/utf7.js +182 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/bom-handling.js +42 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/extend-node.js +147 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/index.js +94 -0
- package/dist/deps/.pnpm/iconv-lite@0.4.24/deps/iconv-lite/lib/streams.js +95 -0
- package/dist/deps/.pnpm/safer-buffer@2.1.2/deps/safer-buffer/safer.js +45 -0
- package/dist/entries/app-rsc-entry.js +17 -48
- package/dist/entries/app-rsc-manifest.js +3 -4
- package/dist/entries/app-ssr-entry.js +1 -0
- package/dist/entries/pages-server-entry.js +33 -8
- package/dist/index.js +83 -70
- package/dist/init-cloudflare.d.ts +1 -3
- package/dist/init-cloudflare.js +10 -48
- package/dist/init-platform.d.ts +2 -0
- package/dist/init-platform.js +4 -0
- package/dist/plugins/extensionless-dynamic-import.js +6 -2
- package/dist/plugins/next-intl-catalog.d.ts +12 -0
- package/dist/plugins/next-intl-catalog.js +85 -0
- package/dist/plugins/pages-node-externals.d.ts +1 -0
- package/dist/plugins/pages-node-externals.js +1 -1
- package/dist/plugins/use-cache-callable.d.ts +1 -1
- package/dist/plugins/use-cache-callable.js +136 -94
- package/dist/routing/app-route-graph.d.ts +6 -0
- package/dist/routing/app-route-graph.js +9 -1
- package/dist/server/api-handler.js +19 -4
- package/dist/server/app-bfcache-identity.js +1 -1
- package/dist/server/app-browser-entry.js +79 -63
- package/dist/server/app-browser-history-controller.d.ts +5 -4
- package/dist/server/app-browser-history-controller.js +93 -15
- package/dist/server/app-browser-navigation-controller.d.ts +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -2
- package/dist/server/app-browser-rsc-redirect.js +4 -4
- package/dist/server/app-browser-server-action-client.d.ts +2 -0
- package/dist/server/app-browser-server-action-client.js +4 -3
- package/dist/server/app-browser-state.d.ts +2 -4
- package/dist/server/app-browser-state.js +9 -4
- package/dist/server/app-browser-supplemental-refresh.js +16 -1
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-browser-visible-commit.js +2 -12
- package/dist/server/app-elements-wire.d.ts +6 -38
- package/dist/server/app-elements-wire.js +4 -41
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-history-state.d.ts +2 -2
- package/dist/server/app-history-state.js +5 -2
- package/dist/server/app-mounted-layouts.d.ts +21 -0
- package/dist/server/app-mounted-layouts.js +67 -0
- package/dist/server/app-optimistic-routing.d.ts +19 -1
- package/dist/server/app-optimistic-routing.js +42 -2
- package/dist/server/app-page-boundary-render.js +7 -6
- package/dist/server/app-page-boundary.js +2 -2
- package/dist/server/app-page-cache-finalizer.d.ts +12 -1
- package/dist/server/app-page-cache-finalizer.js +70 -29
- package/dist/server/app-page-cache.d.ts +13 -1
- package/dist/server/app-page-cache.js +31 -9
- package/dist/server/app-page-dispatch.d.ts +5 -10
- package/dist/server/app-page-dispatch.js +84 -154
- package/dist/server/app-page-element-builder.d.ts +2 -2
- package/dist/server/app-page-element-builder.js +10 -9
- package/dist/server/app-page-execution.d.ts +17 -52
- package/dist/server/app-page-execution.js +99 -95
- package/dist/server/app-page-head.d.ts +13 -0
- package/dist/server/app-page-head.js +44 -16
- package/dist/server/app-page-http-access-fallback-metadata.d.ts +1 -0
- package/dist/server/app-page-http-access-fallback-metadata.js +2 -2
- package/dist/server/app-page-layout-gate.d.ts +35 -0
- package/dist/server/app-page-layout-gate.js +50 -0
- package/dist/server/app-page-params.d.ts +0 -1
- package/dist/server/app-page-params.js +1 -14
- package/dist/server/app-page-probe.d.ts +3 -21
- package/dist/server/app-page-probe.js +4 -37
- package/dist/server/app-page-render.d.ts +2 -12
- package/dist/server/app-page-render.js +89 -220
- package/dist/server/app-page-request.d.ts +1 -3
- package/dist/server/app-page-request.js +1 -1
- package/dist/server/app-page-response.js +3 -3
- package/dist/server/app-page-route-wiring.d.ts +13 -6
- package/dist/server/app-page-route-wiring.js +67 -61
- package/dist/server/app-page-rsc-render-status.d.ts +27 -1
- package/dist/server/app-page-rsc-render-status.js +121 -13
- package/dist/server/app-page-stream.d.ts +2 -0
- package/dist/server/app-page-stream.js +2 -2
- package/dist/server/app-pages-bridge.d.ts +4 -0
- package/dist/server/app-pages-bridge.js +7 -3
- package/dist/server/app-render-dependency.d.ts +11 -4
- package/dist/server/app-render-dependency.js +86 -38
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-route-handler-cache.js +2 -2
- package/dist/server/app-route-handler-dispatch.js +14 -9
- package/dist/server/app-route-handler-execution.js +8 -3
- package/dist/server/app-route-handler-policy.d.ts +1 -1
- package/dist/server/app-route-handler-policy.js +3 -3
- package/dist/server/app-route-handler-response.js +1 -1
- package/dist/server/app-route-handler-runtime.js +17 -4
- package/dist/server/app-rsc-cache-busting.d.ts +2 -2
- package/dist/server/app-rsc-cache-busting.js +4 -4
- package/dist/server/app-rsc-error-handler.d.ts +2 -1
- package/dist/server/app-rsc-error-handler.js +9 -1
- package/dist/server/app-rsc-errors.d.ts +8 -0
- package/dist/server/app-rsc-errors.js +8 -1
- package/dist/server/app-rsc-handler.d.ts +5 -5
- package/dist/server/app-rsc-handler.js +30 -24
- package/dist/server/app-rsc-request-normalization.d.ts +0 -4
- package/dist/server/app-rsc-request-normalization.js +1 -4
- package/dist/server/app-rsc-response-finalizer.js +2 -2
- package/dist/server/app-rsc-response-stage.js +5 -3
- package/dist/server/app-server-action-execution.d.ts +3 -1
- package/dist/server/app-server-action-execution.js +7 -4
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +9 -8
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/app-visited-response-cache.d.ts +36 -1
- package/dist/server/app-visited-response-cache.js +46 -5
- package/dist/server/app-worker-stages.d.ts +25 -3
- package/dist/server/app-worker-stages.js +45 -6
- package/dist/server/artifact-compatibility.d.ts +0 -1
- package/dist/server/artifact-compatibility.js +1 -10
- package/dist/server/cache-proof.d.ts +1 -115
- package/dist/server/cache-proof.js +1 -544
- package/dist/server/cacheability-request.js +13 -8
- package/dist/server/dev-server.js +4 -3
- package/dist/server/headers.d.ts +6 -3
- package/dist/server/headers.js +9 -5
- package/dist/server/isr-cache.d.ts +8 -2
- package/dist/server/isr-cache.js +26 -1
- package/dist/server/metadata-route-response.js +32 -15
- package/dist/server/multi-stage.d.ts +52 -11
- package/dist/server/multi-stage.js +13 -1
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/pages-api-route.js +28 -19
- package/dist/server/pages-media-type.d.ts +21 -1
- package/dist/server/pages-media-type.js +69 -5
- package/dist/server/pages-node-compat.js +52 -27
- package/dist/server/pages-page-handler.js +11 -20
- package/dist/server/pages-request-pipeline.d.ts +8 -0
- package/dist/server/pages-request-pipeline.js +2 -2
- package/dist/server/pages-request-stage-entry.js +14 -12
- package/dist/server/pages-response-stage-entry.js +9 -3
- package/dist/server/prod-server.js +5 -1
- package/dist/server/request-pipeline.d.ts +6 -0
- package/dist/server/request-pipeline.js +21 -1
- package/dist/server/shared-cache-identity.d.ts +23 -0
- package/dist/server/shared-cache-identity.js +36 -0
- package/dist/server/worker-stages.d.ts +16 -3
- package/dist/server/worker-stages.js +23 -4
- package/dist/shims/cache-handler.js +2 -2
- package/dist/shims/cache-request-state.d.ts +17 -20
- package/dist/shims/cache-request-state.js +16 -21
- package/dist/shims/cache-runtime.js +27 -11
- package/dist/shims/cache.d.ts +8 -7
- package/dist/shims/cache.js +17 -19
- package/dist/shims/cacheability-classification.d.ts +2 -0
- package/dist/shims/cdn-cache.d.ts +22 -5
- package/dist/shims/client-page-root.js +2 -2
- package/dist/shims/dynamic.js +9 -6
- package/dist/shims/error-boundary.js +2 -2
- package/dist/shims/fetch-cache-state.d.ts +5 -1
- package/dist/shims/fetch-cache-state.js +1 -3
- package/dist/shims/fetch-cache.d.ts +2 -1
- package/dist/shims/fetch-cache.js +34 -24
- package/dist/shims/form.js +2 -2
- package/dist/shims/headers.d.ts +8 -23
- package/dist/shims/headers.js +17 -67
- package/dist/shims/internal/navigation-untracked.js +1 -1
- package/dist/shims/link.js +3 -1
- package/dist/shims/metadata.d.ts +23 -21
- package/dist/shims/metadata.js +62 -24
- package/dist/shims/navigation-server.js +1 -1
- package/dist/shims/navigation.d.ts +74 -7
- package/dist/shims/navigation.js +183 -29
- package/dist/shims/navigation.react-server.js +2 -2
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/slot.d.ts +12 -0
- package/dist/shims/slot.js +37 -9
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +2 -3
- package/dist/utils/cache-control-metadata.d.ts +5 -0
- package/dist/utils/cache-control-metadata.js +9 -1
- package/dist/utils/project.d.ts +2 -2
- package/dist/utils/project.js +3 -16
- package/dist/utils/regex.d.ts +5 -0
- package/dist/utils/regex.js +11 -1
- package/dist/utils/text-stream.d.ts +10 -5
- package/dist/utils/text-stream.js +6 -6
- package/package.json +2 -1
- package/dist/build/layout-classification-types.d.ts +0 -60
- package/dist/build/layout-classification-types.js +0 -1
- package/dist/build/layout-classification.d.ts +0 -62
- package/dist/build/layout-classification.js +0 -98
- package/dist/build/route-classification-injector.d.ts +0 -33
- package/dist/build/route-classification-injector.js +0 -59
- package/dist/build/route-classification-manifest.d.ts +0 -54
- package/dist/build/route-classification-manifest.js +0 -143
- package/dist/server/app-browser-client-reuse-manifest.d.ts +0 -11
- package/dist/server/app-browser-client-reuse-manifest.js +0 -101
- package/dist/server/app-layout-param-observation.d.ts +0 -42
- package/dist/server/app-layout-param-observation.js +0 -168
- package/dist/server/client-reuse-manifest.d.ts +0 -103
- package/dist/server/client-reuse-manifest.js +0 -209
- package/dist/server/skip-cache-proof.d.ts +0 -60
- package/dist/server/skip-cache-proof.js +0 -168
- package/dist/server/static-layout-client-reuse-proof.d.ts +0 -14
- package/dist/server/static-layout-client-reuse-proof.js +0 -33
- package/dist/utils/sorted-array.d.ts +0 -8
- package/dist/utils/sorted-array.js +0 -20
|
@@ -11,7 +11,7 @@ import { createPprFallbackShellSuspensePromise, trackPprFallbackShellCacheTask }
|
|
|
11
11
|
import { createUseCacheAccessError, markDynamicUsage, recordInvalidDynamicUsageError } from "./internal/headers-state.js";
|
|
12
12
|
import { isDraftModeEnabled } from "./headers.js";
|
|
13
13
|
import { _registerCacheContextAccessor } from "./internal/cache-context-accessor.js";
|
|
14
|
-
import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife, cacheLifeProfiles, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
14
|
+
import { _hasPendingRevalidatedTag, _isOnDemandRevalidate, _setRequestScopedCacheLife, cacheLifeProfiles, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
15
15
|
import "./fetch-cache.js";
|
|
16
16
|
import { hasUseCacheLayoutMarker, hasUseCachePageMarker, isUseCacheFunctionReference, withoutUseCacheSegmentMarker } from "./internal/app-page-props-cache-key.js";
|
|
17
17
|
import { isWellKnownProperty } from "./internal/thenable-well-known-properties.js";
|
|
@@ -389,7 +389,7 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
389
389
|
if (knownRootParamNames && rootParams) cacheKey += computeRootParamsCacheKeySuffix(rootParams, knownRootParamNames);
|
|
390
390
|
const softTags = getCurrentFetchSoftTags();
|
|
391
391
|
let existing = null;
|
|
392
|
-
if (!_hasPendingRevalidatedTag(softTags)) try {
|
|
392
|
+
if (!_hasPendingRevalidatedTag(softTags) && !_isOnDemandRevalidate()) try {
|
|
393
393
|
existing = await handler.get(cacheKey, {
|
|
394
394
|
kind: "FETCH",
|
|
395
395
|
softTags
|
|
@@ -398,8 +398,10 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
398
398
|
console.error("[vinext] use cache: handler.get failed; treating as a cache miss:", error);
|
|
399
399
|
}
|
|
400
400
|
const redirectValue = existing?.value;
|
|
401
|
+
let staleRedirect;
|
|
401
402
|
if (isRootParamRedirect(existing) && isServableCacheState(existing?.cacheState) && rootParams && redirectValue?.kind === "FETCH" && !_hasPendingRevalidatedTag([...redirectValue.tags ?? [], ...softTags])) {
|
|
402
403
|
cacheKey = coarseCacheKey + computeRootParamsCacheKeySuffix(rootParams, addKnownRootParamNames(id, rootParamNamesFromTags(redirectValue.tags)));
|
|
404
|
+
if (existing?.cacheState) staleRedirect = existing;
|
|
403
405
|
try {
|
|
404
406
|
existing = await handler.get(cacheKey, {
|
|
405
407
|
kind: "FETCH",
|
|
@@ -410,7 +412,8 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
410
412
|
existing = null;
|
|
411
413
|
}
|
|
412
414
|
}
|
|
413
|
-
const generate = async (propagate) => {
|
|
415
|
+
const generate = async (propagate, staleEntry) => {
|
|
416
|
+
const timestamp = Date.now();
|
|
414
417
|
const { result, ctx, effectiveLife, collectedResult } = await runCachedFunctionWithContext(callFn, callArgs, cacheVariant, (value) => serializeCacheResult(value, rsc));
|
|
415
418
|
const rootParamNames = ctx.readRootParamNames && ctx.readRootParamNames.size > 0 ? addKnownRootParamNames(id, ctx.readRootParamNames) : knownRootParamsByFunctionId.get(id);
|
|
416
419
|
if (propagate) {
|
|
@@ -442,6 +445,7 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
442
445
|
const cacheContext = {
|
|
443
446
|
fetchCache: true,
|
|
444
447
|
tags: ctx.tags,
|
|
448
|
+
timestamp,
|
|
445
449
|
...cacheFunctionInvocation ? { cacheFunctionInvocation } : {},
|
|
446
450
|
cacheControl: {
|
|
447
451
|
revalidate: revalidateSeconds,
|
|
@@ -463,11 +467,18 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
463
467
|
revalidate: revalidateSeconds
|
|
464
468
|
}, {
|
|
465
469
|
...cacheContext,
|
|
466
|
-
tags: redirectTags
|
|
470
|
+
tags: redirectTags,
|
|
471
|
+
...coarseCacheKey === cacheKey ? staleEntry && { staleEntry } : staleRedirect && { staleEntry: staleRedirect }
|
|
467
472
|
});
|
|
468
473
|
cacheValue.data.url = specificCacheKey;
|
|
469
|
-
await handler.set(specificCacheKey, cacheValue,
|
|
470
|
-
|
|
474
|
+
await handler.set(specificCacheKey, cacheValue, {
|
|
475
|
+
...cacheContext,
|
|
476
|
+
...staleEntry && specificCacheKey === cacheKey ? { staleEntry } : {}
|
|
477
|
+
});
|
|
478
|
+
} else await handler.set(cacheKey, cacheValue, {
|
|
479
|
+
...cacheContext,
|
|
480
|
+
...staleEntry ? { staleEntry } : {}
|
|
481
|
+
});
|
|
471
482
|
} catch {}
|
|
472
483
|
return collectedResult ? collectedResult.result : result;
|
|
473
484
|
};
|
|
@@ -476,10 +487,13 @@ function registerCachedFunction(fn, id, variant, options = {}) {
|
|
|
476
487
|
propagateCacheTagsToRequest(existing.value.tags);
|
|
477
488
|
const result = await rsc.createFromReadableStream(uint8ToStream(base64ToUint8(existing.value.data.body)), {}, { preserveServerReferences: true });
|
|
478
489
|
recordRequestScopedCacheControl(existing.cacheControl);
|
|
479
|
-
if (existing.cacheState === "stale")
|
|
490
|
+
if (existing.cacheState === "stale") {
|
|
491
|
+
const staleEntry = existing;
|
|
492
|
+
regenerateInBackground(id, () => generate(false, staleEntry));
|
|
493
|
+
}
|
|
480
494
|
return result;
|
|
481
495
|
} catch {}
|
|
482
|
-
return generate(true);
|
|
496
|
+
return generate(true, existing?.cacheState ? existing : void 0);
|
|
483
497
|
}, cacheVariant);
|
|
484
498
|
};
|
|
485
499
|
const cachedFn = memoizeInCacheScope((...args) => invoke(args));
|
|
@@ -589,9 +603,11 @@ async function runCachedFunctionWithContext(fn, args, variant, collectResult) {
|
|
|
589
603
|
let collectedResult;
|
|
590
604
|
const workUnitType = variant === "private" ? "private-cache" : "cache";
|
|
591
605
|
const result = await workUnitAsyncStorage.run({ type: workUnitType }, () => cacheContextStorage.run(ctx, async () => {
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
606
|
+
if (!collectResult) return await fn(...args);
|
|
607
|
+
let value;
|
|
608
|
+
const lazyValue = { then: (onFulfilled, onRejected) => (value ??= new Promise((resolve) => resolve(fn(...args)))).then(onFulfilled, onRejected) };
|
|
609
|
+
collectedResult = await collectResult(lazyValue, ctx);
|
|
610
|
+
return await lazyValue;
|
|
595
611
|
}));
|
|
596
612
|
if (ctx.invalidDynamicUsageError) throw ctx.invalidDynamicUsageError;
|
|
597
613
|
const effectiveLife = resolveCacheLife(ctx.lifeConfigs);
|
package/dist/shims/cache.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ExecutionContextLike, getRequestExecutionContext, runWithExecutionContext } from "./request-context.js";
|
|
2
|
-
import { _recordUseCacheRootParamRead, _registerCacheContextAccessor, getRegisteredCacheContext } from "./internal/cache-context-accessor.js";
|
|
3
|
-
import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheLifeSink, CacheState, PendingCdnTagInvalidation, UnstableCacheObservation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _peekUnstableCacheObservations, _queuePendingCdnTagInvalidation, _queuePendingRevalidation, _revalidateCdnTags, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, markActionRevalidation, recordUnstableCacheObservation, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
4
2
|
import { CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, registerDataCacheHandler, registerLazyDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
|
|
3
|
+
import { _recordUseCacheRootParamRead, _registerCacheContextAccessor, getRegisteredCacheContext } from "./internal/cache-context-accessor.js";
|
|
4
|
+
import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheLifeConfig, CacheState, PendingCdnTagInvalidation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _isOnDemandRevalidate, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _queuePendingCdnTagInvalidation, _queuePendingRevalidation, _revalidateCdnTags, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, markActionRevalidation, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
5
5
|
//#region src/shims/cache.d.ts
|
|
6
6
|
/**
|
|
7
7
|
* Revalidate cached data associated with a specific cache tag.
|
|
@@ -61,10 +61,11 @@ export declare function updateTag(tag: string): undefined;
|
|
|
61
61
|
/**
|
|
62
62
|
* Opt out of static rendering and indicate a particular component should not be cached.
|
|
63
63
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
64
|
+
* Without Cache Components this marks the render dynamic, so the page is not
|
|
65
|
+
* stored. With Cache Components it does nothing, as in Next.js: its prerenders
|
|
66
|
+
* ignore it, and on a request it doesn't make the page dynamic, so the page
|
|
67
|
+
* stays static and cacheable.
|
|
68
|
+
* Source: https://github.com/vercel/next.js/blob/canary/packages/next/src/server/web/spec-extension/unstable-no-store.ts
|
|
68
69
|
*/
|
|
69
70
|
export declare function unstable_noStore(): void;
|
|
70
71
|
/**
|
|
@@ -142,4 +143,4 @@ type UnstableCacheOptions = {
|
|
|
142
143
|
*/
|
|
143
144
|
export declare function unstable_cache<T extends (...args: any[]) => Promise<any>>(fn: T, keyParts?: string[], options?: UnstableCacheOptions): T;
|
|
144
145
|
//#endregion
|
|
145
|
-
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig,
|
|
146
|
+
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, ActionRevalidationKind, CacheControlMetadata, CacheHandler, CacheHandlerContext, CacheHandlerValue, CacheLifeConfig, CacheState, CachedAppPageValue, CachedFetchValue, CachedImageValue, CachedPagesValue, CachedRedirectValue, CachedRouteValue, type ExecutionContextLike, IncrementalCacheValue, MemoryCacheHandler, NoOpCacheHandler, PendingCdnTagInvalidation, UnstableCacheRevalidationMode, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _isOnDemandRevalidate, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _queuePendingCdnTagInvalidation, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _revalidateCdnTags, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, markActionRevalidation, unstable_noStore as noStore, registerDataCacheHandler, registerLazyDataCacheHandler, runWithDetachedCacheObservations, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry };
|
package/dist/shims/cache.js
CHANGED
|
@@ -6,13 +6,13 @@ import { workUnitAsyncStorage } from "./internal/work-unit-async-storage.js";
|
|
|
6
6
|
import { isStagedCacheabilityProbeActive } from "./cacheability-classification.js";
|
|
7
7
|
import { MemoryCacheHandler, NoOpCacheHandler, configureMemoryCacheHandler, getCacheHandler, getDataCacheHandler, registerDataCacheHandler, registerLazyDataCacheHandler, setCacheHandler, setDataCacheHandler } from "./cache-handler.js";
|
|
8
8
|
import { encodeCacheTag, encodeCacheTags } from "../utils/encode-cache-tag.js";
|
|
9
|
-
import {
|
|
9
|
+
import { sha256Hex } from "../utils/hash.js";
|
|
10
10
|
import { addCollectedRequestTags, getCurrentFetchSoftTags, runWithDetachedFetchObservations } from "./fetch-cache-state.js";
|
|
11
11
|
import { makeHangingPromise } from "./internal/make-hanging-promise.js";
|
|
12
12
|
import { getHeadersAccessPhase, markDynamicUsage } from "./internal/headers-state.js";
|
|
13
13
|
import { isDraftModeEnabled } from "./headers.js";
|
|
14
14
|
import { _recordUseCacheRootParamRead, _registerCacheContextAccessor, getRegisteredCacheContext } from "./internal/cache-context-accessor.js";
|
|
15
|
-
import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife,
|
|
15
|
+
import { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _isOnDemandRevalidate, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _queuePendingCdnTagInvalidation, _queuePendingRevalidation, _revalidateCdnTags, _runWithCacheState, _setRequestScopedCacheLife, cacheLifeProfiles, getAndClearActionRevalidationKind, markActionRevalidation, runWithDetachedCacheObservations, shouldServeStaleUnstableCacheEntry } from "./cache-request-state.js";
|
|
16
16
|
import { isPathKnownNotEdgeCached } from "./cdn-purge-routes.js";
|
|
17
17
|
//#region src/shims/cache.ts
|
|
18
18
|
/**
|
|
@@ -154,13 +154,15 @@ function updateTag(tag) {
|
|
|
154
154
|
/**
|
|
155
155
|
* Opt out of static rendering and indicate a particular component should not be cached.
|
|
156
156
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
157
|
+
* Without Cache Components this marks the render dynamic, so the page is not
|
|
158
|
+
* stored. With Cache Components it does nothing, as in Next.js: its prerenders
|
|
159
|
+
* ignore it, and on a request it doesn't make the page dynamic, so the page
|
|
160
|
+
* stays static and cacheable.
|
|
161
|
+
* Source: https://github.com/vercel/next.js/blob/canary/packages/next/src/server/web/spec-extension/unstable-no-store.ts
|
|
161
162
|
*/
|
|
162
163
|
function unstable_noStore() {
|
|
163
164
|
if (isInsideUnstableCacheScope()) return;
|
|
165
|
+
if (String(process.env.__NEXT_CACHE_COMPONENTS) === "true") return;
|
|
164
166
|
markDynamicUsage();
|
|
165
167
|
}
|
|
166
168
|
/**
|
|
@@ -394,7 +396,7 @@ function scheduleUnstableCacheBackgroundRevalidation(cacheKey, refresh) {
|
|
|
394
396
|
pending.set(cacheKey, trackedRevalidation);
|
|
395
397
|
waitUntilUnstableCacheRevalidation(trackedRevalidation);
|
|
396
398
|
}
|
|
397
|
-
async function refreshUnstableCacheResult(fn, args, keyedArgs, cacheKey, tags, revalidateSeconds) {
|
|
399
|
+
async function refreshUnstableCacheResult(fn, args, keyedArgs, cacheKey, tags, revalidateSeconds, staleEntry) {
|
|
398
400
|
const argsUnchanged = serializeArgsOrNull(args) === keyedArgs;
|
|
399
401
|
const result = await _unstableCacheAls.run(true, () => _unstableCacheCallbackAls.run({ useCacheContext: _useCacheContextAls.getStore() }, () => fn(...args)));
|
|
400
402
|
if (!argsUnchanged) return result;
|
|
@@ -411,7 +413,8 @@ async function refreshUnstableCacheResult(fn, args, keyedArgs, cacheKey, tags, r
|
|
|
411
413
|
await getDataCacheHandler().set(cacheKey, cacheValue, {
|
|
412
414
|
fetchCache: true,
|
|
413
415
|
tags,
|
|
414
|
-
revalidate: revalidateSeconds
|
|
416
|
+
revalidate: revalidateSeconds,
|
|
417
|
+
...staleEntry ? { staleEntry } : {}
|
|
415
418
|
});
|
|
416
419
|
return result;
|
|
417
420
|
}
|
|
@@ -439,16 +442,10 @@ function unstable_cache(fn, keyParts, options) {
|
|
|
439
442
|
const keyedArgs = JSON.stringify(args);
|
|
440
443
|
const invocationKey = `${fixedKey}${keyedArgs}`;
|
|
441
444
|
addCollectedRequestTags(tags);
|
|
442
|
-
recordUnstableCacheObservation({
|
|
443
|
-
kind: "unstable_cache",
|
|
444
|
-
keyHash: fnv1a64(invocationKey),
|
|
445
|
-
revalidate: typeof revalidateSeconds === "number" ? revalidateSeconds : revalidateSeconds === false ? false : null,
|
|
446
|
-
tagCount: tags.length,
|
|
447
|
-
tagHash: tags.length > 0 ? fnv1a64(JSON.stringify(tags)) : null
|
|
448
|
-
});
|
|
449
445
|
const cacheKey = `${UNSTABLE_CACHE_KEY_PREFIX}:${await sha256Hex(invocationKey)}`;
|
|
450
446
|
const isDraftMode = isDraftModeEnabled();
|
|
451
|
-
|
|
447
|
+
let staleEntry;
|
|
448
|
+
if (!isDraftMode && !isNestedUnstableCacheCall() && !_isOnDemandRevalidate()) {
|
|
452
449
|
const softTags = getCurrentFetchSoftTags();
|
|
453
450
|
const existing = _hasPendingRevalidatedTag([...tags, ...softTags]) ? null : await getDataCacheHandler().get(cacheKey, {
|
|
454
451
|
kind: "FETCH",
|
|
@@ -457,10 +454,11 @@ function unstable_cache(fn, keyParts, options) {
|
|
|
457
454
|
});
|
|
458
455
|
if (existing?.value && existing.value.kind === "FETCH") {
|
|
459
456
|
const cached = tryDeserializeUnstableCacheResult(existing.value.data.body);
|
|
457
|
+
if (existing.cacheState === "stale") staleEntry = existing;
|
|
460
458
|
if (cached.ok) {
|
|
461
459
|
if (existing.cacheState === "stale") {
|
|
462
460
|
if (shouldServeStaleUnstableCacheEntry()) {
|
|
463
|
-
scheduleUnstableCacheBackgroundRevalidation(cacheKey, () => refreshUnstableCacheResult(fn, args, keyedArgs, cacheKey, tags, revalidateSeconds));
|
|
461
|
+
scheduleUnstableCacheBackgroundRevalidation(cacheKey, () => refreshUnstableCacheResult(fn, args, keyedArgs, cacheKey, tags, revalidateSeconds, staleEntry));
|
|
464
462
|
return cached.value;
|
|
465
463
|
}
|
|
466
464
|
} else return cached.value;
|
|
@@ -468,9 +466,9 @@ function unstable_cache(fn, keyParts, options) {
|
|
|
468
466
|
}
|
|
469
467
|
}
|
|
470
468
|
if (isDraftMode) return await _unstableCacheAls.run(true, () => fn(...args));
|
|
471
|
-
return await refreshUnstableCacheResult(fn, args, keyedArgs, cacheKey, tags, revalidateSeconds);
|
|
469
|
+
return await refreshUnstableCacheResult(fn, args, keyedArgs, cacheKey, tags, revalidateSeconds, staleEntry);
|
|
472
470
|
};
|
|
473
471
|
return cachedFn;
|
|
474
472
|
}
|
|
475
473
|
//#endregion
|
|
476
|
-
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, MemoryCacheHandler, NoOpCacheHandler, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _markPendingRevalidatedTag, _peekRequestScopedCacheLife,
|
|
474
|
+
export { ACTION_DID_REVALIDATE_DYNAMIC_ONLY, ACTION_DID_REVALIDATE_STATIC_AND_DYNAMIC, MemoryCacheHandler, NoOpCacheHandler, _captureRequestScopedCacheLifeAccessors, _consumeRequestScopedCacheLife, _drainPendingRevalidations, _hasPendingRevalidatedTag, _initRequestScopedCacheState, _isOnDemandRevalidate, _markPendingRevalidatedTag, _peekRequestScopedCacheLife, _queuePendingCdnTagInvalidation, _queuePendingRevalidation, _recordUseCacheRootParamRead, _registerCacheContextAccessor, _revalidateCdnTags, _runWithCacheState, _setRequestScopedCacheLife, cacheLife, cacheLifeProfiles, cacheTag, configureMemoryCacheHandler, getAndClearActionRevalidationKind, getCacheHandler, getDataCacheHandler, getRegisteredCacheContext, getRequestExecutionContext, io, isInsideUnstableCacheScope, markActionRevalidation, unstable_noStore as noStore, unstable_noStore, refresh, registerDataCacheHandler, registerLazyDataCacheHandler, revalidatePath, revalidateTag, runWithDetachedCacheObservations, runWithExecutionContext, setCacheHandler, setDataCacheHandler, shouldServeStaleUnstableCacheEntry, unstable_cache, unstable_cacheLife, unstable_cacheTag, unstable_io, updateTag };
|
|
@@ -17,6 +17,8 @@ export type RouteCacheabilityOutcome = {
|
|
|
17
17
|
*/
|
|
18
18
|
status?: number;
|
|
19
19
|
headers?: Readonly<Record<string, string>>;
|
|
20
|
+
/** App pages: the client-router stale time from the completed render's cacheLife. */
|
|
21
|
+
staleTimeSeconds?: number;
|
|
20
22
|
tags?: readonly string[];
|
|
21
23
|
};
|
|
22
24
|
export type RouteCacheabilityState = {
|
|
@@ -32,6 +32,12 @@ export type CdnCacheableHeaderInput = {
|
|
|
32
32
|
*/
|
|
33
33
|
tags?: readonly string[];
|
|
34
34
|
};
|
|
35
|
+
/** A page's document, rendered from an RSC request's payload. */
|
|
36
|
+
export type CdnAppPageDocument = {
|
|
37
|
+
html: string;
|
|
38
|
+
/** The renderer's own `Link` header. */
|
|
39
|
+
linkHeader?: string;
|
|
40
|
+
};
|
|
35
41
|
export type CdnResponsePolicy = {
|
|
36
42
|
/** Whether a provider-specific response header controls shared caching. */
|
|
37
43
|
isHeader(name: string): boolean;
|
|
@@ -76,12 +82,15 @@ export type CdnCacheAdapter = {
|
|
|
76
82
|
*/
|
|
77
83
|
readonly requiresCompletedResponseAdmission?: boolean;
|
|
78
84
|
/**
|
|
79
|
-
* This adapter's response-stage transport keys shared
|
|
80
|
-
* `VinextResponseStageDispatchOptions.cacheIdentity` when core supplies
|
|
81
|
-
* Core supplies it only when completed-response admission is also
|
|
82
|
-
* because that admission is what makes a
|
|
85
|
+
* This adapter's response-stage transport keys shared dispatches by
|
|
86
|
+
* `VinextResponseStageDispatchOptions.cacheIdentity` when core supplies
|
|
87
|
+
* one. Core supplies it only when completed-response admission is also
|
|
88
|
+
* required, because that admission is what makes a host-free identity, and
|
|
89
|
+
* a page's query-free one, safe. `"query-free"` also drops the user query
|
|
90
|
+
* from App page identities; `"host-free"` keeps every dispatch's query, for
|
|
91
|
+
* a transport whose cache keys the dispatched query itself.
|
|
83
92
|
*/
|
|
84
|
-
readonly responseStageCacheIdentity?: "query-free";
|
|
93
|
+
readonly responseStageCacheIdentity?: "host-free" | "query-free";
|
|
85
94
|
/**
|
|
86
95
|
* Optionally return a foreground page response while completed-response
|
|
87
96
|
* admission continues on an independent body branch. Returning `null` keeps
|
|
@@ -90,6 +99,14 @@ export type CdnCacheAdapter = {
|
|
|
90
99
|
deferCompletedPageResponseAdmission?(response: Response, complete: (response: Response) => Promise<Response>): Response | null;
|
|
91
100
|
/** Capture the full-route RSC side stream while admitting a completed HTML response. */
|
|
92
101
|
captureAppPageRscData?(rscData: Promise<ArrayBuffer>): void;
|
|
102
|
+
/**
|
|
103
|
+
* Store the page's document beside an RSC request's completed response, as
|
|
104
|
+
* Next.js keeps a page's document and RSC payload in one entry. Returns the
|
|
105
|
+
* callback admission calls with the document the render rendered from its
|
|
106
|
+
* payload, or with `null` when the page has no document to store, or
|
|
107
|
+
* `undefined` when this render's response stores no document.
|
|
108
|
+
*/
|
|
109
|
+
captureAppPageDocument?(): ((document: CdnAppPageDocument | null) => void) | undefined;
|
|
93
110
|
/**
|
|
94
111
|
* Whether this adapter sends the 304 for a Pages render whose If-None-Match
|
|
95
112
|
* matches. When it does, the render returns the page, so an adapter that
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { searchParamsToRecord } from "../utils/query.js";
|
|
3
3
|
import { getNavigationContext } from "./navigation-context-state.js";
|
|
4
|
+
import { getClientNavigationRenderContext, useSearchParams } from "./navigation.js";
|
|
4
5
|
import "./navigation-server.js";
|
|
5
|
-
import { isOwnPropertyCheck, isWellKnownProperty } from "./internal/thenable-well-known-properties.js";
|
|
6
6
|
import { RenderedSearchContext } from "./slot.js";
|
|
7
|
-
import {
|
|
7
|
+
import { isOwnPropertyCheck, isWellKnownProperty } from "./internal/thenable-well-known-properties.js";
|
|
8
8
|
import { createElement, use, useMemo } from "react";
|
|
9
9
|
//#region src/shims/client-page-root.tsx
|
|
10
10
|
/**
|
package/dist/shims/dynamic.js
CHANGED
|
@@ -89,9 +89,11 @@ function createElementWithProps(Component, props) {
|
|
|
89
89
|
}
|
|
90
90
|
/**
|
|
91
91
|
* Lightweight error boundary that renders the loading component with the error
|
|
92
|
-
* when a dynamic() loader rejects
|
|
93
|
-
*
|
|
94
|
-
*
|
|
92
|
+
* when a dynamic() loader rejects, as the Pages Router's react-loadable does by
|
|
93
|
+
* passing `error` to `loading`. App Router trees never get it: Next.js's App
|
|
94
|
+
* Router next/dynamic is React.lazy inside Suspense with no boundary of its own,
|
|
95
|
+
* so loader and render errors reach the nearest error.tsx.
|
|
96
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/lazy-dynamic/loadable.tsx
|
|
95
97
|
*
|
|
96
98
|
* Lazily created because React.Component is not available in the RSC environment
|
|
97
99
|
* (server components use a slimmed-down React that doesn't include class components).
|
|
@@ -202,6 +204,7 @@ function dynamic(dynamicInput, options) {
|
|
|
202
204
|
}
|
|
203
205
|
const InitialLazyComponent = createLazyComponent(loader);
|
|
204
206
|
const ClientSSRFalse = (props) => {
|
|
207
|
+
const isAppRouterTree = useIsAppRouterTree();
|
|
205
208
|
const [mounted, setMounted] = React.useState(false);
|
|
206
209
|
const { LazyComponent, retry, retryKey } = useRetryableLazyComponent(loader, InitialLazyComponent);
|
|
207
210
|
React.useEffect(() => setMounted(true), []);
|
|
@@ -209,7 +212,7 @@ function dynamic(dynamicInput, options) {
|
|
|
209
212
|
const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps({ retry })) : null;
|
|
210
213
|
const lazyElement = createElementWithProps(LazyComponent, props);
|
|
211
214
|
let content = lazyElement;
|
|
212
|
-
if (LoadingComponent) {
|
|
215
|
+
if (LoadingComponent && !isAppRouterTree) {
|
|
213
216
|
const ErrorBoundary = getDynamicErrorBoundary();
|
|
214
217
|
if (ErrorBoundary) content = React.createElement(ErrorBoundary, {
|
|
215
218
|
fallback: LoadingComponent,
|
|
@@ -237,7 +240,7 @@ function dynamic(dynamicInput, options) {
|
|
|
237
240
|
const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps()) : null;
|
|
238
241
|
const lazyElement = createElementWithProps(LazyServer, props);
|
|
239
242
|
let content = lazyElement;
|
|
240
|
-
if (LoadingComponent) {
|
|
243
|
+
if (LoadingComponent && !isAppRouterTree) {
|
|
241
244
|
const ErrorBoundary = getDynamicErrorBoundary();
|
|
242
245
|
if (ErrorBoundary) content = React.createElement(ErrorBoundary, {
|
|
243
246
|
fallback: LoadingComponent,
|
|
@@ -257,7 +260,7 @@ function dynamic(dynamicInput, options) {
|
|
|
257
260
|
const fallback = LoadingComponent ? React.createElement(LoadingComponent, createDynamicLoadingProps({ retry })) : null;
|
|
258
261
|
const lazyElement = createElementWithProps(LazyComponent, props);
|
|
259
262
|
let content = lazyElement;
|
|
260
|
-
if (LoadingComponent) {
|
|
263
|
+
if (LoadingComponent && !isAppRouterTree) {
|
|
261
264
|
const ErrorBoundary = getDynamicErrorBoundary();
|
|
262
265
|
if (ErrorBoundary) content = React.createElement(ErrorBoundary, {
|
|
263
266
|
fallback: LoadingComponent,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
3
|
+
import { handleAppNavigationFailure } from "../client/app-nav-failure-handler.js";
|
|
4
|
+
import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
|
|
3
5
|
import { decodeRedirectError, forbidden, isRedirectError, notFound, unauthorized } from "./navigation-errors.js";
|
|
4
6
|
import "./navigation-server.js";
|
|
5
7
|
import { isRedirectToCurrentUrl, useErrorBoundaryPathname, useErrorBoundaryRouter } from "./error-boundary-navigation.js";
|
|
6
8
|
import DefaultGlobalError from "./default-global-error.js";
|
|
7
|
-
import { handleAppNavigationFailure } from "../client/app-nav-failure-handler.js";
|
|
8
|
-
import { VINEXT_DEV_ERROR_RECOVERY_EVENT } from "../utils/dev-error-recovery-event.js";
|
|
9
9
|
import { consumeCaughtNotFoundBoundary, useCaughtNotFoundBoundary } from "./caught-not-found-boundaries.js";
|
|
10
10
|
import React from "react";
|
|
11
11
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -11,12 +11,16 @@ export type FetchDedupeEntry = {
|
|
|
11
11
|
response: Response | null;
|
|
12
12
|
};
|
|
13
13
|
export type FetchCacheState = {
|
|
14
|
-
cacheableFetchUrls: Set<string>;
|
|
15
14
|
currentRequestTags: string[];
|
|
16
15
|
currentFetchSoftTags: string[];
|
|
17
16
|
currentFetchCacheMode: FetchCacheMode | null;
|
|
18
17
|
currentFetchRevalidate: number | null;
|
|
19
18
|
currentForceDynamicFetchDefault: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Pages Router preview/draft render. App Router draft state is read from the
|
|
21
|
+
* headers context instead; Pages renders don't have one.
|
|
22
|
+
*/
|
|
23
|
+
isDraftMode: boolean;
|
|
20
24
|
dynamicFetchUrls: Set<string>;
|
|
21
25
|
refreshStaleFetchesInForeground: boolean;
|
|
22
26
|
isFetchDedupeActive: boolean;
|
|
@@ -11,12 +11,12 @@ const _FALLBACK_KEY = Symbol.for("vinext.fetchCache.fallback");
|
|
|
11
11
|
const fetchCacheAls = getOrCreateAls("vinext.fetchCache.als");
|
|
12
12
|
function createFetchCacheState() {
|
|
13
13
|
return {
|
|
14
|
-
cacheableFetchUrls: /* @__PURE__ */ new Set(),
|
|
15
14
|
currentRequestTags: [],
|
|
16
15
|
currentFetchSoftTags: [],
|
|
17
16
|
currentFetchCacheMode: null,
|
|
18
17
|
currentFetchRevalidate: null,
|
|
19
18
|
currentForceDynamicFetchDefault: false,
|
|
19
|
+
isDraftMode: false,
|
|
20
20
|
dynamicFetchUrls: /* @__PURE__ */ new Set(),
|
|
21
21
|
refreshStaleFetchesInForeground: false,
|
|
22
22
|
isFetchDedupeActive: false,
|
|
@@ -77,13 +77,11 @@ function getCurrentFetchSoftTags() {
|
|
|
77
77
|
*/
|
|
78
78
|
function runWithDetachedFetchObservations(fn) {
|
|
79
79
|
if (isInsideUnifiedScope()) return runWithUnifiedStateMutation((uCtx) => {
|
|
80
|
-
uCtx.cacheableFetchUrls = /* @__PURE__ */ new Set();
|
|
81
80
|
uCtx.currentRequestTags = [];
|
|
82
81
|
uCtx.dynamicFetchUrls = /* @__PURE__ */ new Set();
|
|
83
82
|
}, fn);
|
|
84
83
|
return fetchCacheAls.run({
|
|
85
84
|
...getFetchCacheState(),
|
|
86
|
-
cacheableFetchUrls: /* @__PURE__ */ new Set(),
|
|
87
85
|
currentRequestTags: [],
|
|
88
86
|
dynamicFetchUrls: /* @__PURE__ */ new Set()
|
|
89
87
|
}, fn);
|
|
@@ -11,7 +11,6 @@ declare global {
|
|
|
11
11
|
}
|
|
12
12
|
/** @internal Reset dedup state — exposed for test isolation only. */
|
|
13
13
|
export declare function _resetPendingRefetches(): void;
|
|
14
|
-
export declare function peekCacheableFetchObservations(): string[];
|
|
15
14
|
export declare function peekDynamicFetchObservations(): string[];
|
|
16
15
|
export declare function consumeDynamicFetchObservations(): string[];
|
|
17
16
|
/**
|
|
@@ -31,6 +30,8 @@ export declare function setCurrentFetchSoftTags(tags: string[]): void;
|
|
|
31
30
|
export declare function setCurrentFetchCacheMode(mode: FetchCacheMode | null): void;
|
|
32
31
|
export declare function setCurrentFetchRevalidate(revalidate: number | null): void;
|
|
33
32
|
export declare function setCurrentForceDynamicFetchDefault(enabled: boolean): void;
|
|
33
|
+
/** Mark the current Pages Router render as a preview/draft render. */
|
|
34
|
+
export declare function setCurrentFetchDraftMode(enabled: boolean): void;
|
|
34
35
|
export declare function setRefreshStaleFetchesInForeground(enabled: boolean): void;
|
|
35
36
|
/**
|
|
36
37
|
* Install the patched fetch and reset per-request tag state.
|
|
@@ -6,8 +6,8 @@ import { sha256Hex } from "../utils/hash.js";
|
|
|
6
6
|
import { traceAppFetch } from "../server/app-fetch-tracing.js";
|
|
7
7
|
import { addCollectedRequestTags, fallbackFetchCacheState, fetchCacheAls, getCurrentFetchSoftTags, getFetchCacheState, resetFallbackFetchCacheState, runWithDetachedFetchObservations } from "./fetch-cache-state.js";
|
|
8
8
|
import { isInsideAnyCacheScope, markDynamicUsage } from "./internal/headers-state.js";
|
|
9
|
-
import { getHeadersContext } from "./headers.js";
|
|
10
|
-
import { _hasPendingRevalidatedTag, _setRequestScopedCacheLife } from "./cache-request-state.js";
|
|
9
|
+
import { getHeadersContext, isDraftModeEnabled } from "./headers.js";
|
|
10
|
+
import { _hasPendingRevalidatedTag, _isOnDemandRevalidate, _setRequestScopedCacheLife } from "./cache-request-state.js";
|
|
11
11
|
import { Buffer } from "node:buffer";
|
|
12
12
|
//#region src/shims/fetch-cache.ts
|
|
13
13
|
/**
|
|
@@ -463,9 +463,6 @@ function markUncachedFetchForPageOutput(input) {
|
|
|
463
463
|
if (getHeadersContext()?.forceStatic !== true) getFetchCacheState().currentFetchRevalidate = 0;
|
|
464
464
|
markDynamicUsage();
|
|
465
465
|
}
|
|
466
|
-
function recordCacheableFetchObservation(input) {
|
|
467
|
-
getFetchCacheState().cacheableFetchUrls.add(getFetchObservationUrl(input));
|
|
468
|
-
}
|
|
469
466
|
function recordFiniteFetchRevalidate(revalidateSeconds) {
|
|
470
467
|
if (Number.isFinite(revalidateSeconds) && revalidateSeconds > 0) _setRequestScopedCacheLife({ revalidate: revalidateSeconds });
|
|
471
468
|
}
|
|
@@ -503,7 +500,8 @@ async function writeFetchCacheResponse(handler, cacheKey, response, tags, revali
|
|
|
503
500
|
await handler.set(cacheKey, cacheValue, {
|
|
504
501
|
fetchCache: true,
|
|
505
502
|
tags,
|
|
506
|
-
revalidate: revalidateSeconds
|
|
503
|
+
revalidate: revalidateSeconds,
|
|
504
|
+
...options?.staleEntry ? { staleEntry: options.staleEntry } : {}
|
|
507
505
|
});
|
|
508
506
|
}
|
|
509
507
|
async function lowerFetchCacheRevalidateIfNeeded(handler, cacheKey, cachedValue, tags, revalidateSeconds) {
|
|
@@ -520,9 +518,6 @@ async function lowerFetchCacheRevalidateIfNeeded(handler, cacheKey, cachedValue,
|
|
|
520
518
|
revalidate: revalidateSeconds
|
|
521
519
|
});
|
|
522
520
|
}
|
|
523
|
-
function peekCacheableFetchObservations() {
|
|
524
|
-
return [...getFetchCacheState().cacheableFetchUrls].sort();
|
|
525
|
-
}
|
|
526
521
|
function peekDynamicFetchObservations() {
|
|
527
522
|
return [...getFetchCacheState().dynamicFetchUrls].sort();
|
|
528
523
|
}
|
|
@@ -559,6 +554,10 @@ function setCurrentFetchRevalidate(revalidate) {
|
|
|
559
554
|
function setCurrentForceDynamicFetchDefault(enabled) {
|
|
560
555
|
getFetchCacheState().currentForceDynamicFetchDefault = enabled;
|
|
561
556
|
}
|
|
557
|
+
/** Mark the current Pages Router render as a preview/draft render. */
|
|
558
|
+
function setCurrentFetchDraftMode(enabled) {
|
|
559
|
+
getFetchCacheState().isDraftMode = enabled;
|
|
560
|
+
}
|
|
562
561
|
function setRefreshStaleFetchesInForeground(enabled) {
|
|
563
562
|
getFetchCacheState().refreshStaleFetchesInForeground = enabled;
|
|
564
563
|
}
|
|
@@ -705,8 +704,12 @@ function dedupeFetch(input, init) {
|
|
|
705
704
|
*/
|
|
706
705
|
function createPatchedFetch() {
|
|
707
706
|
const patchedFetch = async function patchedFetch(input, init, span) {
|
|
708
|
-
const nextOpts = init?.next;
|
|
709
707
|
const state = getFetchCacheState();
|
|
708
|
+
if (state.isDraftMode || isDraftModeEnabled()) {
|
|
709
|
+
recordDynamicFetchObservation(input);
|
|
710
|
+
return dedupeFetch(input, init);
|
|
711
|
+
}
|
|
712
|
+
const nextOpts = init?.next;
|
|
710
713
|
const fetchIdx = isInsideUnifiedScope() || fetchCacheAls.getStore() !== void 0 || fallbackFetchCacheState.isFetchDedupeActive ? (state.nextFetchId ?? 1) + 1 : void 0;
|
|
711
714
|
if (fetchIdx !== void 0) state.nextFetchId = fetchIdx;
|
|
712
715
|
const recordFetchOutcome = (response, cacheStatus, cacheReason) => {
|
|
@@ -753,7 +756,6 @@ function createPatchedFetch() {
|
|
|
753
756
|
return recordFetchOutcome(await dedupeFetch(input, cleanInit), "skip", "auto no cache");
|
|
754
757
|
}
|
|
755
758
|
const cacheReason = fetchCacheMode === "force-cache" || fetchCacheMode === "default-cache" ? `fetchCache = ${fetchCacheMode}` : `revalidate: ${nextOpts?.revalidate === false || cacheDirective === "force-cache" ? 4294967294 : revalidateSeconds}`;
|
|
756
|
-
recordCacheableFetchObservation(input);
|
|
757
759
|
if (typeof nextOpts?.revalidate === "number" && nextOpts.revalidate > 0) {
|
|
758
760
|
lowerCurrentFetchRevalidate(nextOpts.revalidate);
|
|
759
761
|
recordFiniteFetchRevalidate(nextOpts.revalidate);
|
|
@@ -785,8 +787,9 @@ function createPatchedFetch() {
|
|
|
785
787
|
}
|
|
786
788
|
const handler = getDataCacheHandler();
|
|
787
789
|
let mustBypassPendingRevalidation = _hasPendingRevalidatedTag([...tags, ...softTags]);
|
|
790
|
+
let staleEntry;
|
|
788
791
|
try {
|
|
789
|
-
let cached = mustBypassPendingRevalidation ? null : await handler.get(cacheKey, {
|
|
792
|
+
let cached = mustBypassPendingRevalidation || _isOnDemandRevalidate() ? null : await handler.get(cacheKey, {
|
|
790
793
|
kind: "FETCH",
|
|
791
794
|
tags,
|
|
792
795
|
softTags,
|
|
@@ -806,15 +809,19 @@ function createPatchedFetch() {
|
|
|
806
809
|
return recordFetchOutcome(buildCachedFetchResponse(cachedData, input), "hit", cacheReason);
|
|
807
810
|
}
|
|
808
811
|
if (cached?.value && cached.value.kind === "FETCH" && cached.cacheState === "stale") {
|
|
812
|
+
staleEntry = cached;
|
|
809
813
|
if (shouldRefreshStaleFetchInForeground()) {
|
|
810
814
|
const freshResponse = await dedupeFetch(input, fetchInit);
|
|
811
|
-
await writeFetchCacheResponse(handler, cacheKey, freshResponse, tags, revalidateSeconds);
|
|
815
|
+
await writeFetchCacheResponse(handler, cacheKey, freshResponse, tags, revalidateSeconds, { staleEntry: cached });
|
|
812
816
|
return recordFetchOutcome(freshResponse, "miss", cacheReason);
|
|
813
817
|
}
|
|
814
818
|
const staleData = cached.value.data;
|
|
815
819
|
if (!pendingRefetches.has(cacheKey)) {
|
|
816
820
|
const refetchPromise = originalFetch(input, fetchInit).then(async (freshResp) => {
|
|
817
|
-
await writeFetchCacheResponse(handler, cacheKey, freshResp, tags, revalidateSeconds, {
|
|
821
|
+
await writeFetchCacheResponse(handler, cacheKey, freshResp, tags, revalidateSeconds, {
|
|
822
|
+
cloneForReturn: false,
|
|
823
|
+
staleEntry: cached
|
|
824
|
+
});
|
|
818
825
|
}).catch((err) => {
|
|
819
826
|
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
820
827
|
console.error(`[vinext] fetch cache background revalidation failed for ${url} (key=${cacheKey.slice(0, 12)}...):`, err);
|
|
@@ -835,13 +842,17 @@ function createPatchedFetch() {
|
|
|
835
842
|
}
|
|
836
843
|
const response = await (mustBypassPendingRevalidation ? originalFetch(input, fetchInit) : dedupeFetch(input, fetchInit));
|
|
837
844
|
const cacheValue = await buildFetchCacheValue(response, tags, revalidateSeconds);
|
|
838
|
-
if (cacheValue)
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
+
if (cacheValue) {
|
|
846
|
+
const write = handler.set(cacheKey, cacheValue, {
|
|
847
|
+
fetchCache: true,
|
|
848
|
+
tags,
|
|
849
|
+
revalidate: revalidateSeconds,
|
|
850
|
+
...staleEntry ? { staleEntry } : {}
|
|
851
|
+
}).catch((err) => {
|
|
852
|
+
console.error("[vinext] fetch cache write error:", err);
|
|
853
|
+
});
|
|
854
|
+
getRequestExecutionContext()?.waitUntil(write);
|
|
855
|
+
}
|
|
845
856
|
return recordFetchOutcome(response, "miss", cacheReason);
|
|
846
857
|
};
|
|
847
858
|
return ((input, init) => {
|
|
@@ -894,7 +905,6 @@ function withFetchCache() {
|
|
|
894
905
|
async function runWithFetchCache(fn) {
|
|
895
906
|
_ensurePatchInstalled();
|
|
896
907
|
if (isInsideUnifiedScope()) return await runWithUnifiedStateMutation((uCtx) => {
|
|
897
|
-
uCtx.cacheableFetchUrls = /* @__PURE__ */ new Set();
|
|
898
908
|
uCtx.currentRequestTags = [];
|
|
899
909
|
uCtx.currentFetchSoftTags = [];
|
|
900
910
|
uCtx.dynamicFetchUrls = /* @__PURE__ */ new Set();
|
|
@@ -904,12 +914,12 @@ async function runWithFetchCache(fn) {
|
|
|
904
914
|
uCtx.nextFetchId = 1;
|
|
905
915
|
}, fn);
|
|
906
916
|
return fetchCacheAls.run({
|
|
907
|
-
cacheableFetchUrls: /* @__PURE__ */ new Set(),
|
|
908
917
|
currentRequestTags: [],
|
|
909
918
|
currentFetchSoftTags: [],
|
|
910
919
|
currentFetchCacheMode: null,
|
|
911
920
|
currentFetchRevalidate: null,
|
|
912
921
|
currentForceDynamicFetchDefault: false,
|
|
922
|
+
isDraftMode: false,
|
|
913
923
|
dynamicFetchUrls: /* @__PURE__ */ new Set(),
|
|
914
924
|
refreshStaleFetchesInForeground: false,
|
|
915
925
|
isFetchDedupeActive: true,
|
|
@@ -950,4 +960,4 @@ function getOriginalFetch() {
|
|
|
950
960
|
return originalFetch;
|
|
951
961
|
}
|
|
952
962
|
//#endregion
|
|
953
|
-
export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch,
|
|
963
|
+
export { _resetPendingRefetches, addCollectedRequestTags, consumeDynamicFetchObservations, ensureFetchPatch, getCollectedFetchTags, getCurrentFetchSoftTags, getOriginalFetch, peekDynamicFetchObservations, runWithDetachedFetchObservations, runWithFetchCache, runWithFetchDedupe, setCurrentFetchCacheMode, setCurrentFetchDraftMode, setCurrentFetchRevalidate, setCurrentFetchSoftTags, setCurrentForceDynamicFetchDefault, setRefreshStaleFetchesInForeground, withFetchCache };
|
package/dist/shims/form.js
CHANGED
|
@@ -5,10 +5,10 @@ import "../server/headers.js";
|
|
|
5
5
|
import { assertSafeNavigationUrl } from "./url-safety.js";
|
|
6
6
|
import { APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL } from "../server/app-rsc-render-mode.js";
|
|
7
7
|
import { withBasePath } from "./url-utils.js";
|
|
8
|
-
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
9
|
-
import "../server/app-elements.js";
|
|
10
8
|
import { createRscRequestHeaders, createRscRequestUrl } from "../server/app-rsc-cache-busting.js";
|
|
11
9
|
import { hasAppNavigationRuntime, loadNavigationRuntimeRouteManifest } from "../client/navigation-runtime.js";
|
|
10
|
+
import { AppElementsWire } from "../server/app-elements-wire.js";
|
|
11
|
+
import "../server/app-elements.js";
|
|
12
12
|
import { getMountedSlotsHeader, getPrefetchInterceptionContext, getPrefetchedUrls, hasPrefetchCacheEntryForNavigation, navigateClientSide, prefetchRscResponse } from "./navigation.js";
|
|
13
13
|
import { useMergedRef } from "./use-merged-ref.js";
|
|
14
14
|
import { forwardRef, useActionState, useCallback, useEffect, useRef } from "react";
|