vinext 1.0.0 → 1.0.1
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/THIRD_PARTY_LICENSES.md +26 -0
- package/dist/build/lifecycle.js +10 -10
- package/dist/build/pages-client-assets-module.js +6 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.js +3 -7
- package/dist/build/prerender.d.ts +8 -1
- package/dist/build/prerender.js +134 -38
- package/dist/build/run-prerender.js +4 -3
- package/dist/build/server-entry.d.ts +2 -0
- package/dist/build/server-entry.js +7 -1
- package/dist/client/browser-globals.d.ts +4 -0
- package/dist/client/browser-globals.js +5 -0
- package/dist/client/navigation-runtime.d.ts +0 -1
- package/dist/client/navigation-runtime.js +2 -2
- package/dist/config/dotenv.js +14 -3
- package/dist/entries/app-rsc-entry.js +3 -2
- package/dist/index.js +142 -71
- package/dist/init-cloudflare.d.ts +1 -1
- package/dist/init-cloudflare.js +6 -6
- package/dist/init-platform.js +1 -1
- package/dist/init.js +4 -2
- package/dist/plugins/commonjs-syntax.d.ts +16 -0
- package/dist/plugins/commonjs-syntax.js +22 -0
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +54 -3
- package/dist/plugins/import-meta-url.js +6 -6
- package/dist/plugins/og-asset-ownership.d.ts +2 -0
- package/dist/plugins/og-asset-ownership.js +24 -13
- package/dist/plugins/og-assets.d.ts +18 -0
- package/dist/plugins/og-assets.js +50 -8
- package/dist/plugins/og-harfbuzz.js +38 -27
- package/dist/plugins/optimize-imports.js +2 -1
- package/dist/plugins/require-context.d.ts +1 -0
- package/dist/plugins/require-context.js +28 -1
- package/dist/plugins/scan-build-css.d.ts +12 -0
- package/dist/plugins/scan-build-css.js +39 -0
- package/dist/plugins/strip-server-exports.d.ts +2 -0
- package/dist/plugins/strip-server-exports.js +3 -1
- package/dist/plugins/transform-result.d.ts +18 -0
- package/dist/plugins/transform-result.js +23 -2
- package/dist/plugins/typeof-window.d.ts +10 -0
- package/dist/plugins/typeof-window.js +33 -9
- package/dist/routing/app-route-graph.d.ts +0 -1
- package/dist/routing/app-route-graph.js +2 -4
- package/dist/routing/app-route-ids.d.ts +3 -0
- package/dist/routing/app-route-ids.js +6 -0
- package/dist/server/app-bfcache-id.d.ts +1 -0
- package/dist/server/app-bfcache-id.js +7 -1
- package/dist/server/app-bfcache-identity.js +1 -2
- package/dist/server/app-browser-entry.js +4 -2
- package/dist/server/app-browser-hydration.d.ts +1 -1
- package/dist/server/app-browser-hydration.js +2 -2
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +1 -1
- package/dist/server/app-history-state.d.ts +0 -1
- package/dist/server/app-history-state.js +2 -5
- package/dist/server/app-page-cache-render.js +2 -1
- package/dist/server/app-page-render.js +2 -1
- package/dist/server/app-page-search-params-observation.js +1 -1
- package/dist/server/app-page-stream.js +1 -1
- package/dist/server/app-page-tracing.js +2 -1
- package/dist/server/app-pages-bridge.js +3 -2
- package/dist/server/app-render-abort-error.d.ts +3 -0
- package/dist/server/app-render-abort-error.js +8 -0
- package/dist/server/app-request-stage-independent-entry.js +4 -7
- package/dist/server/app-route-handler-cache.d.ts +2 -1
- package/dist/server/app-route-handler-cache.js +11 -7
- package/dist/server/app-route-handler-dispatch.js +10 -3
- package/dist/server/app-route-handler-execution.d.ts +9 -1
- package/dist/server/app-route-handler-execution.js +28 -13
- package/dist/server/app-route-handler-policy.js +2 -2
- package/dist/server/app-route-handler-response.d.ts +1 -1
- package/dist/server/app-route-handler-response.js +14 -5
- package/dist/server/app-router-entry.d.ts +2 -1
- package/dist/server/app-router-entry.js +5 -9
- package/dist/server/app-rsc-errors.d.ts +0 -1
- package/dist/server/app-rsc-errors.js +2 -6
- package/dist/server/app-rsc-handler.d.ts +1 -0
- package/dist/server/app-rsc-handler.js +18 -7
- package/dist/server/app-rsc-request-normalization.d.ts +1 -1
- package/dist/server/app-rsc-request-normalization.js +3 -2
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-route-matching.js +1 -1
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-ssr-entry.js +3 -3
- package/dist/server/app-ssr-search-params-gate.js +1 -1
- package/dist/server/app-ssr-stream.js +1 -1
- package/dist/server/cache-control.js +3 -11
- package/dist/server/cacheability-request.js +49 -49
- package/dist/server/config-headers.js +1 -1
- package/dist/server/dev-server.js +11 -3
- package/dist/server/headers.d.ts +2 -0
- package/dist/server/headers.js +5 -1
- package/dist/server/http-error-responses.js +1 -0
- package/dist/server/isr-cache.d.ts +2 -0
- package/dist/server/isr-cache.js +6 -1
- package/dist/server/metadata-route-response.js +94 -37
- package/dist/server/pages-api-route.js +8 -2
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +73 -22
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-page-data.d.ts +6 -1
- package/dist/server/pages-page-data.js +71 -65
- package/dist/server/pages-page-handler.js +29 -11
- package/dist/server/pages-page-response.js +3 -1
- package/dist/server/pages-request-pipeline.d.ts +2 -1
- package/dist/server/pages-request-pipeline.js +20 -5
- package/dist/server/pages-request-stage-entry.js +6 -4
- package/dist/server/prerender-manifest.d.ts +6 -0
- package/dist/server/prerender-manifest.js +1 -1
- package/dist/server/prod-server.js +3 -13
- package/dist/server/response-stage-cacheability.js +1 -1
- package/dist/server/worker-revalidation-context.d.ts +2 -1
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/workers-tracing.d.ts +17 -0
- package/dist/server/workers-tracing.js +48 -8
- package/dist/shims/cache-request-state.d.ts +3 -14
- package/dist/shims/cache-request-state.js +2 -13
- package/dist/shims/cache-runtime.js +4 -2
- package/dist/shims/cache.d.ts +2 -1
- package/dist/shims/cache.js +4 -2
- package/dist/shims/cacheability-classification.d.ts +1 -1
- package/dist/shims/cacheability-classification.js +2 -2
- package/dist/shims/cdn-cache.d.ts +10 -1
- package/dist/shims/cdn-cache.js +16 -9
- package/dist/shims/error.d.ts +4 -18
- package/dist/shims/error.js +17 -10
- package/dist/shims/error.react-server.d.ts +4 -6
- package/dist/shims/error.react-server.js +4 -1
- package/dist/shims/fetch-cache.js +4 -3
- package/dist/shims/headers.d.ts +6 -69
- package/dist/shims/headers.js +37 -181
- package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
- package/dist/shims/internal/cache-context-accessor.js +15 -0
- package/dist/shims/internal/headers-state.d.ts +74 -0
- package/dist/shims/internal/headers-state.js +157 -0
- package/dist/shims/navigation.js +2 -2
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/root-params.js +1 -1
- package/dist/shims/server.js +52 -2
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/utils/encode-cache-tag.d.ts +1 -0
- package/dist/utils/encode-cache-tag.js +11 -1
- package/dist/utils/vite-cli-invocation.js +8 -1
- package/package.json +6 -2
- package/dist/server/metadata-route-cache-policy.d.ts +0 -5
- package/dist/server/metadata-route-cache-policy.js +0 -6
|
@@ -348,13 +348,17 @@ async function captureCacheabilityAdmissionBody(body, deadlineAt, limit = CACHEA
|
|
|
348
348
|
throw error;
|
|
349
349
|
}
|
|
350
350
|
}
|
|
351
|
-
function responseWithCachePolicy(response, body, outcome) {
|
|
351
|
+
function responseWithCachePolicy(response, body, outcome, browserCacheControl) {
|
|
352
352
|
const headers = new Headers(response.headers);
|
|
353
353
|
if (typeof body === "string") headers.delete("Content-Length");
|
|
354
354
|
applyCdnResponseHeaders(headers, outcome?.cacheable === true && outcome.cacheControl ? {
|
|
355
355
|
cacheControl: outcome.cacheControl,
|
|
356
|
-
tags: outcome.tags
|
|
357
|
-
|
|
356
|
+
tags: outcome.tags,
|
|
357
|
+
browserCacheControl
|
|
358
|
+
} : {
|
|
359
|
+
cacheControl: NO_STORE_CACHE_CONTROL,
|
|
360
|
+
browserCacheControl
|
|
361
|
+
});
|
|
358
362
|
return new Response(body, {
|
|
359
363
|
headers,
|
|
360
364
|
status: response.status,
|
|
@@ -367,21 +371,15 @@ async function stripSharedHtmlClientTraceMetadata(body, marker) {
|
|
|
367
371
|
const { stripClientTraceMetadataBlock } = await import("./client-trace-metadata.js");
|
|
368
372
|
return stripClientTraceMetadataBlock(html, marker);
|
|
369
373
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
const
|
|
373
|
-
if (
|
|
374
|
-
|
|
375
|
-
return
|
|
376
|
-
cacheable: true,
|
|
377
|
-
cacheControl,
|
|
378
|
-
...state.cdnCacheTags ? { tags: state.cdnCacheTags } : {}
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
function inferPagesPageCacheability(response, state) {
|
|
374
|
+
/** Only an explicitly authored provider policy may override framework storage. */
|
|
375
|
+
function explicitProviderOutcome(response, state) {
|
|
376
|
+
const name = readCdnResponsePolicyHeaderName(response.headers);
|
|
377
|
+
if (!name || name === "cache-control") return null;
|
|
378
|
+
const value = response.headers.get(name);
|
|
379
|
+
if (!(state.explicitResponseCachePolicy || state.configCdnCachePolicy?.get(name) === value || state.frameworkResponseCachePolicy && state.frameworkResponseCachePolicy.get(name) !== value) || !value) return null;
|
|
382
380
|
const cacheControl = readCdnResponseCacheControl(response.headers);
|
|
383
|
-
if (!cacheControl
|
|
384
|
-
return {
|
|
381
|
+
if (!cacheControl) return null;
|
|
382
|
+
return isNonCacheableCacheControl(cacheControl) ? { cacheable: false } : {
|
|
385
383
|
cacheable: true,
|
|
386
384
|
cacheControl,
|
|
387
385
|
...state.cdnCacheTags ? { tags: state.cdnCacheTags } : {}
|
|
@@ -397,18 +395,17 @@ function completedRouteOutcome(response, state, rendererOutcome = state.outcome
|
|
|
397
395
|
cacheable: false,
|
|
398
396
|
reason: varyRejectionReason
|
|
399
397
|
};
|
|
400
|
-
if (
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
return responseOutcome.cacheable ? responseOutcome : rendererOutcome ?? responseOutcome;
|
|
398
|
+
if (response.headers.has("set-cookie")) return {
|
|
399
|
+
cacheable: false,
|
|
400
|
+
reason: "response sets a cookie"
|
|
401
|
+
};
|
|
402
|
+
if (rendererOutcome?.dynamicUsage) return rendererOutcome;
|
|
403
|
+
const outcome = explicitProviderOutcome(response, state) ?? rendererOutcome;
|
|
404
|
+
const tags = outcome?.tags ?? rendererOutcome?.tags ?? state.cdnCacheTags;
|
|
405
|
+
return outcome && tags && outcome.tags !== tags ? {
|
|
406
|
+
...outcome,
|
|
407
|
+
tags
|
|
408
|
+
} : outcome;
|
|
412
409
|
}
|
|
413
410
|
function staticToDynamicResponse(route) {
|
|
414
411
|
const headers = new Headers({ "Content-Type": "text/plain; charset=utf-8" });
|
|
@@ -427,30 +424,32 @@ function cacheabilityEvaluationFailureResponse(pattern) {
|
|
|
427
424
|
});
|
|
428
425
|
}
|
|
429
426
|
function hasStrictFinalResponseVeto(response, state) {
|
|
430
|
-
|
|
431
|
-
|
|
427
|
+
const providerHeaders = new Headers(response.headers);
|
|
428
|
+
providerHeaders.delete("Cache-Control");
|
|
429
|
+
return Boolean(state.finalResponseVetoReason || response.headers.has("set-cookie") || hasExplicitNonCacheableResponsePolicy(providerHeaders, state.frameworkResponseCachePolicy));
|
|
432
430
|
}
|
|
433
431
|
async function finalizeWorkerCacheabilityAdmission(response, state) {
|
|
434
432
|
if (state.preserveResponseCachePolicy) return response;
|
|
433
|
+
const browserCacheControl = state.explicitResponseCachePolicy || state.configCdnCachePolicy?.has("cache-control") || state.route?.kind === "pages-api" || state.route?.kind === "pages-page" && state.outcome?.cacheable !== true ? response.headers.get("Cache-Control") ?? void 0 : void 0;
|
|
435
434
|
const admission = state.admission;
|
|
436
435
|
if (state.route?.kind === "app-route" || state.route?.kind === "pages-api") {
|
|
437
436
|
let manifestRoute = null;
|
|
438
|
-
const responseOutcome =
|
|
437
|
+
const responseOutcome = completedRouteOutcome(response, state);
|
|
439
438
|
const representation = admission?.representation ? resolveCacheabilityRepresentation(admission.representation, state.route.kind) : null;
|
|
440
|
-
const hasExplicitRuntimePolicy =
|
|
441
|
-
if (!admission || admission.policy === "deny" || !representation || !admission.requestKey) return responseWithCachePolicy(response, response.body, null);
|
|
439
|
+
const hasExplicitRuntimePolicy = responseOutcome?.cacheable === true;
|
|
440
|
+
if (!admission || admission.policy === "deny" || !representation || !admission.requestKey) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
442
441
|
if (admission.policy === "manifest" && state.route.kind === "app-route") {
|
|
443
442
|
const manifest = admission.manifest;
|
|
444
443
|
manifestRoute = findCacheabilityManifestRoute(manifest, state.route.kind, state.route.pattern);
|
|
445
444
|
}
|
|
446
445
|
const isManifestAuthorized = manifestRoute !== null && admission.routePathname !== void 0 && cacheabilityManifestRouteState(manifestRoute, admission.routePathname, representation) !== null;
|
|
447
446
|
const canUseBoundedRuntimeAdmission = hasExplicitRuntimePolicy && (admission.policy === "runtime" || admission.policy === "manifest" && !isManifestAuthorized);
|
|
448
|
-
if (!isManifestAuthorized && !canUseBoundedRuntimeAdmission || response.status >= 500 || state.credentialedRequest || state.forcedDynamicReason || hasStrictFinalResponseVeto(response, state) || cacheabilityVaryRejectionReason(response.headers, state) !== null) return responseWithCachePolicy(response, response.body, null);
|
|
447
|
+
if (!isManifestAuthorized && !canUseBoundedRuntimeAdmission || response.status >= 500 || state.credentialedRequest || state.forcedDynamicReason || hasStrictFinalResponseVeto(response, state) || cacheabilityVaryRejectionReason(response.headers, state) !== null) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
449
448
|
const outcome = responseOutcome;
|
|
450
|
-
if (!outcome.cacheable || !outcome.cacheControl) return responseWithCachePolicy(response, response.body, null);
|
|
451
449
|
if (state.completedResponseBody) {
|
|
450
|
+
if (!outcome?.cacheable || !outcome.cacheControl) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
452
451
|
if (!state.applyCompletedResponsePolicy) return response;
|
|
453
|
-
return responseWithCachePolicy(response, response.body, outcome);
|
|
452
|
+
return responseWithCachePolicy(response, response.body, outcome, browserCacheControl);
|
|
454
453
|
}
|
|
455
454
|
let captured;
|
|
456
455
|
try {
|
|
@@ -458,35 +457,36 @@ async function finalizeWorkerCacheabilityAdmission(response, state) {
|
|
|
458
457
|
} catch {
|
|
459
458
|
return cacheabilityEvaluationFailureResponse(state.route.pattern);
|
|
460
459
|
}
|
|
461
|
-
if (captured.kind === "fallback") return responseWithCachePolicy(response, captured.body, null);
|
|
462
|
-
return responseWithCachePolicy(response, captured.body, outcome);
|
|
460
|
+
if (captured.kind === "fallback") return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
|
|
461
|
+
return responseWithCachePolicy(response, captured.body, outcome, browserCacheControl);
|
|
463
462
|
}
|
|
464
|
-
if (!admission || admission.policy === "deny" || !admission.representation || !admission.requestKey || !state.route || response.status >= 500) return responseWithCachePolicy(response, response.body, null);
|
|
463
|
+
if (!admission || admission.policy === "deny" || !admission.representation || !admission.requestKey || !state.route || response.status >= 500) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
465
464
|
const pageRoute = {
|
|
466
465
|
kind: state.route.kind,
|
|
467
466
|
pattern: state.route.pattern
|
|
468
467
|
};
|
|
469
468
|
const requestRepresentation = admission.representation;
|
|
470
469
|
const representation = resolveCacheabilityRepresentation(requestRepresentation, pageRoute.kind);
|
|
471
|
-
if (!cacheabilityRepresentationMatchesPageRoute(pageRoute.kind, representation)) return responseWithCachePolicy(response, response.body, null);
|
|
470
|
+
if (!cacheabilityRepresentationMatchesPageRoute(pageRoute.kind, representation)) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
472
471
|
let manifestRoute = null;
|
|
473
472
|
let manifestRouteState = null;
|
|
474
473
|
if (admission.policy === "manifest") {
|
|
475
474
|
const manifest = admission.manifest;
|
|
476
475
|
manifestRoute = findCacheabilityManifestRoute(manifest, pageRoute.kind, pageRoute.pattern);
|
|
477
476
|
manifestRouteState = admission.routePathname ? cacheabilityManifestPageState(manifest, pageRoute, requestRepresentation, admission.routePathname) : null;
|
|
478
|
-
if (!manifestRoute || !manifestRouteState) return responseWithCachePolicy(response, response.body, null);
|
|
477
|
+
if (!manifestRoute || !manifestRouteState) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
479
478
|
}
|
|
480
|
-
if (state.forcedDynamicReason) return responseWithCachePolicy(response, response.body, null);
|
|
481
|
-
if (hasStrictFinalResponseVeto(response, state)) return responseWithCachePolicy(response, response.body, null);
|
|
482
|
-
if (cacheabilityVaryRejectionReason(response.headers, state) !== null) return responseWithCachePolicy(response, response.body, null);
|
|
479
|
+
if (state.forcedDynamicReason) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
480
|
+
if (hasStrictFinalResponseVeto(response, state)) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
481
|
+
if (cacheabilityVaryRejectionReason(response.headers, state) !== null) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
482
|
+
if (state.route.kind === "pages-page" && !state.completion && completedRouteOutcome(response, state)?.cacheable !== true) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
483
483
|
let captured;
|
|
484
484
|
try {
|
|
485
485
|
captured = await captureCacheabilityAdmissionBody(response.body, state.captureDeadlineAt, CACHEABILITY_ADMISSION_RESPONSE_BODY_LIMIT, state.captureBudget ?? isolateCaptureBudget);
|
|
486
486
|
} catch {
|
|
487
487
|
return cacheabilityEvaluationFailureResponse(state.route.pattern);
|
|
488
488
|
}
|
|
489
|
-
if (captured.kind === "fallback") return responseWithCachePolicy(response, captured.body, null);
|
|
489
|
+
if (captured.kind === "fallback") return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
|
|
490
490
|
const rendererOutcome = state.completion ? await state.completion : state.outcome ?? null;
|
|
491
491
|
const outcome = completedRouteOutcome(response, state, rendererOutcome);
|
|
492
492
|
if (outcome?.cacheable !== true || !outcome.cacheControl) {
|
|
@@ -494,12 +494,12 @@ async function finalizeWorkerCacheabilityAdmission(response, state) {
|
|
|
494
494
|
await captured.body?.cancel().catch(() => {});
|
|
495
495
|
return staticToDynamicResponse(manifestRoute);
|
|
496
496
|
}
|
|
497
|
-
return responseWithCachePolicy(response, captured.body, null);
|
|
497
|
+
return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
|
|
498
498
|
}
|
|
499
499
|
const effectivePolicyHeader = readCdnResponsePolicyHeaderName(response.headers);
|
|
500
500
|
const replacesRendererPolicy = outcome !== rendererOutcome && effectivePolicyHeader !== null && state.configCdnCachePolicy?.get(effectivePolicyHeader) === response.headers.get(effectivePolicyHeader);
|
|
501
|
-
if (state.route.kind === "app-page" && !replacesRendererPolicy && rendererOutcome?.searchParamsUnread !== true) return responseWithCachePolicy(response, captured.body, null);
|
|
502
|
-
return responseWithCachePolicy(response, representation === "html" && state.clientTraceMetadataMarker ? await stripSharedHtmlClientTraceMetadata(captured.body, state.clientTraceMetadataMarker) : captured.body, outcome);
|
|
501
|
+
if (state.route.kind === "app-page" && !replacesRendererPolicy && rendererOutcome?.searchParamsUnread !== true) return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
|
|
502
|
+
return responseWithCachePolicy(response, representation === "html" && state.clientTraceMetadataMarker ? await stripSharedHtmlClientTraceMetadata(captured.body, state.clientTraceMetadataMarker) : captured.body, outcome, browserCacheControl);
|
|
503
503
|
}
|
|
504
504
|
async function finalizeWorkerCacheabilityResponse(response, ctx) {
|
|
505
505
|
const state = readState(ctx);
|
|
@@ -28,7 +28,7 @@ function markExplicitConfigResponseVeto(matched) {
|
|
|
28
28
|
continue;
|
|
29
29
|
}
|
|
30
30
|
if (isCdnResponsePolicyHeader(name)) markRouteCacheabilityConfigCdnCachePolicy(name, header.value);
|
|
31
|
-
if (isCdnResponsePolicyHeader(name) && isNonCacheableCdnResponsePolicy(name, header.value)) markRouteCacheabilityFinalResponseUncacheable(`next.config headers set a non-cacheable ${header.key} policy`);
|
|
31
|
+
if (name !== "cache-control" && isCdnResponsePolicyHeader(name) && isNonCacheableCdnResponsePolicy(name, header.value)) markRouteCacheabilityFinalResponseUncacheable(`next.config headers set a non-cacheable ${header.key} policy`);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
function retainLastSingularConfigValues(matched) {
|
|
@@ -504,13 +504,17 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
504
504
|
if (typeof pageModule.getStaticPaths === "function" && route.isDynamic) {
|
|
505
505
|
const pathsResult = await pageModule.getStaticPaths({
|
|
506
506
|
locales: i18nConfig?.locales ?? [],
|
|
507
|
-
defaultLocale:
|
|
507
|
+
defaultLocale: i18nConfig?.defaultLocale ?? ""
|
|
508
508
|
});
|
|
509
509
|
const fallback = pathsResult?.fallback ?? false;
|
|
510
510
|
const paths = pathsResult?.paths ?? [];
|
|
511
511
|
const routePattern = patternToNextFormat(route.pattern);
|
|
512
512
|
const routeParams = getPagesRouteParams(routePattern);
|
|
513
|
-
const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, params, routeParams,
|
|
513
|
+
const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, params, routeParams, localeStrippedUrl, {
|
|
514
|
+
locale,
|
|
515
|
+
locales: i18nConfig?.locales,
|
|
516
|
+
defaultLocale: i18nConfig?.defaultLocale
|
|
517
|
+
}));
|
|
514
518
|
if (fallback === false && !isValidPath && requestPreviewData === false) {
|
|
515
519
|
if (isDataReq) {
|
|
516
520
|
const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
|
|
@@ -745,6 +749,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
745
749
|
}
|
|
746
750
|
if ((statusCode ?? 200) === 200) dataHeaders["x-nextjs-matched-path"] = `${locale ? `/${locale}` : ""}${patternToNextFormat(route.pattern)}`;
|
|
747
751
|
if (gsspExtraHeaders) for (const [k, v] of Object.entries(gsspExtraHeaders)) dataHeaders[k] = v;
|
|
752
|
+
dataHeaders["Cache-Control"] = DEV_PAGES_CACHE_CONTROL;
|
|
748
753
|
applyDevPagesPreviewHeaders(dataHeaders, requestPreview);
|
|
749
754
|
const dataRoutePattern = patternToNextFormat(route.pattern);
|
|
750
755
|
if (dataRoutePattern !== "/_error" && dataRoutePattern !== "/500") {
|
|
@@ -836,7 +841,10 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
836
841
|
domainLocales,
|
|
837
842
|
...serializedPagesNextData
|
|
838
843
|
})}<\/script>`}\n ${createInlineScriptTag(`window.__VINEXT_PAGE_PATTERNS__=${safeJsonStringify(pagePatterns)}`, scriptNonce)}\n ${hydrationScript}`;
|
|
839
|
-
const extraHeaders = {
|
|
844
|
+
const extraHeaders = {
|
|
845
|
+
...gsspExtraHeaders,
|
|
846
|
+
"Cache-Control": DEV_PAGES_CACHE_CONTROL
|
|
847
|
+
};
|
|
840
848
|
if (typeof pageModule.getStaticProps === "function") {
|
|
841
849
|
extraHeaders["Cache-Control"] = DEV_PAGES_CACHE_CONTROL;
|
|
842
850
|
extraHeaders[NEXTJS_CACHE_HEADER] = isFallbackRender ? "MISS" : isOnDemandRevalidate ? "REVALIDATED" : "HIT";
|
package/dist/server/headers.d.ts
CHANGED
|
@@ -62,6 +62,8 @@ export declare const VINEXT_RSC_COMPLETION_METADATA_HEADER = "X-Vinext-Rsc-Compl
|
|
|
62
62
|
export declare const VINEXT_RENDERED_PATH_AND_SEARCH_HEADER = "X-Vinext-Rendered-Path-And-Search";
|
|
63
63
|
/** Prerender-only JSON side channel carrying request cacheLife metadata. */
|
|
64
64
|
export declare const VINEXT_PRERENDER_CACHE_LIFE_HEADER = "x-vinext-prerender-cache-life";
|
|
65
|
+
/** Prerender-only Pages marker: "0" confirms the page render used the requested URL. */
|
|
66
|
+
export declare const VINEXT_PRERENDER_REWRITTEN_HEADER = "x-vinext-prerender-rewritten";
|
|
65
67
|
/** Marks a local prerender-server 500 that originated from a thrown render error. */
|
|
66
68
|
export declare const VINEXT_PRERENDER_RENDER_ERROR_HEADER = "x-vinext-prerender-render-error";
|
|
67
69
|
/** Internal marker persisted only inside metadata-route APP_ROUTE cache values. */
|
package/dist/server/headers.js
CHANGED
|
@@ -62,6 +62,8 @@ const VINEXT_RSC_COMPLETION_METADATA_HEADER = "X-Vinext-Rsc-Completion-Metadata"
|
|
|
62
62
|
const VINEXT_RENDERED_PATH_AND_SEARCH_HEADER = "X-Vinext-Rendered-Path-And-Search";
|
|
63
63
|
/** Prerender-only JSON side channel carrying request cacheLife metadata. */
|
|
64
64
|
const VINEXT_PRERENDER_CACHE_LIFE_HEADER = "x-vinext-prerender-cache-life";
|
|
65
|
+
/** Prerender-only Pages marker: "0" confirms the page render used the requested URL. */
|
|
66
|
+
const VINEXT_PRERENDER_REWRITTEN_HEADER = "x-vinext-prerender-rewritten";
|
|
65
67
|
/** Marks a local prerender-server 500 that originated from a thrown render error. */
|
|
66
68
|
const VINEXT_PRERENDER_RENDER_ERROR_HEADER = "x-vinext-prerender-render-error";
|
|
67
69
|
/** Internal marker persisted only inside metadata-route APP_ROUTE cache values. */
|
|
@@ -161,9 +163,11 @@ const VINEXT_INTERNAL_HEADERS = [
|
|
|
161
163
|
VINEXT_CACHEABILITY_PROBE_HEADER.toLowerCase(),
|
|
162
164
|
VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER.toLowerCase(),
|
|
163
165
|
VINEXT_EXPECTED_WORKER_VERSION_HEADER.toLowerCase(),
|
|
166
|
+
VINEXT_MW_CTX_HEADER,
|
|
164
167
|
VINEXT_PRERENDER_ROUTE_PARAMS_HEADER,
|
|
165
168
|
VINEXT_PRERENDER_SPECULATIVE_HEADER,
|
|
166
169
|
VINEXT_PRERENDER_CACHE_LIFE_HEADER,
|
|
170
|
+
VINEXT_PRERENDER_REWRITTEN_HEADER,
|
|
167
171
|
VINEXT_REVALIDATE_HOST_HEADER,
|
|
168
172
|
VINEXT_REVALIDATED_CACHE_TAG_HEADER,
|
|
169
173
|
VINEXT_TRACE_ERROR_HEADER.toLowerCase(),
|
|
@@ -171,4 +175,4 @@ const VINEXT_INTERNAL_HEADERS = [
|
|
|
171
175
|
VINEXT_TRACE_ROUTE_HEADER.toLowerCase()
|
|
172
176
|
];
|
|
173
177
|
//#endregion
|
|
174
|
-
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_CACHE_TAGS_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STALE_TIME_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_EXPECTED_WORKER_VERSION_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERCEPTION_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_METADATA_ROUTE_CACHE_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_METADATA_ROUTES_PATH, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_READINESS_HEADER, VINEXT_PRERENDER_READINESS_PATH, VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_REVALIDATE_HOST_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_STATE_FINGERPRINT_HEADER, VINEXT_RSC_VARY_HEADER, VINEXT_STALE_TIME_PENDING_HEADER, VINEXT_TIMING_HEADER, VINEXT_TRACE_BUFFERED_BODY_HEADER, VINEXT_TRACE_ERROR_HEADER, VINEXT_TRACE_ROUTE_HEADER, isVinextRscVaryField };
|
|
178
|
+
export { ACTION_FORWARDED_HEADER, ACTION_REDIRECT_HEADER, ACTION_REDIRECT_STATUS_HEADER, ACTION_REDIRECT_TYPE_HEADER, ACTION_REVALIDATED_HEADER, FLIGHT_HEADERS, INTERNAL_HEADERS, MIDDLEWARE_HEADER_PREFIX, MIDDLEWARE_NEXT_HEADER, MIDDLEWARE_REWRITE_HEADER, MIDDLEWARE_SET_COOKIE_HEADER, MIDDLEWARE_SKIP_HEADER, NEXTJS_ACTION_NOT_FOUND_HEADER, NEXTJS_CACHE_HEADER, NEXTJS_DEPLOYMENT_ID_HEADER, NEXT_ACTION_HEADER, NEXT_CACHE_TAGS_HEADER, NEXT_HTML_REQUEST_ID_HEADER, NEXT_REQUEST_ID_HEADER, NEXT_ROUTER_PREFETCH_HEADER, NEXT_ROUTER_SEGMENT_PREFETCH_HEADER, NEXT_ROUTER_STALE_TIME_HEADER, NEXT_ROUTER_STATE_TREE_HEADER, NEXT_URL_HEADER, RSC_ACTION_HEADER, RSC_HEADER, VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_QUERY_PARAM, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_CACHE_HEADER, VINEXT_CLIENT_REUSE_MANIFEST_HEADER, VINEXT_DYNAMIC_STALE_TIME_HEADER, VINEXT_EXPECTED_WORKER_VERSION_HEADER, VINEXT_INTERCEPTION_CONTEXT_HEADER, VINEXT_INTERCEPTION_ID_HEADER, VINEXT_INTERNAL_HEADERS, VINEXT_METADATA_ROUTE_CACHE_HEADER, VINEXT_MOUNTED_SLOTS_HEADER, VINEXT_MW_CTX_HEADER, VINEXT_PARAMS_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_METADATA_ROUTES_PATH, VINEXT_PRERENDER_PAGES_STATIC_PATHS_PATH, VINEXT_PRERENDER_READINESS_HEADER, VINEXT_PRERENDER_READINESS_PATH, VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_REWRITTEN_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER, VINEXT_PRERENDER_STATIC_PARAMS_PATH, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_REVALIDATED_CACHE_TAG_HEADER, VINEXT_REVALIDATE_HEADER, VINEXT_REVALIDATE_HOST_HEADER, VINEXT_RSC_COMPLETION_METADATA_HEADER, VINEXT_RSC_MARKER_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER, VINEXT_RSC_RENDER_MODE_HEADER, VINEXT_RSC_STATE_FINGERPRINT_HEADER, VINEXT_RSC_VARY_HEADER, VINEXT_STALE_TIME_PENDING_HEADER, VINEXT_TIMING_HEADER, VINEXT_TRACE_BUFFERED_BODY_HEADER, VINEXT_TRACE_ERROR_HEADER, VINEXT_TRACE_ROUTE_HEADER, isVinextRscVaryField };
|
|
@@ -77,6 +77,7 @@ function notFoundStaticAssetResponse(headers) {
|
|
|
77
77
|
responseHeaders.delete("content-length");
|
|
78
78
|
responseHeaders.delete("transfer-encoding");
|
|
79
79
|
responseHeaders.set("Content-Type", "text/plain; charset=utf-8");
|
|
80
|
+
responseHeaders.set("Cache-Control", "private, no-cache, no-store, max-age=0, must-revalidate");
|
|
80
81
|
return new Response("Not Found", {
|
|
81
82
|
status: 404,
|
|
82
83
|
headers: responseHeaders
|
|
@@ -102,6 +102,8 @@ export declare function buildAppPageCacheValue(html: string, rscData?: ArrayBuff
|
|
|
102
102
|
* Long pathnames are hashed to stay within KV key-length limits (512 bytes).
|
|
103
103
|
*/
|
|
104
104
|
export declare function isrCacheKey(router: string, pathname: string, buildId?: string): string;
|
|
105
|
+
/** Build and request time share the same locale-stripped Pages pathname identity. */
|
|
106
|
+
export declare function pagesIsrCacheKey(pathname: string, buildId?: string, i18nCacheVariant?: string | null): string;
|
|
105
107
|
/**
|
|
106
108
|
* Compute an App Router ISR key for one cache artifact.
|
|
107
109
|
*
|
package/dist/server/isr-cache.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER } from "../utils/protocol-headers.js";
|
|
2
|
+
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
2
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
3
4
|
import { reportRequestError } from "./instrumentation.js";
|
|
4
5
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
@@ -164,6 +165,10 @@ function buildCacheKey(prefix, pathname, suffix) {
|
|
|
164
165
|
function isrCacheKey(router, pathname, buildId) {
|
|
165
166
|
return buildCacheKey(buildId ? `${router}:${buildId}` : router, pathname);
|
|
166
167
|
}
|
|
168
|
+
/** Build and request time share the same locale-stripped Pages pathname identity. */
|
|
169
|
+
function pagesIsrCacheKey(pathname, buildId, i18nCacheVariant) {
|
|
170
|
+
return isrCacheKey("pages:v2", normalizeCachePathname(normalizePathnameForRouteMatch(pathname)) + (i18nCacheVariant ? `::i18n=${encodeURIComponent(i18nCacheVariant)}` : ""), buildId);
|
|
171
|
+
}
|
|
167
172
|
/**
|
|
168
173
|
* Compute an App Router ISR key for one cache artifact.
|
|
169
174
|
*
|
|
@@ -206,4 +211,4 @@ function appIsrRouteKey(pathname) {
|
|
|
206
211
|
return appIsrCacheKey(pathname, pathname !== "/" && pathname.endsWith("/") ? "route:trailing-slash" : "route");
|
|
207
212
|
}
|
|
208
213
|
//#endregion
|
|
209
|
-
export { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrCacheKey, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, coalesceOnDemandRevalidation, getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret, isrCacheControl, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, resolveRouteExpireSeconds, triggerBackgroundRegeneration };
|
|
214
|
+
export { PRERENDER_REVALIDATE_HEADER, PRERENDER_REVALIDATE_ONLY_GENERATED_HEADER, appIsrCacheKey, appIsrHtmlKey, appIsrRouteKey, appIsrRscKey, buildAppPageCacheValue, buildPagesCacheValue, coalesceOnDemandRevalidation, getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret, isrCacheControl, isrCacheKey, isrGet, isrSet, isrSetPrerenderedAppPage, normalizeMountedSlotsHeader, pagesIsrCacheKey, resolveRouteExpireSeconds, triggerBackgroundRegeneration };
|
|
@@ -4,23 +4,28 @@ import { decodeMatchedParams } from "../routing/utils.js";
|
|
|
4
4
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
5
5
|
import { VINEXT_METADATA_ROUTE_CACHE_HEADER } from "./headers.js";
|
|
6
6
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
7
|
-
import { beginRouteCacheability, markRouteCacheabilityExplicitResponsePolicy } from "../shims/cacheability-classification.js";
|
|
8
|
-
import {
|
|
7
|
+
import { beginRouteCacheability, markRouteCacheabilityExplicitResponsePolicy, markRouteCacheabilityResponseBodyComplete, recordRouteCacheability } from "../shims/cacheability-classification.js";
|
|
8
|
+
import { NEVER_CACHE_CONTROL, applyCdnResponseHeaders, hasCdnResponsePolicy } from "./cache-control.js";
|
|
9
|
+
import { buildAppRouteMissIsrCacheControl } from "./isr-decision.js";
|
|
9
10
|
import { isrCacheControl } from "./isr-cache.js";
|
|
10
11
|
import { resolveClientStaleTimeSeconds } from "../utils/cache-control-metadata.js";
|
|
11
|
-
import {
|
|
12
|
+
import { isRenderDynamicLatched } from "../shims/internal/headers-state.js";
|
|
13
|
+
import { getActiveDraftModeState, getHeadersContext, hasDraftModeCookieHeader, replaceHeadersContext } from "../shims/headers.js";
|
|
14
|
+
import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
|
|
12
15
|
import { ensureFetchPatch, getCollectedFetchTags, setCurrentFetchSoftTags } from "../shims/fetch-cache.js";
|
|
13
16
|
import { isValidMetadataImageId, manifestToJson, matchMetadataRoutePattern, robotsToText, sitemapToXml } from "./metadata-routes.js";
|
|
14
17
|
import { applyPrerenderCacheLifeHeader, applyPrerenderCacheTagsHeader } from "./prerender-cache-life-header.js";
|
|
15
18
|
import { canonicalizeAppPageParams } from "./app-page-segment-state.js";
|
|
16
19
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
17
20
|
import { buildAppRouteCacheValue, buildRouteHandlerCachedResponse } from "./app-route-handler-response.js";
|
|
18
|
-
import {
|
|
21
|
+
import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
|
|
22
|
+
import { completeAppRouteHandlerResponse } from "./app-route-handler-execution.js";
|
|
19
23
|
//#region src/server/metadata-route-response.ts
|
|
20
24
|
function isOuterMetadataCacheEnabled() {
|
|
21
25
|
return process.env.NODE_ENV !== "development";
|
|
22
26
|
}
|
|
23
27
|
const routeFunctionCache = /* @__PURE__ */ new WeakMap();
|
|
28
|
+
const userMetadataResponses = /* @__PURE__ */ new WeakSet();
|
|
24
29
|
const USE_CACHE_FUNCTION_SYMBOL = Symbol.for("vinext.useCacheFunction");
|
|
25
30
|
const CACHE_HEADERS = {
|
|
26
31
|
noCache: "no-cache, no-store",
|
|
@@ -53,17 +58,19 @@ function metadataRouteCacheHeader(route) {
|
|
|
53
58
|
if (route.isDynamic && isImageMetadataRoute(route) && process.env.NODE_ENV === "development") return CACHE_HEADERS.noCache;
|
|
54
59
|
return CACHE_HEADERS.revalidate;
|
|
55
60
|
}
|
|
56
|
-
function withMetadataRouteCacheHeader(response, route) {
|
|
57
|
-
if (hasCdnResponsePolicy(response.headers) && !hasExplicitNonCacheableResponsePolicy(response.headers)) markRouteCacheabilityExplicitResponsePolicy();
|
|
58
|
-
const headers = new Headers(response.headers);
|
|
59
|
-
if (!headers.has("Cache-Control")) headers.set("Cache-Control", metadataRouteCacheHeader(route));
|
|
60
|
-
return new Response(response.body, {
|
|
61
|
-
headers,
|
|
62
|
-
status: response.status,
|
|
63
|
-
statusText: response.statusText
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
61
|
function beginMetadataRouteCacheability(route) {
|
|
62
|
+
const dynamic = route.module?.dynamic;
|
|
63
|
+
if (dynamic === "force-static" || dynamic === "error") {
|
|
64
|
+
const current = getHeadersContext();
|
|
65
|
+
const staticContext = createStaticGenerationHeadersContext({
|
|
66
|
+
dynamicConfig: dynamic,
|
|
67
|
+
routeKind: "route",
|
|
68
|
+
routePattern: route.servedUrl,
|
|
69
|
+
draftModeEnabled: getActiveDraftModeState() ?? void 0,
|
|
70
|
+
draftModeSecret: current?.draftModeSecret
|
|
71
|
+
});
|
|
72
|
+
replaceHeadersContext(staticContext);
|
|
73
|
+
}
|
|
67
74
|
beginRouteCacheability("app-route", route.patternParts ? `/${route.patternParts.join("/")}` : route.servedUrl);
|
|
68
75
|
}
|
|
69
76
|
function getMetadataRouteFunctions(route) {
|
|
@@ -137,29 +144,68 @@ function markMetadataRouteCacheValue(value) {
|
|
|
137
144
|
function buildMetadataRouteTags(route, cleanPathname, collectedTags) {
|
|
138
145
|
return buildPageCacheTags(cleanPathname, collectedTags, route.routeSegments ?? [], "route");
|
|
139
146
|
}
|
|
140
|
-
function captureRenderedMetadataRoute(response) {
|
|
141
|
-
const
|
|
147
|
+
async function captureRenderedMetadataRoute(response, route, cleanPathname) {
|
|
148
|
+
const isUserResponse = userMetadataResponses.has(response);
|
|
149
|
+
let completed = false;
|
|
150
|
+
if (isOuterMetadataCacheEnabled()) {
|
|
151
|
+
const result = await completeAppRouteHandlerResponse(response);
|
|
152
|
+
response = result.response;
|
|
153
|
+
completed = result.completed;
|
|
154
|
+
if (completed) markRouteCacheabilityResponseBodyComplete();
|
|
155
|
+
}
|
|
156
|
+
const browserCacheControl = response.headers.get("Cache-Control") ?? void 0;
|
|
157
|
+
const hasUserPolicy = isUserResponse && hasCdnResponsePolicy(response.headers);
|
|
158
|
+
if (hasUserPolicy) markRouteCacheabilityExplicitResponsePolicy();
|
|
159
|
+
const observedCacheLife = _consumeRequestScopedCacheLife();
|
|
142
160
|
const collectedTags = getCollectedFetchTags();
|
|
161
|
+
const revalidate = typeof route.module?.revalidate === "number" ? route.module.revalidate : Infinity;
|
|
162
|
+
const frameworkRevalidate = Math.min(observedCacheLife?.revalidate ?? Infinity, revalidate);
|
|
163
|
+
const cacheLife = {
|
|
164
|
+
...observedCacheLife,
|
|
165
|
+
revalidate: frameworkRevalidate
|
|
166
|
+
};
|
|
167
|
+
const cacheable = (response.status < 400 || response.status === 404) && completed && !isRenderDynamicLatched() && !getActiveDraftModeState() && !hasDraftModeCookieHeader() && route.module?.dynamic !== "force-dynamic" && frameworkRevalidate > 0 && !response.headers.has("set-cookie");
|
|
168
|
+
const cacheControl = cacheable ? buildAppRouteMissIsrCacheControl(frameworkRevalidate, cacheLife?.expire) : NEVER_CACHE_CONTROL;
|
|
169
|
+
if (isUserResponse && !hasUserPolicy) {
|
|
170
|
+
response = new Response(response.body, {
|
|
171
|
+
headers: new Headers(response.headers),
|
|
172
|
+
status: response.status,
|
|
173
|
+
statusText: response.statusText
|
|
174
|
+
});
|
|
175
|
+
applyCdnResponseHeaders(response.headers, { cacheControl: isOuterMetadataCacheEnabled() ? cacheControl : metadataRouteCacheHeader(route) });
|
|
176
|
+
}
|
|
177
|
+
recordRouteCacheability(cacheable ? {
|
|
178
|
+
cacheable: true,
|
|
179
|
+
cacheControl,
|
|
180
|
+
tags: buildMetadataRouteTags(route, cleanPathname, collectedTags)
|
|
181
|
+
} : {
|
|
182
|
+
cacheable: false,
|
|
183
|
+
dynamicUsage: true
|
|
184
|
+
});
|
|
143
185
|
if (process.env.VINEXT_PRERENDER === "1") {
|
|
144
|
-
applyPrerenderCacheLifeHeader(response.headers,
|
|
186
|
+
applyPrerenderCacheLifeHeader(response.headers, {
|
|
187
|
+
...cacheLife,
|
|
188
|
+
revalidate: cacheable ? frameworkRevalidate : 0
|
|
189
|
+
});
|
|
145
190
|
applyPrerenderCacheTagsHeader(response.headers, collectedTags);
|
|
146
191
|
}
|
|
147
192
|
return {
|
|
193
|
+
browserCacheControl,
|
|
148
194
|
cacheLife,
|
|
195
|
+
cacheable,
|
|
149
196
|
collectedTags,
|
|
150
197
|
response
|
|
151
198
|
};
|
|
152
199
|
}
|
|
153
200
|
async function writeRenderedMetadataRoute(options, route, routeKey, rendered, previousEntry) {
|
|
154
|
-
if (!options.isrSet || !rendered.
|
|
201
|
+
if (!options.isrSet || !rendered.cacheable) return;
|
|
155
202
|
const previousCacheControl = previousEntry?.value.cacheControl;
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
const expire = rendered.cacheLife?.expire ?? previousCacheControl?.expire ?? defaultCacheLife.expire;
|
|
203
|
+
const revalidate = rendered.cacheLife?.revalidate ?? previousCacheControl?.revalidate ?? (typeof route.module?.revalidate === "number" ? route.module.revalidate : false);
|
|
204
|
+
const expire = rendered.cacheLife?.expire ?? previousCacheControl?.expire;
|
|
159
205
|
const stale = resolveClientStaleTimeSeconds(rendered.cacheLife) ?? previousCacheControl?.stale;
|
|
160
|
-
const value = markMetadataRouteCacheValue(await buildAppRouteCacheValue(rendered.response));
|
|
206
|
+
const value = markMetadataRouteCacheValue(await buildAppRouteCacheValue(rendered.response, rendered.browserCacheControl));
|
|
161
207
|
await options.isrSet(routeKey, value, {
|
|
162
|
-
cacheControl: isrCacheControl(revalidate, {
|
|
208
|
+
cacheControl: isrCacheControl(revalidate === Infinity ? false : revalidate, {
|
|
163
209
|
...typeof expire === "number" ? { expireSeconds: expire } : {},
|
|
164
210
|
...typeof stale === "number" ? { staleSeconds: stale } : {}
|
|
165
211
|
}),
|
|
@@ -171,16 +217,21 @@ async function runMetadataRouteRegeneration(options, route, render, routeKey, pr
|
|
|
171
217
|
try {
|
|
172
218
|
await runWithRequestContext(requestContext, async () => {
|
|
173
219
|
ensureFetchPatch();
|
|
220
|
+
beginMetadataRouteCacheability(route);
|
|
174
221
|
setCurrentFetchSoftTags(buildMetadataRouteTags(route, options.cleanPathname, []));
|
|
175
222
|
const rendered = await render();
|
|
176
|
-
if (rendered)
|
|
223
|
+
if (rendered) try {
|
|
224
|
+
await writeRenderedMetadataRoute(options, route, routeKey, rendered, previousEntry);
|
|
225
|
+
} finally {
|
|
226
|
+
rendered.response.body?.cancel().catch(() => {});
|
|
227
|
+
}
|
|
177
228
|
});
|
|
178
229
|
} finally {
|
|
179
230
|
await closeAfterResponse(requestContext);
|
|
180
231
|
}
|
|
181
232
|
}
|
|
182
|
-
async function readMatchedPrerenderedMetadataRouteResponse(options, route,
|
|
183
|
-
if (!isOuterMetadataCacheEnabled() || !options.isrGet || !options.isrRouteKey) return {
|
|
233
|
+
async function readMatchedPrerenderedMetadataRouteResponse(options, route, render) {
|
|
234
|
+
if (!isOuterMetadataCacheEnabled() || !options.isrGet || !options.isrRouteKey || getActiveDraftModeState() || hasDraftModeCookieHeader() || route.module?.dynamic === "force-dynamic" || route.module?.revalidate === 0) return {
|
|
184
235
|
cachedEntry: null,
|
|
185
236
|
response: null
|
|
186
237
|
};
|
|
@@ -214,7 +265,7 @@ async function readMatchedPrerenderedMetadataRouteResponse(options, route, funct
|
|
|
214
265
|
revalidateSeconds
|
|
215
266
|
})
|
|
216
267
|
};
|
|
217
|
-
if (
|
|
268
|
+
if (options.isrSet && options.scheduleBackgroundRegeneration) {
|
|
218
269
|
const executionContext = getRequestExecutionContext();
|
|
219
270
|
options.scheduleBackgroundRegeneration(routeKey, () => runMetadataRouteRegeneration(options, route, render, routeKey, cached, executionContext), {
|
|
220
271
|
routerKind: "App Router",
|
|
@@ -330,7 +381,10 @@ async function handleGeneratedSitemap(route, cleanPathname, functions) {
|
|
|
330
381
|
const matchedId = findGeneratedSitemapId(await functions.generateSitemaps({}), rawId);
|
|
331
382
|
if (!matchedId) return notFoundResponse();
|
|
332
383
|
const result = await functions.defaultExport({ id: makeThenableMetadataRouteId(matchedId) });
|
|
333
|
-
if (result instanceof Response)
|
|
384
|
+
if (result instanceof Response) {
|
|
385
|
+
userMetadataResponses.add(result);
|
|
386
|
+
return result;
|
|
387
|
+
}
|
|
334
388
|
if (!isSitemapEntries(result)) throw new TypeError("Metadata sitemap routes must return an array.");
|
|
335
389
|
return markFullyBufferedBody(new Response(sitemapToXml(result), { headers: {
|
|
336
390
|
"Content-Type": route.contentType,
|
|
@@ -367,7 +421,10 @@ async function callDynamicMetadataRoute(route, match, makeThenableParams, functi
|
|
|
367
421
|
id: makeThenableMetadataRouteId(matchedImageId)
|
|
368
422
|
});
|
|
369
423
|
} else result = await functions.defaultExport({ params: paramsThenable });
|
|
370
|
-
if (result instanceof Response)
|
|
424
|
+
if (result instanceof Response) {
|
|
425
|
+
userMetadataResponses.add(result);
|
|
426
|
+
return result;
|
|
427
|
+
}
|
|
371
428
|
let body;
|
|
372
429
|
if (route.type === "sitemap") {
|
|
373
430
|
if (!isSitemapEntries(result)) throw new TypeError("Metadata sitemap routes must return an array.");
|
|
@@ -410,8 +467,8 @@ function isMetadataRouteRequestPath(metadataRoutes, cleanPathname) {
|
|
|
410
467
|
}
|
|
411
468
|
return false;
|
|
412
469
|
}
|
|
413
|
-
async function writeMetadataRouteMiss(options, route,
|
|
414
|
-
if (process.env.VINEXT_PRERENDER === "1" || !isOuterMetadataCacheEnabled() || !rendered.
|
|
470
|
+
async function writeMetadataRouteMiss(options, route, rendered, cachedEntry) {
|
|
471
|
+
if (process.env.VINEXT_PRERENDER === "1" || !isOuterMetadataCacheEnabled() || !rendered.cacheable || !options.isrRouteKey || !options.isrSet) return;
|
|
415
472
|
try {
|
|
416
473
|
await writeRenderedMetadataRoute(options, route, options.isrRouteKey(options.cleanPathname), {
|
|
417
474
|
...rendered,
|
|
@@ -433,13 +490,13 @@ async function handleMetadataRouteRequest(options) {
|
|
|
433
490
|
const render = async () => {
|
|
434
491
|
setCurrentFetchSoftTags(buildMetadataRouteTags(route, options.cleanPathname, []));
|
|
435
492
|
const response = await handleGeneratedSitemap(route, options.cleanPathname, functions);
|
|
436
|
-
return response ? captureRenderedMetadataRoute(response) : null;
|
|
493
|
+
return response ? captureRenderedMetadataRoute(response, route, options.cleanPathname) : null;
|
|
437
494
|
};
|
|
438
|
-
const cached = await readMatchedPrerenderedMetadataRouteResponse(options, route,
|
|
495
|
+
const cached = await readMatchedPrerenderedMetadataRouteResponse(options, route, render);
|
|
439
496
|
if (cached.response) return cached.response;
|
|
440
497
|
const rendered = await render();
|
|
441
498
|
if (rendered) {
|
|
442
|
-
await writeMetadataRouteMiss(options, route,
|
|
499
|
+
await writeMetadataRouteMiss(options, route, rendered, cached.cachedEntry);
|
|
443
500
|
return rendered.response;
|
|
444
501
|
}
|
|
445
502
|
}
|
|
@@ -471,12 +528,12 @@ async function handleMetadataRouteRequest(options) {
|
|
|
471
528
|
}
|
|
472
529
|
const render = async () => {
|
|
473
530
|
setCurrentFetchSoftTags(buildMetadataRouteTags(route, options.cleanPathname, []));
|
|
474
|
-
return captureRenderedMetadataRoute(route.isDynamic ? await callDynamicMetadataRoute(route, match, options.makeThenableParams, functions) : serveStaticMetadataRoute(route));
|
|
531
|
+
return captureRenderedMetadataRoute(route.isDynamic ? await callDynamicMetadataRoute(route, match, options.makeThenableParams, functions) : serveStaticMetadataRoute(route), route, options.cleanPathname);
|
|
475
532
|
};
|
|
476
|
-
const cached = await readMatchedPrerenderedMetadataRouteResponse(options, route,
|
|
533
|
+
const cached = await readMatchedPrerenderedMetadataRouteResponse(options, route, render);
|
|
477
534
|
if (cached.response) return cached.response;
|
|
478
535
|
const rendered = await render();
|
|
479
|
-
await writeMetadataRouteMiss(options, route,
|
|
536
|
+
await writeMetadataRouteMiss(options, route, rendered, cached.cachedEntry);
|
|
480
537
|
return rendered.response;
|
|
481
538
|
}
|
|
482
539
|
return null;
|
|
@@ -3,6 +3,8 @@ import "./server-globals.js";
|
|
|
3
3
|
import { NextRequest } from "../shims/server.js";
|
|
4
4
|
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
5
5
|
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
6
|
+
import { markRouteCacheabilityExplicitResponsePolicy } from "../shims/cacheability-classification.js";
|
|
7
|
+
import { hasCdnResponsePolicy } from "./cache-control.js";
|
|
6
8
|
import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
|
|
7
9
|
import { tracePagesApiHandler } from "./pages-execution-tracing.js";
|
|
8
10
|
import { resolveBodyParserConfig } from "./pages-body-parser-config.js";
|
|
@@ -29,8 +31,12 @@ function isNodeApiRouteModule(module) {
|
|
|
29
31
|
return typeof module.default === "function" && !isEdgeApiRuntime(resolveModuleRuntime(module));
|
|
30
32
|
}
|
|
31
33
|
async function handlePagesApiRoute(options) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
const run = async () => {
|
|
35
|
+
const response = await _handlePagesApiRoute(options);
|
|
36
|
+
if (hasCdnResponsePolicy(response.headers)) markRouteCacheabilityExplicitResponsePolicy();
|
|
37
|
+
return response;
|
|
38
|
+
};
|
|
39
|
+
return options.ctx ? runWithExecutionContext(options.ctx, run) : run();
|
|
34
40
|
}
|
|
35
41
|
async function _handlePagesApiRoute(options) {
|
|
36
42
|
if (!options.match) return new Response("404 - API route not found", { status: 404 });
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* unit-testable and lives in a normal typed module rather than a codegen
|
|
10
10
|
* template string.
|
|
11
11
|
*/
|
|
12
|
+
export declare function getSharedChunkFiles(manifest: Record<string, string[]>): string[];
|
|
12
13
|
/**
|
|
13
14
|
* Resolve the effective SSR manifest: prefer the caller-supplied object and
|
|
14
15
|
* fall back to the registered client build metadata.
|