vinext 1.0.0 → 1.1.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 +72 -1
- package/THIRD_PARTY_LICENSES.md +26 -0
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -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 +6 -85
- package/dist/build/prerender.d.ts +8 -1
- package/dist/build/prerender.js +167 -46
- 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/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/browser-globals.d.ts +4 -0
- package/dist/client/browser-globals.js +5 -0
- package/dist/client/navigation-runtime.d.ts +11 -1
- package/dist/client/navigation-runtime.js +3 -3
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/dotenv.js +14 -3
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +67 -45
- package/dist/index.d.ts +4 -1
- package/dist/index.js +200 -100
- 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/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/commonjs-syntax.d.ts +16 -0
- package/dist/plugins/commonjs-syntax.js +22 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- 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/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- 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 +15 -9
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-hydration.d.ts +1 -1
- package/dist/server/app-browser-hydration.js +2 -2
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -1
- package/dist/server/app-history-state.js +9 -5
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +65 -44
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -118
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +55 -33
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-search-params-observation.js +1 -1
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +7 -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-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +8 -11
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- 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 +11 -4
- 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 +8 -12
- 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 +5 -0
- package/dist/server/app-rsc-handler.js +229 -102
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +7 -4
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +37 -20
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +9 -7
- package/dist/server/app-ssr-search-params-gate.js +1 -1
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +35 -16
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cache-control.js +3 -11
- package/dist/server/cacheability-request.js +56 -52
- package/dist/server/config-headers.js +3 -1
- package/dist/server/dev-server.js +23 -5
- package/dist/server/headers.d.ts +16 -0
- package/dist/server/headers.js +19 -1
- package/dist/server/http-error-responses.js +1 -0
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.d.ts +2 -0
- package/dist/server/isr-cache.js +8 -3
- package/dist/server/metadata-route-response.js +94 -37
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- 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 +50 -15
- 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 +14 -8
- package/dist/server/prerender-manifest.d.ts +6 -0
- package/dist/server/prerender-manifest.js +1 -1
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +152 -78
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/response-stage-cacheability.js +1 -1
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- 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-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +18 -14
- package/dist/shims/cache-request-state.js +33 -21
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +168 -226
- package/dist/shims/cache.d.ts +3 -2
- package/dist/shims/cache.js +8 -5
- package/dist/shims/cacheability-classification.d.ts +8 -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-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- 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.d.ts +6 -0
- package/dist/shims/fetch-cache.js +23 -4
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +19 -69
- package/dist/shims/headers.js +82 -183
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- 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 +73 -0
- package/dist/shims/internal/headers-state.js +157 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +16 -6
- package/dist/shims/request-context.d.ts +9 -0
- 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/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/encode-cache-tag.d.ts +1 -0
- package/dist/utils/encode-cache-tag.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/dist/utils/vite-cli-invocation.js +8 -1
- package/package.json +8 -4
- package/dist/server/metadata-route-cache-policy.d.ts +0 -5
- package/dist/server/metadata-route-cache-policy.js +0 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "../utils/protocol-headers.js";
|
|
2
2
|
import { isVinextRscVaryField } from "./app-rsc-vary.js";
|
|
3
|
-
import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER } from "./headers.js";
|
|
3
|
+
import { VINEXT_CACHEABILITY_PROBE_HEADER, VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER, VINEXT_SPECIAL_ERROR_STATUS_HEADER } from "./headers.js";
|
|
4
4
|
import { isNonCacheableCacheControl } from "../shims/cdn-cache.js";
|
|
5
5
|
import { CACHEABILITY_REQUEST_STATE, recordConfigCdnCachePolicyHeader } from "../shims/cacheability-classification.js";
|
|
6
6
|
import { NO_STORE_CACHE_CONTROL, applyCdnResponseBuildIdentityHeaders, applyCdnResponseHeaders, hasExplicitNonCacheableResponsePolicy, isCdnResponsePolicyHeader, readCdnResponseCacheControl, readCdnResponsePolicyHeaderName } from "./cache-control.js";
|
|
@@ -348,17 +348,25 @@ 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, completedStatus) {
|
|
352
352
|
const headers = new Headers(response.headers);
|
|
353
353
|
if (typeof body === "string") headers.delete("Content-Length");
|
|
354
|
+
for (const [name, value] of Object.entries(completedStatus?.headers ?? {})) if (!headers.has(name)) headers.set(name, value);
|
|
354
355
|
applyCdnResponseHeaders(headers, outcome?.cacheable === true && outcome.cacheControl ? {
|
|
355
356
|
cacheControl: outcome.cacheControl,
|
|
356
|
-
tags: outcome.tags
|
|
357
|
-
|
|
357
|
+
tags: outcome.tags,
|
|
358
|
+
browserCacheControl
|
|
359
|
+
} : {
|
|
360
|
+
cacheControl: NO_STORE_CACHE_CONTROL,
|
|
361
|
+
browserCacheControl
|
|
362
|
+
});
|
|
363
|
+
const status = completedStatus?.status ?? response.status;
|
|
364
|
+
const completed = completedStatus?.status;
|
|
365
|
+
if (completed === 401 || completed === 403 || completed === 404) headers.set(VINEXT_SPECIAL_ERROR_STATUS_HEADER, String(completed));
|
|
358
366
|
return new Response(body, {
|
|
359
367
|
headers,
|
|
360
|
-
status
|
|
361
|
-
statusText: response.statusText
|
|
368
|
+
status,
|
|
369
|
+
statusText: status === response.status ? response.statusText : ""
|
|
362
370
|
});
|
|
363
371
|
}
|
|
364
372
|
async function stripSharedHtmlClientTraceMetadata(body, marker) {
|
|
@@ -367,21 +375,15 @@ async function stripSharedHtmlClientTraceMetadata(body, marker) {
|
|
|
367
375
|
const { stripClientTraceMetadataBlock } = await import("./client-trace-metadata.js");
|
|
368
376
|
return stripClientTraceMetadataBlock(html, marker);
|
|
369
377
|
}
|
|
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) {
|
|
378
|
+
/** Only an explicitly authored provider policy may override framework storage. */
|
|
379
|
+
function explicitProviderOutcome(response, state) {
|
|
380
|
+
const name = readCdnResponsePolicyHeaderName(response.headers);
|
|
381
|
+
if (!name || name === "cache-control") return null;
|
|
382
|
+
const value = response.headers.get(name);
|
|
383
|
+
if (!(state.explicitResponseCachePolicy || state.configCdnCachePolicy?.get(name) === value || state.frameworkResponseCachePolicy && state.frameworkResponseCachePolicy.get(name) !== value) || !value) return null;
|
|
382
384
|
const cacheControl = readCdnResponseCacheControl(response.headers);
|
|
383
|
-
if (!cacheControl
|
|
384
|
-
return {
|
|
385
|
+
if (!cacheControl) return null;
|
|
386
|
+
return isNonCacheableCacheControl(cacheControl) ? { cacheable: false } : {
|
|
385
387
|
cacheable: true,
|
|
386
388
|
cacheControl,
|
|
387
389
|
...state.cdnCacheTags ? { tags: state.cdnCacheTags } : {}
|
|
@@ -397,18 +399,17 @@ function completedRouteOutcome(response, state, rendererOutcome = state.outcome
|
|
|
397
399
|
cacheable: false,
|
|
398
400
|
reason: varyRejectionReason
|
|
399
401
|
};
|
|
400
|
-
if (
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
return responseOutcome.cacheable ? responseOutcome : rendererOutcome ?? responseOutcome;
|
|
402
|
+
if (response.headers.has("set-cookie")) return {
|
|
403
|
+
cacheable: false,
|
|
404
|
+
reason: "response sets a cookie"
|
|
405
|
+
};
|
|
406
|
+
if (rendererOutcome?.dynamicUsage) return rendererOutcome;
|
|
407
|
+
const outcome = explicitProviderOutcome(response, state) ?? rendererOutcome;
|
|
408
|
+
const tags = outcome?.tags ?? rendererOutcome?.tags ?? state.cdnCacheTags;
|
|
409
|
+
return outcome && tags && outcome.tags !== tags ? {
|
|
410
|
+
...outcome,
|
|
411
|
+
tags
|
|
412
|
+
} : outcome;
|
|
412
413
|
}
|
|
413
414
|
function staticToDynamicResponse(route) {
|
|
414
415
|
const headers = new Headers({ "Content-Type": "text/plain; charset=utf-8" });
|
|
@@ -427,30 +428,32 @@ function cacheabilityEvaluationFailureResponse(pattern) {
|
|
|
427
428
|
});
|
|
428
429
|
}
|
|
429
430
|
function hasStrictFinalResponseVeto(response, state) {
|
|
430
|
-
|
|
431
|
-
|
|
431
|
+
const providerHeaders = new Headers(response.headers);
|
|
432
|
+
providerHeaders.delete("Cache-Control");
|
|
433
|
+
return Boolean(state.finalResponseVetoReason || response.headers.has("set-cookie") || hasExplicitNonCacheableResponsePolicy(providerHeaders, state.frameworkResponseCachePolicy));
|
|
432
434
|
}
|
|
433
435
|
async function finalizeWorkerCacheabilityAdmission(response, state) {
|
|
434
436
|
if (state.preserveResponseCachePolicy) return response;
|
|
437
|
+
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
438
|
const admission = state.admission;
|
|
436
439
|
if (state.route?.kind === "app-route" || state.route?.kind === "pages-api") {
|
|
437
440
|
let manifestRoute = null;
|
|
438
|
-
const responseOutcome =
|
|
441
|
+
const responseOutcome = completedRouteOutcome(response, state);
|
|
439
442
|
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);
|
|
443
|
+
const hasExplicitRuntimePolicy = responseOutcome?.cacheable === true;
|
|
444
|
+
if (!admission || admission.policy === "deny" || !representation || !admission.requestKey) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
442
445
|
if (admission.policy === "manifest" && state.route.kind === "app-route") {
|
|
443
446
|
const manifest = admission.manifest;
|
|
444
447
|
manifestRoute = findCacheabilityManifestRoute(manifest, state.route.kind, state.route.pattern);
|
|
445
448
|
}
|
|
446
449
|
const isManifestAuthorized = manifestRoute !== null && admission.routePathname !== void 0 && cacheabilityManifestRouteState(manifestRoute, admission.routePathname, representation) !== null;
|
|
447
450
|
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);
|
|
451
|
+
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
452
|
const outcome = responseOutcome;
|
|
450
|
-
if (!outcome.cacheable || !outcome.cacheControl) return responseWithCachePolicy(response, response.body, null);
|
|
451
453
|
if (state.completedResponseBody) {
|
|
454
|
+
if (!outcome?.cacheable || !outcome.cacheControl) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
452
455
|
if (!state.applyCompletedResponsePolicy) return response;
|
|
453
|
-
return responseWithCachePolicy(response, response.body, outcome);
|
|
456
|
+
return responseWithCachePolicy(response, response.body, outcome, browserCacheControl);
|
|
454
457
|
}
|
|
455
458
|
let captured;
|
|
456
459
|
try {
|
|
@@ -458,35 +461,36 @@ async function finalizeWorkerCacheabilityAdmission(response, state) {
|
|
|
458
461
|
} catch {
|
|
459
462
|
return cacheabilityEvaluationFailureResponse(state.route.pattern);
|
|
460
463
|
}
|
|
461
|
-
if (captured.kind === "fallback") return responseWithCachePolicy(response, captured.body, null);
|
|
462
|
-
return responseWithCachePolicy(response, captured.body, outcome);
|
|
464
|
+
if (captured.kind === "fallback") return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
|
|
465
|
+
return responseWithCachePolicy(response, captured.body, outcome, browserCacheControl);
|
|
463
466
|
}
|
|
464
|
-
if (!admission || admission.policy === "deny" || !admission.representation || !admission.requestKey || !state.route || response.status >= 500) return responseWithCachePolicy(response, response.body, null);
|
|
467
|
+
if (!admission || admission.policy === "deny" || !admission.representation || !admission.requestKey || !state.route || response.status >= 500) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
465
468
|
const pageRoute = {
|
|
466
469
|
kind: state.route.kind,
|
|
467
470
|
pattern: state.route.pattern
|
|
468
471
|
};
|
|
469
472
|
const requestRepresentation = admission.representation;
|
|
470
473
|
const representation = resolveCacheabilityRepresentation(requestRepresentation, pageRoute.kind);
|
|
471
|
-
if (!cacheabilityRepresentationMatchesPageRoute(pageRoute.kind, representation)) return responseWithCachePolicy(response, response.body, null);
|
|
474
|
+
if (!cacheabilityRepresentationMatchesPageRoute(pageRoute.kind, representation)) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
472
475
|
let manifestRoute = null;
|
|
473
476
|
let manifestRouteState = null;
|
|
474
477
|
if (admission.policy === "manifest") {
|
|
475
478
|
const manifest = admission.manifest;
|
|
476
479
|
manifestRoute = findCacheabilityManifestRoute(manifest, pageRoute.kind, pageRoute.pattern);
|
|
477
480
|
manifestRouteState = admission.routePathname ? cacheabilityManifestPageState(manifest, pageRoute, requestRepresentation, admission.routePathname) : null;
|
|
478
|
-
if (!manifestRoute || !manifestRouteState) return responseWithCachePolicy(response, response.body, null);
|
|
481
|
+
if (!manifestRoute || !manifestRouteState) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
479
482
|
}
|
|
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);
|
|
483
|
+
if (state.forcedDynamicReason) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
484
|
+
if (hasStrictFinalResponseVeto(response, state)) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
485
|
+
if (cacheabilityVaryRejectionReason(response.headers, state) !== null) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
486
|
+
if (state.route.kind === "pages-page" && !state.completion && completedRouteOutcome(response, state)?.cacheable !== true) return responseWithCachePolicy(response, response.body, null, browserCacheControl);
|
|
483
487
|
let captured;
|
|
484
488
|
try {
|
|
485
489
|
captured = await captureCacheabilityAdmissionBody(response.body, state.captureDeadlineAt, CACHEABILITY_ADMISSION_RESPONSE_BODY_LIMIT, state.captureBudget ?? isolateCaptureBudget);
|
|
486
490
|
} catch {
|
|
487
491
|
return cacheabilityEvaluationFailureResponse(state.route.pattern);
|
|
488
492
|
}
|
|
489
|
-
if (captured.kind === "fallback") return responseWithCachePolicy(response, captured.body, null);
|
|
493
|
+
if (captured.kind === "fallback") return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
|
|
490
494
|
const rendererOutcome = state.completion ? await state.completion : state.outcome ?? null;
|
|
491
495
|
const outcome = completedRouteOutcome(response, state, rendererOutcome);
|
|
492
496
|
if (outcome?.cacheable !== true || !outcome.cacheControl) {
|
|
@@ -494,12 +498,12 @@ async function finalizeWorkerCacheabilityAdmission(response, state) {
|
|
|
494
498
|
await captured.body?.cancel().catch(() => {});
|
|
495
499
|
return staticToDynamicResponse(manifestRoute);
|
|
496
500
|
}
|
|
497
|
-
return responseWithCachePolicy(response, captured.body, null);
|
|
501
|
+
return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
|
|
498
502
|
}
|
|
499
503
|
const effectivePolicyHeader = readCdnResponsePolicyHeaderName(response.headers);
|
|
500
504
|
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);
|
|
505
|
+
if (state.route.kind === "app-page" && !replacesRendererPolicy && rendererOutcome?.searchParamsUnread !== true) return responseWithCachePolicy(response, captured.body, null, browserCacheControl);
|
|
506
|
+
return responseWithCachePolicy(response, representation === "html" && state.clientTraceMetadataMarker ? await stripSharedHtmlClientTraceMetadata(captured.body, state.clientTraceMetadataMarker) : captured.body, outcome, browserCacheControl, rendererOutcome ?? void 0);
|
|
503
507
|
}
|
|
504
508
|
async function finalizeWorkerCacheabilityResponse(response, ctx) {
|
|
505
509
|
const state = readState(ctx);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { matchHeaders } from "../config/config-matchers.js";
|
|
2
|
+
import "./headers.js";
|
|
2
3
|
import { markRouteCacheabilityConfigCdnCachePolicy, markRouteCacheabilityDynamic, markRouteCacheabilityFinalResponseUncacheable } from "../shims/cacheability-classification.js";
|
|
3
4
|
import { isCdnResponsePolicyHeader, isNonCacheableCdnResponsePolicy } from "./cache-control.js";
|
|
4
5
|
import { mergeVaryHeader } from "./middleware-response-headers.js";
|
|
@@ -28,7 +29,7 @@ function markExplicitConfigResponseVeto(matched) {
|
|
|
28
29
|
continue;
|
|
29
30
|
}
|
|
30
31
|
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`);
|
|
32
|
+
if (name !== "cache-control" && isCdnResponsePolicyHeader(name) && isNonCacheableCdnResponsePolicy(name, header.value)) markRouteCacheabilityFinalResponseUncacheable(`next.config headers set a non-cacheable ${header.key} policy`);
|
|
32
33
|
}
|
|
33
34
|
}
|
|
34
35
|
function retainLastSingularConfigValues(matched) {
|
|
@@ -77,6 +78,7 @@ function applyConfigHeadersToResponse(responseHeaders, options) {
|
|
|
77
78
|
if (options.recordCacheability !== false) markExplicitConfigResponseVeto(matched);
|
|
78
79
|
for (const header of matched) {
|
|
79
80
|
const lowerName = header.key.toLowerCase();
|
|
81
|
+
if (lowerName === "x-vinext-special-error-status") continue;
|
|
80
82
|
if (lowerName === "link") {
|
|
81
83
|
if (options.middlewareHeaders?.get(lowerName)) continue;
|
|
82
84
|
const postConfigLink = options.appendToPostConfigLink ? responseHeaders.get(lowerName) : null;
|
|
@@ -21,6 +21,7 @@ import { createInlineScriptTag, createNonceAttribute, safeJsonStringify } from "
|
|
|
21
21
|
import { applyDocumentAssetProps, extractDocumentAssetProps, markDocumentAssetPropsProtectedTags, stripDocumentAssetPropsProtectionMarkers } from "./pages-document-asset-props.js";
|
|
22
22
|
import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
|
|
23
23
|
import { getScriptNonceFromNodeHeaderSources } from "./csp.js";
|
|
24
|
+
import { stripViteModuleQuery } from "../utils/path.js";
|
|
24
25
|
import { logRequest, now } from "./request-log.js";
|
|
25
26
|
import { buildDefaultPagesNotFoundResponse } from "./pages-default-404.js";
|
|
26
27
|
import { buildPagesReadinessNextData } from "./pages-readiness.js";
|
|
@@ -148,6 +149,15 @@ function stripDevPagesNotFoundFramingHeaders(res) {
|
|
|
148
149
|
res.removeHeader("Transfer-Encoding");
|
|
149
150
|
}
|
|
150
151
|
/**
|
|
152
|
+
* Vite's `transformIndexHtml` treats its URL as the HTML document's path, so
|
|
153
|
+
* the request query carries no meaning there. Since Vite 8.3.3 it also maps
|
|
154
|
+
* `/?q` onto the project root directory and then watches the filesystem root
|
|
155
|
+
* for each inline `<style>` proxy module, so pass the bare path.
|
|
156
|
+
*/
|
|
157
|
+
function toHtmlTransformPath(url) {
|
|
158
|
+
return stripViteModuleQuery(url);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
151
161
|
* Stream a Pages Router page response using progressive SSR.
|
|
152
162
|
*
|
|
153
163
|
* Sends the HTML shell (head, layout, Suspense fallbacks) immediately
|
|
@@ -244,7 +254,7 @@ async function streamPageToResponseImpl(routePattern, res, element, options) {
|
|
|
244
254
|
</body>
|
|
245
255
|
</html>`;
|
|
246
256
|
}
|
|
247
|
-
let transformedShell = await server.transformIndexHtml(url, shellTemplate);
|
|
257
|
+
let transformedShell = await server.transformIndexHtml(toHtmlTransformPath(url), shellTemplate);
|
|
248
258
|
transformedShell = stripDocumentAssetPropsProtectionMarkers(applyDocumentAssetProps(transformedShell, documentAssetProps, {
|
|
249
259
|
configuredCrossOrigin: crossOrigin,
|
|
250
260
|
protectedAssetMarker,
|
|
@@ -504,13 +514,17 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
504
514
|
if (typeof pageModule.getStaticPaths === "function" && route.isDynamic) {
|
|
505
515
|
const pathsResult = await pageModule.getStaticPaths({
|
|
506
516
|
locales: i18nConfig?.locales ?? [],
|
|
507
|
-
defaultLocale:
|
|
517
|
+
defaultLocale: i18nConfig?.defaultLocale ?? ""
|
|
508
518
|
});
|
|
509
519
|
const fallback = pathsResult?.fallback ?? false;
|
|
510
520
|
const paths = pathsResult?.paths ?? [];
|
|
511
521
|
const routePattern = patternToNextFormat(route.pattern);
|
|
512
522
|
const routeParams = getPagesRouteParams(routePattern);
|
|
513
|
-
const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, params, routeParams,
|
|
523
|
+
const isValidPath = paths.some((pathEntry) => matchesPagesStaticPath(pathEntry, params, routeParams, localeStrippedUrl, {
|
|
524
|
+
locale,
|
|
525
|
+
locales: i18nConfig?.locales,
|
|
526
|
+
defaultLocale: i18nConfig?.defaultLocale
|
|
527
|
+
}));
|
|
514
528
|
if (fallback === false && !isValidPath && requestPreviewData === false) {
|
|
515
529
|
if (isDataReq) {
|
|
516
530
|
const deploymentId = process.env.__VINEXT_DEPLOYMENT_ID || process.env.NEXT_DEPLOYMENT_ID;
|
|
@@ -745,6 +759,7 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
745
759
|
}
|
|
746
760
|
if ((statusCode ?? 200) === 200) dataHeaders["x-nextjs-matched-path"] = `${locale ? `/${locale}` : ""}${patternToNextFormat(route.pattern)}`;
|
|
747
761
|
if (gsspExtraHeaders) for (const [k, v] of Object.entries(gsspExtraHeaders)) dataHeaders[k] = v;
|
|
762
|
+
dataHeaders["Cache-Control"] = DEV_PAGES_CACHE_CONTROL;
|
|
748
763
|
applyDevPagesPreviewHeaders(dataHeaders, requestPreview);
|
|
749
764
|
const dataRoutePattern = patternToNextFormat(route.pattern);
|
|
750
765
|
if (dataRoutePattern !== "/_error" && dataRoutePattern !== "/500") {
|
|
@@ -836,7 +851,10 @@ function createSSRHandler(server, runner, routes, pagesDir, i18nConfig, fileMatc
|
|
|
836
851
|
domainLocales,
|
|
837
852
|
...serializedPagesNextData
|
|
838
853
|
})}<\/script>`}\n ${createInlineScriptTag(`window.__VINEXT_PAGE_PATTERNS__=${safeJsonStringify(pagePatterns)}`, scriptNonce)}\n ${hydrationScript}`;
|
|
839
|
-
const extraHeaders = {
|
|
854
|
+
const extraHeaders = {
|
|
855
|
+
...gsspExtraHeaders,
|
|
856
|
+
"Cache-Control": DEV_PAGES_CACHE_CONTROL
|
|
857
|
+
};
|
|
840
858
|
if (typeof pageModule.getStaticProps === "function") {
|
|
841
859
|
extraHeaders["Cache-Control"] = DEV_PAGES_CACHE_CONTROL;
|
|
842
860
|
extraHeaders[NEXTJS_CACHE_HEADER] = isFallbackRender ? "MISS" : isOnDemandRevalidate ? "REVALIDATED" : "HIT";
|
|
@@ -1122,7 +1140,7 @@ async function renderErrorPage(server, runner, req, res, url, pagesDir, statusCo
|
|
|
1122
1140
|
${protectedErrorScripts}
|
|
1123
1141
|
</body>
|
|
1124
1142
|
</html>`;
|
|
1125
|
-
const transformedHtml = stripDocumentAssetPropsProtectionMarkers(applyDocumentAssetProps(await server.transformIndexHtml(url, html), {}, {
|
|
1143
|
+
const transformedHtml = stripDocumentAssetPropsProtectionMarkers(applyDocumentAssetProps(await server.transformIndexHtml(toHtmlTransformPath(url), html), {}, {
|
|
1126
1144
|
configuredCrossOrigin: context.crossOrigin,
|
|
1127
1145
|
protectedAssetMarker
|
|
1128
1146
|
}), protectedAssetMarker);
|
package/dist/server/headers.d.ts
CHANGED
|
@@ -58,12 +58,28 @@ export declare const VINEXT_PARAMS_HEADER = "X-Vinext-Params";
|
|
|
58
58
|
export declare const VINEXT_DYNAMIC_STALE_TIME_HEADER = "X-Vinext-Dynamic-Stale-Time";
|
|
59
59
|
/** Marks an RSC body carrying completion metadata after the Flight payload. */
|
|
60
60
|
export declare const VINEXT_RSC_COMPLETION_METADATA_HEADER = "X-Vinext-Rsc-Completion-Metadata";
|
|
61
|
+
/**
|
|
62
|
+
* Carries the stored status of an App page RSC response whose 401, 403 or 404
|
|
63
|
+
* is its page's notFound(), forbidden() or unauthorized(). Middleware and
|
|
64
|
+
* config headers can't set it, and the request stage strips it.
|
|
65
|
+
*/
|
|
66
|
+
export declare const VINEXT_SPECIAL_ERROR_STATUS_HEADER = "x-vinext-special-error-status";
|
|
61
67
|
/** URL-encoded rendered path and search after middleware/config rewrites. */
|
|
62
68
|
export declare const VINEXT_RENDERED_PATH_AND_SEARCH_HEADER = "X-Vinext-Rendered-Path-And-Search";
|
|
63
69
|
/** Prerender-only JSON side channel carrying request cacheLife metadata. */
|
|
64
70
|
export declare const VINEXT_PRERENDER_CACHE_LIFE_HEADER = "x-vinext-prerender-cache-life";
|
|
71
|
+
/** Prerender-only Pages marker: "0" confirms the page render used the requested URL. */
|
|
72
|
+
export declare const VINEXT_PRERENDER_REWRITTEN_HEADER = "x-vinext-prerender-rewritten";
|
|
65
73
|
/** Marks a local prerender-server 500 that originated from a thrown render error. */
|
|
66
74
|
export declare const VINEXT_PRERENDER_RENDER_ERROR_HEADER = "x-vinext-prerender-render-error";
|
|
75
|
+
/**
|
|
76
|
+
* Prerender-only marker: the response's 401, 403, 404 or redirect is its page's
|
|
77
|
+
* notFound(), forbidden(), unauthorized() or redirect(), which escaped the shell.
|
|
78
|
+
* Its value is the JSON of the headers to store: a redirect's own location, or
|
|
79
|
+
* `{}`. Only the prerender server sets it, from the special error the page
|
|
80
|
+
* recorded on its ctx, and it drops one that the response carries.
|
|
81
|
+
*/
|
|
82
|
+
export declare const VINEXT_PRERENDER_SPECIAL_ERROR_HEADER = "x-vinext-prerender-special-error";
|
|
67
83
|
/** Internal marker persisted only inside metadata-route APP_ROUTE cache values. */
|
|
68
84
|
export declare const VINEXT_METADATA_ROUTE_CACHE_HEADER = "x-vinext-metadata-route-cache";
|
|
69
85
|
/** Disabled-by-default client hint describing already-held App Router payload entries. */
|
package/dist/server/headers.js
CHANGED
|
@@ -58,12 +58,28 @@ const VINEXT_PARAMS_HEADER = "X-Vinext-Params";
|
|
|
58
58
|
const VINEXT_DYNAMIC_STALE_TIME_HEADER = "X-Vinext-Dynamic-Stale-Time";
|
|
59
59
|
/** Marks an RSC body carrying completion metadata after the Flight payload. */
|
|
60
60
|
const VINEXT_RSC_COMPLETION_METADATA_HEADER = "X-Vinext-Rsc-Completion-Metadata";
|
|
61
|
+
/**
|
|
62
|
+
* Carries the stored status of an App page RSC response whose 401, 403 or 404
|
|
63
|
+
* is its page's notFound(), forbidden() or unauthorized(). Middleware and
|
|
64
|
+
* config headers can't set it, and the request stage strips it.
|
|
65
|
+
*/
|
|
66
|
+
const VINEXT_SPECIAL_ERROR_STATUS_HEADER = "x-vinext-special-error-status";
|
|
61
67
|
/** URL-encoded rendered path and search after middleware/config rewrites. */
|
|
62
68
|
const VINEXT_RENDERED_PATH_AND_SEARCH_HEADER = "X-Vinext-Rendered-Path-And-Search";
|
|
63
69
|
/** Prerender-only JSON side channel carrying request cacheLife metadata. */
|
|
64
70
|
const VINEXT_PRERENDER_CACHE_LIFE_HEADER = "x-vinext-prerender-cache-life";
|
|
71
|
+
/** Prerender-only Pages marker: "0" confirms the page render used the requested URL. */
|
|
72
|
+
const VINEXT_PRERENDER_REWRITTEN_HEADER = "x-vinext-prerender-rewritten";
|
|
65
73
|
/** Marks a local prerender-server 500 that originated from a thrown render error. */
|
|
66
74
|
const VINEXT_PRERENDER_RENDER_ERROR_HEADER = "x-vinext-prerender-render-error";
|
|
75
|
+
/**
|
|
76
|
+
* Prerender-only marker: the response's 401, 403, 404 or redirect is its page's
|
|
77
|
+
* notFound(), forbidden(), unauthorized() or redirect(), which escaped the shell.
|
|
78
|
+
* Its value is the JSON of the headers to store: a redirect's own location, or
|
|
79
|
+
* `{}`. Only the prerender server sets it, from the special error the page
|
|
80
|
+
* recorded on its ctx, and it drops one that the response carries.
|
|
81
|
+
*/
|
|
82
|
+
const VINEXT_PRERENDER_SPECIAL_ERROR_HEADER = "x-vinext-prerender-special-error";
|
|
67
83
|
/** Internal marker persisted only inside metadata-route APP_ROUTE cache values. */
|
|
68
84
|
const VINEXT_METADATA_ROUTE_CACHE_HEADER = "x-vinext-metadata-route-cache";
|
|
69
85
|
/** Disabled-by-default client hint describing already-held App Router payload entries. */
|
|
@@ -161,9 +177,11 @@ const VINEXT_INTERNAL_HEADERS = [
|
|
|
161
177
|
VINEXT_CACHEABILITY_PROBE_HEADER.toLowerCase(),
|
|
162
178
|
VINEXT_CACHEABILITY_PROBE_ROUTE_HEADER.toLowerCase(),
|
|
163
179
|
VINEXT_EXPECTED_WORKER_VERSION_HEADER.toLowerCase(),
|
|
180
|
+
VINEXT_MW_CTX_HEADER,
|
|
164
181
|
VINEXT_PRERENDER_ROUTE_PARAMS_HEADER,
|
|
165
182
|
VINEXT_PRERENDER_SPECULATIVE_HEADER,
|
|
166
183
|
VINEXT_PRERENDER_CACHE_LIFE_HEADER,
|
|
184
|
+
VINEXT_PRERENDER_REWRITTEN_HEADER,
|
|
167
185
|
VINEXT_REVALIDATE_HOST_HEADER,
|
|
168
186
|
VINEXT_REVALIDATED_CACHE_TAG_HEADER,
|
|
169
187
|
VINEXT_TRACE_ERROR_HEADER.toLowerCase(),
|
|
@@ -171,4 +189,4 @@ const VINEXT_INTERNAL_HEADERS = [
|
|
|
171
189
|
VINEXT_TRACE_ROUTE_HEADER.toLowerCase()
|
|
172
190
|
];
|
|
173
191
|
//#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 };
|
|
192
|
+
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_SPECIAL_ERROR_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_SPECIAL_ERROR_STATUS_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
|
|
@@ -117,6 +117,22 @@ export declare const IMAGE_CONTENT_SECURITY_POLICY = "script-src 'none'; frame-s
|
|
|
117
117
|
* Returns false for SVG (unless dangerouslyAllowSVG is true), HTML, or any non-image type.
|
|
118
118
|
*/
|
|
119
119
|
export declare function isSafeImageContentType(contentType: string | null, dangerouslyAllowSVG?: boolean): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Cache state for a successful image response, sent as both `X-Nextjs-Cache`
|
|
122
|
+
* and `X-Vinext-Cache`.
|
|
123
|
+
*
|
|
124
|
+
* Next.js keeps optimized images in an image cache and labels each 200 with
|
|
125
|
+
* where the bytes came from: `MISS` when the optimizer ran for this request,
|
|
126
|
+
* `HIT` or `STALE` when the cache served them. vinext has no image cache on any
|
|
127
|
+
* runtime, so every successful response is transformed (or passed through) from
|
|
128
|
+
* the source for the request that receives it. Next.js behaves the same way
|
|
129
|
+
* when its image cache is disabled (`images.maximumDiskCacheSize: 0`): every
|
|
130
|
+
* 200 is a `MISS`. `HIT` and `STALE` need a cache of optimized images.
|
|
131
|
+
*
|
|
132
|
+
* Next.js sets the header after its ETag check, so a 304 and error responses
|
|
133
|
+
* go out without it. Only full image responses carry either header here too.
|
|
134
|
+
*/
|
|
135
|
+
export declare const IMAGE_RESPONSE_CACHE_STATE = "MISS";
|
|
120
136
|
/**
|
|
121
137
|
* Handlers for image optimization I/O operations.
|
|
122
138
|
* Workers provide these callbacks to adapt their specific bindings.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { badRequestResponse } from "./http-error-responses.js";
|
|
2
|
+
import { setCacheStateHeaders } from "./cache-headers.js";
|
|
2
3
|
//#region src/server/image-optimization.ts
|
|
3
4
|
/**
|
|
4
5
|
* Image optimization request handler.
|
|
@@ -182,11 +183,32 @@ function setImageSecurityHeaders(headers, config) {
|
|
|
182
183
|
headers.set("X-Content-Type-Options", "nosniff");
|
|
183
184
|
headers.set("Content-Disposition", config?.contentDispositionType === "attachment" ? "attachment" : "inline");
|
|
184
185
|
}
|
|
185
|
-
|
|
186
|
-
|
|
186
|
+
/**
|
|
187
|
+
* Cache state for a successful image response, sent as both `X-Nextjs-Cache`
|
|
188
|
+
* and `X-Vinext-Cache`.
|
|
189
|
+
*
|
|
190
|
+
* Next.js keeps optimized images in an image cache and labels each 200 with
|
|
191
|
+
* where the bytes came from: `MISS` when the optimizer ran for this request,
|
|
192
|
+
* `HIT` or `STALE` when the cache served them. vinext has no image cache on any
|
|
193
|
+
* runtime, so every successful response is transformed (or passed through) from
|
|
194
|
+
* the source for the request that receives it. Next.js behaves the same way
|
|
195
|
+
* when its image cache is disabled (`images.maximumDiskCacheSize: 0`): every
|
|
196
|
+
* 200 is a `MISS`. `HIT` and `STALE` need a cache of optimized images.
|
|
197
|
+
*
|
|
198
|
+
* Next.js sets the header after its ETag check, so a 304 and error responses
|
|
199
|
+
* go out without it. Only full image responses carry either header here too.
|
|
200
|
+
*/
|
|
201
|
+
const IMAGE_RESPONSE_CACHE_STATE = "MISS";
|
|
202
|
+
/** Headers shared by every successful image response, transformed or not. */
|
|
203
|
+
function setImageResponseHeaders(headers, config) {
|
|
187
204
|
headers.set("Cache-Control", IMAGE_CACHE_CONTROL);
|
|
188
205
|
headers.set("Vary", "Accept");
|
|
189
206
|
setImageSecurityHeaders(headers, config);
|
|
207
|
+
setCacheStateHeaders(headers, IMAGE_RESPONSE_CACHE_STATE);
|
|
208
|
+
}
|
|
209
|
+
function createPassthroughImageResponse(source, config) {
|
|
210
|
+
const headers = new Headers(source.headers);
|
|
211
|
+
setImageResponseHeaders(headers, config);
|
|
190
212
|
return new Response(source.body, {
|
|
191
213
|
status: 200,
|
|
192
214
|
headers
|
|
@@ -216,9 +238,7 @@ async function handleImageOptimization(request, handlers, allowedWidths, imageCo
|
|
|
216
238
|
quality
|
|
217
239
|
});
|
|
218
240
|
const headers = new Headers(transformed.headers);
|
|
219
|
-
headers
|
|
220
|
-
headers.set("Vary", "Accept");
|
|
221
|
-
setImageSecurityHeaders(headers, imageConfig);
|
|
241
|
+
setImageResponseHeaders(headers, imageConfig);
|
|
222
242
|
if (!isSafeImageContentType(headers.get("Content-Type"), imageConfig?.dangerouslyAllowSVG)) headers.set("Content-Type", format);
|
|
223
243
|
return new Response(transformed.body, {
|
|
224
244
|
status: 200,
|
|
@@ -287,4 +307,4 @@ function handleConfiguredImageOptimization(request, fetchAsset, allowedWidths, i
|
|
|
287
307
|
}, allowedWidths, imageConfig);
|
|
288
308
|
}
|
|
289
309
|
//#endregion
|
|
290
|
-
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, VINEXT_IMAGE_OPTIMIZATION_PATH, getImageOptimizer, handleConfiguredImageOptimization, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect, setImageOptimizer };
|
|
310
|
+
export { DEFAULT_DEVICE_SIZES, DEFAULT_IMAGE_SIZES, IMAGE_CACHE_CONTROL, IMAGE_CONTENT_SECURITY_POLICY, IMAGE_OPTIMIZATION_PATH, IMAGE_RESPONSE_CACHE_STATE, VINEXT_IMAGE_OPTIMIZATION_PATH, getImageOptimizer, handleConfiguredImageOptimization, handleImageOptimization, isImageOptimizationPath, isSafeImageContentType, negotiateImageFormat, parseImageParams, resolveDevImageRedirect, setImageOptimizer };
|
|
@@ -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,11 +1,12 @@
|
|
|
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";
|
|
4
|
+
import { isInterceptionMatchedUrlPath } from "./normalize-path.js";
|
|
3
5
|
import { reportRequestError } from "./instrumentation.js";
|
|
4
6
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
5
7
|
import { fnv1a64 } from "../utils/hash.js";
|
|
6
8
|
import { normalizeMountedSlotsHeader } from "./app-mounted-slots-header.js";
|
|
7
9
|
import { APP_RSC_RENDER_MODE_NAVIGATION, getRscRenderModeCacheVariant } from "./app-rsc-render-mode.js";
|
|
8
|
-
import { normalizeAppPageInterceptionProofPathname } from "./app-page-render-identity.js";
|
|
9
10
|
import { getRevalidateSecret, isOnDemandRevalidateRequest, isRevalidateSecret } from "./revalidation-request.js";
|
|
10
11
|
//#region src/server/isr-cache.ts
|
|
11
12
|
/**
|
|
@@ -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
|
*
|
|
@@ -178,7 +183,7 @@ function appIsrHtmlKey(pathname) {
|
|
|
178
183
|
return appIsrCacheKey(pathname, "html");
|
|
179
184
|
}
|
|
180
185
|
function normalizeInterceptionContextForCacheKey(interceptionContext) {
|
|
181
|
-
return
|
|
186
|
+
return isInterceptionMatchedUrlPath(interceptionContext) ? interceptionContext : null;
|
|
182
187
|
}
|
|
183
188
|
/**
|
|
184
189
|
* Build the ISR cache key for an RSC payload.
|
|
@@ -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 };
|