vinext 0.2.0 → 0.2.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/dist/build/css-url-assets.d.ts +3 -1
- package/dist/build/css-url-assets.js +18 -1
- package/dist/build/inject-pregenerated-paths.d.ts +3 -0
- package/dist/build/inject-pregenerated-paths.js +4 -1
- package/dist/build/prerender-server-entry.d.ts +1 -0
- package/dist/build/prerender-server-entry.js +49 -0
- package/dist/build/prerender-server-pool.d.ts +44 -0
- package/dist/build/prerender-server-pool.js +194 -0
- package/dist/build/prerender.js +86 -22
- package/dist/build/run-prerender.js +2 -1
- package/dist/check.d.ts +4 -6
- package/dist/check.js +8 -9
- package/dist/cli.js +1 -1
- package/dist/client/vinext-next-data.d.ts +4 -1
- package/dist/config/config-matchers.js +33 -11
- package/dist/config/next-config.d.ts +36 -6
- package/dist/config/next-config.js +16 -2
- package/dist/entries/app-browser-entry.js +5 -1
- package/dist/entries/app-rsc-entry.d.ts +3 -2
- package/dist/entries/app-rsc-entry.js +4 -0
- package/dist/entries/pages-client-entry.js +14 -3
- package/dist/entries/pages-server-entry.js +18 -4
- package/dist/index.js +320 -25
- package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.js +8 -1
- package/dist/packages/cloudflare/src/deploy.js +1 -5
- package/dist/packages/cloudflare/src/tpr.js +26 -5
- package/dist/plugins/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +1 -1
- package/dist/plugins/og-assets.js +2 -1
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
- package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
- package/dist/plugins/sass.d.ts +17 -1
- package/dist/plugins/sass.js +74 -1
- package/dist/plugins/styled-jsx.d.ts +16 -0
- package/dist/plugins/styled-jsx.js +149 -0
- package/dist/routing/app-route-graph.js +22 -16
- package/dist/routing/file-matcher.d.ts +8 -1
- package/dist/routing/file-matcher.js +15 -3
- package/dist/server/app-browser-entry.js +46 -14
- package/dist/server/app-browser-navigation-controller.js +1 -1
- package/dist/server/app-browser-server-action-client.js +5 -3
- package/dist/server/app-browser-state.d.ts +1 -0
- package/dist/server/app-browser-state.js +2 -2
- package/dist/server/app-browser-visible-commit.js +1 -1
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +3 -3
- package/dist/server/app-page-cache.js +23 -6
- package/dist/server/app-page-dispatch.d.ts +1 -0
- package/dist/server/app-page-dispatch.js +25 -8
- package/dist/server/app-page-element-builder.js +1 -0
- package/dist/server/app-page-execution.js +2 -1
- package/dist/server/app-page-render-identity.d.ts +1 -0
- package/dist/server/app-page-render-identity.js +2 -1
- package/dist/server/app-page-render.d.ts +2 -0
- package/dist/server/app-page-render.js +67 -16
- package/dist/server/app-page-response.d.ts +7 -0
- package/dist/server/app-page-response.js +16 -4
- package/dist/server/app-page-stream.d.ts +2 -1
- package/dist/server/app-page-stream.js +1 -1
- package/dist/server/app-route-handler-execution.js +1 -1
- package/dist/server/app-route-tree-prefetch.d.ts +43 -0
- package/dist/server/app-route-tree-prefetch.js +187 -0
- package/dist/server/app-router-entry.js +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +2 -1
- package/dist/server/app-rsc-cache-busting.js +9 -4
- package/dist/server/app-rsc-handler.d.ts +6 -0
- package/dist/server/app-rsc-handler.js +89 -11
- package/dist/server/app-rsc-render-mode.d.ts +3 -2
- package/dist/server/app-rsc-render-mode.js +4 -1
- package/dist/server/app-rsc-request-normalization.d.ts +3 -4
- package/dist/server/app-rsc-request-normalization.js +4 -5
- package/dist/server/app-server-action-execution.js +4 -3
- package/dist/server/app-ssr-entry.js +3 -3
- package/dist/server/cache-control.d.ts +3 -1
- package/dist/server/cache-control.js +13 -1
- package/dist/server/dev-server.d.ts +11 -1
- package/dist/server/dev-server.js +78 -20
- package/dist/server/headers.d.ts +6 -2
- package/dist/server/headers.js +11 -5
- package/dist/server/isr-cache.d.ts +2 -1
- package/dist/server/isr-cache.js +7 -3
- package/dist/server/pages-data-route.d.ts +4 -2
- package/dist/server/pages-data-route.js +18 -4
- package/dist/server/pages-dev-module-url.d.ts +2 -1
- package/dist/server/pages-dev-module-url.js +6 -3
- package/dist/server/pages-node-compat.d.ts +12 -1
- package/dist/server/pages-node-compat.js +50 -1
- package/dist/server/pages-page-data.d.ts +9 -0
- package/dist/server/pages-page-data.js +17 -9
- package/dist/server/pages-page-handler.js +19 -7
- package/dist/server/pages-page-response.d.ts +1 -0
- package/dist/server/pages-page-response.js +3 -2
- package/dist/server/pages-request-pipeline.d.ts +8 -6
- package/dist/server/pages-request-pipeline.js +30 -6
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prod-server.d.ts +4 -2
- package/dist/server/prod-server.js +38 -22
- package/dist/server/request-pipeline.js +1 -1
- package/dist/shims/cache-handler.js +8 -1
- package/dist/shims/cache.js +3 -0
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +77 -52
- package/dist/shims/form.d.ts +1 -1
- package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
- package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +2 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +34 -1
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +2 -1
- package/dist/shims/internal/pages-data-fetch-dedup.js +13 -2
- package/dist/shims/internal/pages-data-target.d.ts +8 -3
- package/dist/shims/internal/pages-data-target.js +9 -4
- package/dist/shims/link.d.ts +1 -1
- package/dist/shims/link.js +179 -42
- package/dist/shims/navigation.d.ts +15 -3
- package/dist/shims/navigation.js +202 -39
- package/dist/shims/navigation.react-server.js +1 -1
- package/dist/shims/request-context.js +18 -0
- package/dist/shims/router.js +31 -15
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -1
- package/dist/utils/middleware-request-headers.js +1 -1
- package/dist/utils/protocol-headers.d.ts +7 -1
- package/dist/utils/protocol-headers.js +7 -1
- package/dist/utils/vite-version.d.ts +2 -0
- package/dist/utils/vite-version.js +11 -1
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequestContext, runWithRequestContext } from "../shims/unified-request-context.js";
|
|
2
2
|
import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
3
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
|
-
import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER } from "../utils/protocol-headers.js";
|
|
4
|
+
import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
|
|
5
5
|
import { ACTION_REVALIDATED_HEADER } from "./headers.js";
|
|
6
6
|
import { isExternalUrl, matchRedirect, matchRewrite, preserveRedirectDestinationQuery, proxyExternalRequest, requestContextFromRequest, sanitizeDestination } from "../config/config-matchers.js";
|
|
7
7
|
import { notFoundResponse } from "./http-error-responses.js";
|
|
@@ -19,10 +19,11 @@ import "./app-page-response.js";
|
|
|
19
19
|
import { parseNextHttpErrorDigest } from "./next-error-digest.js";
|
|
20
20
|
import { matchPrerenderRouteParamsPayload, readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
21
21
|
import { getRenderedConcreteUrlPathsForRoute } from "./pregenerated-concrete-paths.js";
|
|
22
|
+
import { pickRootParams, setRootParams } from "../shims/root-params.js";
|
|
22
23
|
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage } from "./server-action-not-found.js";
|
|
23
24
|
import { buildPageCacheTags } from "./implicit-tags.js";
|
|
24
25
|
import { buildPostMwRequestContext } from "./app-post-middleware-context.js";
|
|
25
|
-
import {
|
|
26
|
+
import { createRouteTreePrefetchResponse, isRouteTreePrefetchRequest } from "./app-route-tree-prefetch.js";
|
|
26
27
|
import { flattenErrorCauses } from "../utils/error-cause.js";
|
|
27
28
|
import { finalizeAppRscResponse } from "./app-rsc-response-finalizer.js";
|
|
28
29
|
import { normalizeRscRequest } from "./app-rsc-request-normalization.js";
|
|
@@ -163,10 +164,10 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
163
164
|
headers: { Location: location }
|
|
164
165
|
});
|
|
165
166
|
}
|
|
166
|
-
const rscCacheBustingRedirect = await resolveInvalidRscCacheBustingRequest({
|
|
167
|
+
const rscCacheBustingRedirect = hadBasePath ? await resolveInvalidRscCacheBustingRequest({
|
|
167
168
|
isRscRequest,
|
|
168
169
|
request
|
|
169
|
-
});
|
|
170
|
+
}) : null;
|
|
170
171
|
if (rscCacheBustingRedirect) return rscCacheBustingRedirect;
|
|
171
172
|
const normalizedUserlandRequest = requestWithoutRscSuffix(request);
|
|
172
173
|
const userlandRequest = requestWithoutRscCacheBustingSearchParam(normalizedUserlandRequest);
|
|
@@ -200,6 +201,13 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
200
201
|
const scriptNonce = getScriptNonceFromHeaderSources(request.headers, middlewareContext.headers);
|
|
201
202
|
const postMiddlewareRequestContext = buildPostMwRequestContext(userlandRequest);
|
|
202
203
|
let filesystemRouteEligible = hadBasePath || didMiddlewareRewrite;
|
|
204
|
+
const validateClaimedOutsideBasePathRsc = async () => {
|
|
205
|
+
if (hadBasePath || !filesystemRouteEligible) return null;
|
|
206
|
+
return resolveInvalidRscCacheBustingRequest({
|
|
207
|
+
isRscRequest,
|
|
208
|
+
request
|
|
209
|
+
});
|
|
210
|
+
};
|
|
203
211
|
for (const rewrite of options.configRewrites.beforeFiles) {
|
|
204
212
|
const beforeFilesRewrite = await applyRewrite({
|
|
205
213
|
basePathState,
|
|
@@ -215,6 +223,51 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
215
223
|
filesystemRouteEligible = true;
|
|
216
224
|
}
|
|
217
225
|
}
|
|
226
|
+
const claimedRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
|
|
227
|
+
if (claimedRscCacheBustingRedirect) return claimedRscCacheBustingRedirect;
|
|
228
|
+
const actionId = request.headers.get("x-rsc-action") ?? request.headers.get("next-action");
|
|
229
|
+
const isPostRequest = request.method.toUpperCase() === "POST";
|
|
230
|
+
const contentType = request.headers.get("content-type") || "";
|
|
231
|
+
const isProgressiveActionRequest = isPostRequest && !actionId && contentType.startsWith("multipart/form-data");
|
|
232
|
+
let resolvedLateRewritesForAction = false;
|
|
233
|
+
if (!filesystemRouteEligible && (actionId || isProgressiveActionRequest)) {
|
|
234
|
+
let actionMatch = null;
|
|
235
|
+
for (const rewrite of options.configRewrites.afterFiles) {
|
|
236
|
+
const rewritten = await applyRewrite({
|
|
237
|
+
basePathState,
|
|
238
|
+
clearRequestContext: options.clearRequestContext,
|
|
239
|
+
request: normalizedUserlandRequest,
|
|
240
|
+
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
241
|
+
rewrites: [rewrite]
|
|
242
|
+
}, matchPathname(cleanPathname));
|
|
243
|
+
if (rewritten instanceof Response) return rewritten;
|
|
244
|
+
if (!rewritten) continue;
|
|
245
|
+
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
246
|
+
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
247
|
+
filesystemRouteEligible = true;
|
|
248
|
+
actionMatch = options.matchRoute(cleanPathname);
|
|
249
|
+
if (actionMatch) break;
|
|
250
|
+
}
|
|
251
|
+
if (!actionMatch) for (const rewrite of options.configRewrites.fallback) {
|
|
252
|
+
const rewritten = await applyRewrite({
|
|
253
|
+
basePathState,
|
|
254
|
+
clearRequestContext: options.clearRequestContext,
|
|
255
|
+
request: normalizedUserlandRequest,
|
|
256
|
+
requestContext: requestContextForResolvedUrl(postMiddlewareRequestContext, resolvedUrl, url),
|
|
257
|
+
rewrites: [rewrite]
|
|
258
|
+
}, matchPathname(cleanPathname));
|
|
259
|
+
if (rewritten instanceof Response) return rewritten;
|
|
260
|
+
if (!rewritten) continue;
|
|
261
|
+
resolvedUrl = mergeRewriteQuery(resolvedUrl, rewritten);
|
|
262
|
+
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
263
|
+
filesystemRouteEligible = true;
|
|
264
|
+
actionMatch = options.matchRoute(cleanPathname);
|
|
265
|
+
if (actionMatch) break;
|
|
266
|
+
}
|
|
267
|
+
resolvedLateRewritesForAction = filesystemRouteEligible;
|
|
268
|
+
}
|
|
269
|
+
const lateActionRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
|
|
270
|
+
if (lateActionRscCacheBustingRedirect) return lateActionRscCacheBustingRedirect;
|
|
218
271
|
if (filesystemRouteEligible && isImageOptimizationPath(cleanPathname)) {
|
|
219
272
|
const imageRedirect = resolveDevImageRedirect(url, [...options.imageConfig?.deviceSizes ?? DEFAULT_DEVICE_SIZES, ...options.imageConfig?.imageSizes ?? DEFAULT_IMAGE_SIZES], options.imageConfig?.qualities, { isDev: options.isDev });
|
|
220
273
|
if (!imageRedirect) return new Response("Invalid image optimization parameters", { status: 400 });
|
|
@@ -255,9 +308,18 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
255
308
|
});
|
|
256
309
|
const preActionMatch = filesystemRouteEligible ? options.matchRoute(cleanPathname) : null;
|
|
257
310
|
if (preActionMatch) setRootParams(pickRootParams(preActionMatch.params, preActionMatch.route.rootParamNames));
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
311
|
+
if (pagesDataRequest && didMiddlewareRewritePathname && preActionMatch) {
|
|
312
|
+
const headers = new Headers();
|
|
313
|
+
mergeMiddlewareResponseHeaders(headers, middlewareContext.headers);
|
|
314
|
+
headers.set("content-type", "application/json");
|
|
315
|
+
headers.set("x-nextjs-rewrite", resolvedUrl);
|
|
316
|
+
options.clearRequestContext();
|
|
317
|
+
return new Response("{}", { headers });
|
|
318
|
+
}
|
|
319
|
+
if (!filesystemRouteEligible && isPostRequest && actionId) {
|
|
320
|
+
options.clearRequestContext();
|
|
321
|
+
return notFoundResponse();
|
|
322
|
+
}
|
|
261
323
|
let progressiveActionResult = null;
|
|
262
324
|
if (filesystemRouteEligible && isPostRequest && contentType.startsWith("multipart/form-data") && !actionId) {
|
|
263
325
|
if (options.handleProgressiveActionRequest) progressiveActionResult = await options.handleProgressiveActionRequest({
|
|
@@ -322,7 +384,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
322
384
|
options.clearRequestContext();
|
|
323
385
|
return staticPagesFallbackResponse;
|
|
324
386
|
}
|
|
325
|
-
if (!match || match.route.isDynamic) for (const rewrite of options.configRewrites.afterFiles) {
|
|
387
|
+
if (!resolvedLateRewritesForAction && (!match || match.route.isDynamic)) for (const rewrite of options.configRewrites.afterFiles) {
|
|
326
388
|
const afterFilesRewrite = await applyRewrite({
|
|
327
389
|
basePathState,
|
|
328
390
|
clearRequestContext: options.clearRequestContext,
|
|
@@ -335,6 +397,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
335
397
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, afterFilesRewrite);
|
|
336
398
|
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
337
399
|
filesystemRouteEligible = true;
|
|
400
|
+
const claimedRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
|
|
401
|
+
if (claimedRscCacheBustingRedirect) return claimedRscCacheBustingRedirect;
|
|
338
402
|
match = options.matchRoute(cleanPathname);
|
|
339
403
|
const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
|
|
340
404
|
if (rewrittenStaticPagesResponse) {
|
|
@@ -353,7 +417,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
353
417
|
options.clearRequestContext();
|
|
354
418
|
return dynamicPagesFallbackResponse;
|
|
355
419
|
}
|
|
356
|
-
if (!match) for (const rewrite of options.configRewrites.fallback) {
|
|
420
|
+
if (!resolvedLateRewritesForAction && !match) for (const rewrite of options.configRewrites.fallback) {
|
|
357
421
|
const fallbackRewrite = await applyRewrite({
|
|
358
422
|
basePathState,
|
|
359
423
|
clearRequestContext: options.clearRequestContext,
|
|
@@ -366,6 +430,8 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
366
430
|
resolvedUrl = mergeRewriteQuery(resolvedUrl, fallbackRewrite);
|
|
367
431
|
cleanPathname = pathnameForResolvedUrl(resolvedUrl);
|
|
368
432
|
filesystemRouteEligible = true;
|
|
433
|
+
const claimedRscCacheBustingRedirect = await validateClaimedOutsideBasePathRsc();
|
|
434
|
+
if (claimedRscCacheBustingRedirect) return claimedRscCacheBustingRedirect;
|
|
369
435
|
match = options.matchRoute(cleanPathname);
|
|
370
436
|
const rewrittenStaticPagesResponse = await renderPagesForMatchKind("static");
|
|
371
437
|
if (rewrittenStaticPagesResponse) {
|
|
@@ -391,6 +457,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
391
457
|
const response = buildNextDataNotFoundResponse();
|
|
392
458
|
const headers = new Headers(response.headers);
|
|
393
459
|
headers.set("x-nextjs-matched-path", matchPathname(canonicalPathname));
|
|
460
|
+
if (resolvedUrl !== originalResolvedUrl) headers.set("x-nextjs-rewrite", resolvedUrl);
|
|
394
461
|
return new Response("{}", {
|
|
395
462
|
status: 200,
|
|
396
463
|
headers
|
|
@@ -418,11 +485,19 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
418
485
|
}
|
|
419
486
|
const { route, params } = match;
|
|
420
487
|
if (options.ensureRouteLoaded) await options.ensureRouteLoaded(route);
|
|
488
|
+
const resolvedSearchParams = getResolvedSearchParams();
|
|
489
|
+
if (isRouteTreePrefetchRequest(request) && !route.routeHandler) {
|
|
490
|
+
const response = await createRouteTreePrefetchResponse(route, {
|
|
491
|
+
buildId: options.buildId,
|
|
492
|
+
prefetchInlining: options.prefetchInlining
|
|
493
|
+
});
|
|
494
|
+
options.clearRequestContext();
|
|
495
|
+
return applyMiddlewareContextToResponse(response, middlewareContext);
|
|
496
|
+
}
|
|
421
497
|
const prerenderRouteParamsMatch = matchPrerenderRouteParamsPayload(readTrustedPrerenderRouteParams(request), route.pattern, params);
|
|
422
498
|
const prerenderRouteParams = prerenderRouteParamsMatch?.params ?? null;
|
|
423
499
|
const isPrerenderFallbackShell = prerenderRouteParamsMatch?.kind === "fallback-shell";
|
|
424
500
|
const renderParams = prerenderRouteParams ?? params;
|
|
425
|
-
const resolvedSearchParams = getResolvedSearchParams();
|
|
426
501
|
let runtimeFallbackShells = [];
|
|
427
502
|
if (options.createPprFallbackShells && request.method === "GET" && !isRscRequest && !isPrerenderFallbackShell && route.params) runtimeFallbackShells = options.createPprFallbackShells({
|
|
428
503
|
params: route.params,
|
|
@@ -476,6 +551,7 @@ async function handleAppRscRequest(options, request, preMiddlewareRequestContext
|
|
|
476
551
|
staticParamsValidationParams: prerenderRouteParams === null || isPrerenderFallbackShell ? void 0 : params,
|
|
477
552
|
rootParams,
|
|
478
553
|
request,
|
|
554
|
+
renderedPathAndSearch: resolvedUrl,
|
|
479
555
|
route,
|
|
480
556
|
scriptNonce,
|
|
481
557
|
searchParams: resolvedSearchParams,
|
|
@@ -525,14 +601,16 @@ function createAppRscHandler(options) {
|
|
|
525
601
|
const pagesDataInScope = !options.basePath || hasBasePath(pagesDataUrl.pathname, options.basePath);
|
|
526
602
|
if (pagesDataInScope) pagesDataUrl.pathname = stripBasePath(pagesDataUrl.pathname, options.basePath);
|
|
527
603
|
const pagesDataCandidate = pagesDataInScope ? cloneRequestWithUrl(rawRequest, pagesDataUrl.toString()) : null;
|
|
528
|
-
const pagesDataNormalization = options.renderPagesFallback && pagesDataCandidate ? normalizePagesDataRequest(pagesDataCandidate, options.buildId) : null;
|
|
604
|
+
const pagesDataNormalization = options.renderPagesFallback && pagesDataCandidate ? normalizePagesDataRequest(pagesDataCandidate, options.buildId, "", typeof options.runMiddleware === "function" && options.trailingSlash) : null;
|
|
529
605
|
if (pagesDataNormalization?.notFoundResponse) return pagesDataNormalization.notFoundResponse;
|
|
530
606
|
const isPagesDataRequest = pagesDataNormalization?.isDataReq === true;
|
|
531
607
|
const prerenderRouteParamsPayload = readTrustedPrerenderRouteParams(rawRequest);
|
|
608
|
+
const isTrustedSpeculativePrerender = process.env.VINEXT_PRERENDER === "1" && rawRequest.headers.get("x-vinext-prerender-secret") !== null && rawRequest.headers.get("x-vinext-prerender-speculative") === "1";
|
|
532
609
|
const filteredHeaders = filterInternalHeaders(rawRequest.headers);
|
|
533
610
|
if (mwCtx !== null) filteredHeaders.set(VINEXT_MW_CTX_HEADER, mwCtx);
|
|
534
611
|
const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParamsPayload);
|
|
535
612
|
if (prerenderRouteParamsHeader !== null) filteredHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
613
|
+
if (isTrustedSpeculativePrerender) filteredHeaders.set(VINEXT_PRERENDER_SPECULATIVE_HEADER, "1");
|
|
536
614
|
let appRequest = rawRequest;
|
|
537
615
|
if (pagesDataNormalization?.isDataReq) {
|
|
538
616
|
const appRequestUrl = new URL(pagesDataNormalization.request.url);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
//#region src/server/app-rsc-render-mode.d.ts
|
|
2
|
-
type AppRscRenderMode = "navigation" | "prefetch-loading-shell" | "refresh-preserve-ui" | "action-rerender-preserve-ui";
|
|
2
|
+
type AppRscRenderMode = "navigation" | "prefetch-dynamic-shell" | "prefetch-loading-shell" | "refresh-preserve-ui" | "action-rerender-preserve-ui";
|
|
3
3
|
declare const APP_RSC_RENDER_MODE_NAVIGATION = "navigation";
|
|
4
|
+
declare const APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL = "prefetch-dynamic-shell";
|
|
4
5
|
declare const APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL = "prefetch-loading-shell";
|
|
5
6
|
declare const APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI = "refresh-preserve-ui";
|
|
6
7
|
declare const APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI = "action-rerender-preserve-ui";
|
|
@@ -8,4 +9,4 @@ declare function shouldSuppressLoadingBoundaries(mode: AppRscRenderMode): boolea
|
|
|
8
9
|
declare function getRscRenderModeCacheVariant(mode: AppRscRenderMode): string | null;
|
|
9
10
|
declare function parseAppRscRenderMode(value: string | null): AppRscRenderMode;
|
|
10
11
|
//#endregion
|
|
11
|
-
export { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI, APP_RSC_RENDER_MODE_NAVIGATION, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI, AppRscRenderMode, getRscRenderModeCacheVariant, parseAppRscRenderMode, shouldSuppressLoadingBoundaries };
|
|
12
|
+
export { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI, APP_RSC_RENDER_MODE_NAVIGATION, APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI, AppRscRenderMode, getRscRenderModeCacheVariant, parseAppRscRenderMode, shouldSuppressLoadingBoundaries };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
//#region src/server/app-rsc-render-mode.ts
|
|
2
2
|
const APP_RSC_RENDER_MODE_NAVIGATION = "navigation";
|
|
3
|
+
const APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL = "prefetch-dynamic-shell";
|
|
3
4
|
const APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL = "prefetch-loading-shell";
|
|
4
5
|
const APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI = "refresh-preserve-ui";
|
|
5
6
|
const APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI = "action-rerender-preserve-ui";
|
|
@@ -10,11 +11,13 @@ function shouldUsePreserveUiCacheVariant(mode) {
|
|
|
10
11
|
return shouldSuppressLoadingBoundaries(mode);
|
|
11
12
|
}
|
|
12
13
|
function getRscRenderModeCacheVariant(mode) {
|
|
14
|
+
if (mode === "prefetch-dynamic-shell") return "prefetch-dynamic-shell";
|
|
13
15
|
if (mode === "prefetch-loading-shell") return "prefetch-loading-shell";
|
|
14
16
|
return shouldUsePreserveUiCacheVariant(mode) ? "preserve-ui" : null;
|
|
15
17
|
}
|
|
16
18
|
function parseAppRscRenderMode(value) {
|
|
17
19
|
switch (value) {
|
|
20
|
+
case APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL: return APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL;
|
|
18
21
|
case APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL: return APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL;
|
|
19
22
|
case APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI: return APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI;
|
|
20
23
|
case APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI: return APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI;
|
|
@@ -22,4 +25,4 @@ function parseAppRscRenderMode(value) {
|
|
|
22
25
|
}
|
|
23
26
|
}
|
|
24
27
|
//#endregion
|
|
25
|
-
export { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI, APP_RSC_RENDER_MODE_NAVIGATION, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI, getRscRenderModeCacheVariant, parseAppRscRenderMode, shouldSuppressLoadingBoundaries };
|
|
28
|
+
export { APP_RSC_RENDER_MODE_ACTION_RERENDER_PRESERVE_UI, APP_RSC_RENDER_MODE_NAVIGATION, APP_RSC_RENDER_MODE_PREFETCH_DYNAMIC_SHELL, APP_RSC_RENDER_MODE_PREFETCH_LOADING_SHELL, APP_RSC_RENDER_MODE_REFRESH_PRESERVE_UI, getRscRenderModeCacheVariant, parseAppRscRenderMode, shouldSuppressLoadingBoundaries };
|
|
@@ -31,10 +31,9 @@ type NormalizedRscRequest = {
|
|
|
31
31
|
* 4. Collapse double-slashes, resolve `.` and `..` segments (normalizePath)
|
|
32
32
|
* 5. basePath check + strip — 404 when pathname lacks the basePath prefix.
|
|
33
33
|
* `/__vinext/` bypasses this for internal prerender endpoints.
|
|
34
|
-
* 6. RSC detection: `.rsc` suffix
|
|
35
|
-
* `_rsc` cache-busting query
|
|
36
|
-
*
|
|
37
|
-
* store Flight responses under HTML URLs.
|
|
34
|
+
* 6. RSC detection: `.rsc` suffix or Next-style `RSC: 1`. The internal
|
|
35
|
+
* `_rsc` cache-busting query is validated separately so full-route Flight
|
|
36
|
+
* responses do not share the canonical HTML URL in caches that ignore Vary.
|
|
38
37
|
* 7. cleanPathname — pathname with `.rsc` suffix stripped
|
|
39
38
|
* 8. Sanitize X-Vinext-Interception-Context — strip null bytes (header injection)
|
|
40
39
|
* 9. Normalize x-vinext-mounted-slots — dedup and sort for canonical cache keys
|
|
@@ -27,10 +27,9 @@ import { normalizeInterceptionContextHeader } from "./app-interception-context-h
|
|
|
27
27
|
* 4. Collapse double-slashes, resolve `.` and `..` segments (normalizePath)
|
|
28
28
|
* 5. basePath check + strip — 404 when pathname lacks the basePath prefix.
|
|
29
29
|
* `/__vinext/` bypasses this for internal prerender endpoints.
|
|
30
|
-
* 6. RSC detection: `.rsc` suffix
|
|
31
|
-
* `_rsc` cache-busting query
|
|
32
|
-
*
|
|
33
|
-
* store Flight responses under HTML URLs.
|
|
30
|
+
* 6. RSC detection: `.rsc` suffix or Next-style `RSC: 1`. The internal
|
|
31
|
+
* `_rsc` cache-busting query is validated separately so full-route Flight
|
|
32
|
+
* responses do not share the canonical HTML URL in caches that ignore Vary.
|
|
34
33
|
* 7. cleanPathname — pathname with `.rsc` suffix stripped
|
|
35
34
|
* 8. Sanitize X-Vinext-Interception-Context — strip null bytes (header injection)
|
|
36
35
|
* 9. Normalize x-vinext-mounted-slots — dedup and sort for canonical cache keys
|
|
@@ -57,7 +56,7 @@ function normalizeRscRequest(request, basePath, allowOutsideBasePath = false) {
|
|
|
57
56
|
if (!hadBasePath && !pathname.startsWith("/__vinext/") && !allowOutsideBasePath) return notFoundResponse();
|
|
58
57
|
if (hadBasePath) pathname = stripBasePath(pathname, basePath);
|
|
59
58
|
}
|
|
60
|
-
const isRscRequest = pathname.endsWith(".rsc") || request.headers.get("RSC") === "1"
|
|
59
|
+
const isRscRequest = pathname.endsWith(".rsc") || request.headers.get("RSC") === "1";
|
|
61
60
|
const cleanPathname = stripRscSuffix(pathname);
|
|
62
61
|
const interceptionContextHeader = normalizeInterceptionContextHeader(request.headers.get(VINEXT_INTERCEPTION_CONTEXT_HEADER));
|
|
63
62
|
const mountedSlotsHeader = normalizeMountedSlotsHeader(request.headers.get(VINEXT_MOUNTED_SLOTS_HEADER));
|
|
@@ -13,13 +13,13 @@ import { VINEXT_RSC_CONTENT_TYPE, VINEXT_RSC_VARY_HEADER, applyRscCompatibilityI
|
|
|
13
13
|
import { mergeMiddlewareResponseHeaders } from "./middleware-response-headers.js";
|
|
14
14
|
import { applyEdgeRuntimeHeader } from "./app-page-response.js";
|
|
15
15
|
import { getNextErrorDigest, parseNextHttpErrorDigest, parseNextRedirectDigest } from "./next-error-digest.js";
|
|
16
|
+
import { createRootParamsUsageController, pickRootParams, runWithRootParamsScope, runWithRootParamsUsage } from "../shims/root-params.js";
|
|
16
17
|
import { createServerActionNotFoundResponse, getServerActionNotFoundMessage, isServerActionNotFoundError } from "./server-action-not-found.js";
|
|
17
18
|
import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
|
|
18
19
|
import "./app-page-stream.js";
|
|
19
20
|
import { buildAppPageTags } from "./implicit-tags.js";
|
|
20
21
|
import { resolveAppPageNavigationParams } from "./app-page-element-builder.js";
|
|
21
22
|
import { resolveAppPageActionRerenderTarget } from "./app-page-request.js";
|
|
22
|
-
import { createRootParamsUsageController, pickRootParams, runWithRootParamsScope, runWithRootParamsUsage } from "../shims/root-params.js";
|
|
23
23
|
import { getSetCookieName } from "./cookie-utils.js";
|
|
24
24
|
import { createStaticGenerationHeadersContext } from "./app-static-generation.js";
|
|
25
25
|
//#region src/server/app-server-action-execution.ts
|
|
@@ -737,6 +737,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
737
737
|
const match = options.matchRoute(options.cleanPathname);
|
|
738
738
|
let element;
|
|
739
739
|
let errorPattern = match ? match.route.pattern : options.cleanPathname;
|
|
740
|
+
const actionRerenderIsRscRequest = true;
|
|
740
741
|
if (match) {
|
|
741
742
|
const { route: actionRoute, params: actionParams } = match;
|
|
742
743
|
const actionRerenderTarget = await resolveAppPageActionRerenderTarget({
|
|
@@ -746,7 +747,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
746
747
|
findIntercept: options.findIntercept,
|
|
747
748
|
getRouteParamNames: options.getRouteParamNames,
|
|
748
749
|
getSourceRoute: options.getSourceRoute,
|
|
749
|
-
isRscRequest:
|
|
750
|
+
isRscRequest: actionRerenderIsRscRequest,
|
|
750
751
|
toInterceptOpts: options.toInterceptOpts
|
|
751
752
|
});
|
|
752
753
|
const resolvedActionNavigationParams = resolveAppPageNavigationParams(actionRerenderTarget.route, actionRerenderTarget.navigationParams, options.cleanPathname, actionRerenderTarget.interceptOpts);
|
|
@@ -771,7 +772,7 @@ async function handleServerActionRscRequest(options) {
|
|
|
771
772
|
const buildActionRerenderElement = () => options.buildPageElement({
|
|
772
773
|
cleanPathname: options.cleanPathname,
|
|
773
774
|
interceptOpts: actionRerenderTarget.interceptOpts,
|
|
774
|
-
isRscRequest:
|
|
775
|
+
isRscRequest: actionRerenderIsRscRequest,
|
|
775
776
|
mountedSlotsHeader: options.mountedSlotsHeader,
|
|
776
777
|
params: actionRerenderTarget.params,
|
|
777
778
|
request: options.request,
|
|
@@ -12,17 +12,17 @@ import { runWithNavigationContext } from "../shims/navigation-state.js";
|
|
|
12
12
|
import { withScriptNonce } from "../shims/script-nonce-context.js";
|
|
13
13
|
import { createInlineScriptTag, createNonceAttribute, escapeHtmlAttr, safeJsonStringify } from "./html.js";
|
|
14
14
|
import { getClientTraceMetadataHTML } from "./client-trace-metadata.js";
|
|
15
|
+
import { setPagesClientAssets } from "./pages-client-assets.js";
|
|
15
16
|
import DefaultGlobalError from "../shims/default-global-error.js";
|
|
16
17
|
import { BfcacheStateKeyMapContext, ElementsContext, Slot } from "../shims/slot.js";
|
|
17
18
|
import { createSsrErrorMetaRenderer } from "./app-ssr-error-meta.js";
|
|
18
19
|
import { createNavigationRuntimeRscMetadataScript, createRscEmbedTransform, createTickBufferedTransform } from "./app-ssr-stream.js";
|
|
19
|
-
import {
|
|
20
|
+
import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
|
|
21
|
+
import { runWithRootParamsScope } from "../shims/root-params.js";
|
|
20
22
|
import { createInitialBfcacheMaps } from "./app-bfcache-identity.js";
|
|
21
23
|
import { RSC_FORM_STATE_GLOBAL } from "./app-browser-hydration.js";
|
|
22
24
|
import { createClientReferencePreloader } from "./app-client-reference-preloader.js";
|
|
23
25
|
import { deferUntilStreamConsumed } from "./defer-until-stream-consumed.js";
|
|
24
|
-
import { runWithRootParamsScope } from "../shims/root-params.js";
|
|
25
|
-
import { BeforeInteractiveContext } from "../shims/before-interactive-context.js";
|
|
26
26
|
import { renderBeforeInteractiveInlineScripts } from "./before-interactive-head.js";
|
|
27
27
|
import { createInitialDevServerErrorScript } from "./dev-initial-server-error.js";
|
|
28
28
|
import { ssrAppRouterInstance } from "./app-ssr-router-instance.js";
|
|
@@ -2,8 +2,10 @@ import { CdnCacheableHeaderInput } from "../shims/cdn-cache.js";
|
|
|
2
2
|
|
|
3
3
|
//#region src/server/cache-control.d.ts
|
|
4
4
|
declare const NEVER_CACHE_CONTROL = "private, no-cache, no-store, max-age=0, must-revalidate";
|
|
5
|
+
declare const BROWSER_REVALIDATE_CACHE_CONTROL = "public, max-age=0, must-revalidate";
|
|
5
6
|
declare const STATIC_CACHE_CONTROL = "s-maxage=31536000, stale-while-revalidate";
|
|
6
7
|
declare const NO_STORE_CACHE_CONTROL = "no-store, must-revalidate";
|
|
8
|
+
declare function shouldUseNextDeployCacheControl(): boolean;
|
|
7
9
|
/**
|
|
8
10
|
* Route a cacheable response's headers through the active CDN cache adapter and
|
|
9
11
|
* apply the result to `headers`. The default adapter yields a single
|
|
@@ -34,4 +36,4 @@ declare function buildRevalidateCacheControl(revalidateSeconds: number, expireSe
|
|
|
34
36
|
*/
|
|
35
37
|
declare function buildCachedRevalidateCacheControl(cacheState: "HIT" | "STALE", revalidateSeconds: number, expireSeconds?: number): string;
|
|
36
38
|
//#endregion
|
|
37
|
-
export { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, buildCachedRevalidateCacheControl, buildRevalidateCacheControl };
|
|
39
|
+
export { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, buildCachedRevalidateCacheControl, buildRevalidateCacheControl, shouldUseNextDeployCacheControl };
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
2
2
|
//#region src/server/cache-control.ts
|
|
3
3
|
const NEVER_CACHE_CONTROL = "private, no-cache, no-store, max-age=0, must-revalidate";
|
|
4
|
+
const BROWSER_REVALIDATE_CACHE_CONTROL = "public, max-age=0, must-revalidate";
|
|
4
5
|
const STATIC_CACHE_CONTROL = "s-maxage=31536000, stale-while-revalidate";
|
|
5
6
|
const STALE_REVALIDATE_CACHE_CONTROL = "s-maxage=0, stale-while-revalidate";
|
|
6
7
|
const NO_STORE_CACHE_CONTROL = "no-store, must-revalidate";
|
|
8
|
+
const SHARED_CACHE_DIRECTIVE_RE = /(?:^|,)\s*s-maxage\s*=/i;
|
|
9
|
+
function shouldUseNextDeployCacheControl() {
|
|
10
|
+
return process.env.VINEXT_NEXT_DEPLOY_CACHE_CONTROL === "1";
|
|
11
|
+
}
|
|
12
|
+
function isSharedCacheControl(cacheControl) {
|
|
13
|
+
return SHARED_CACHE_DIRECTIVE_RE.test(cacheControl);
|
|
14
|
+
}
|
|
7
15
|
/**
|
|
8
16
|
* Route a cacheable response's headers through the active CDN cache adapter and
|
|
9
17
|
* apply the result to `headers`. The default adapter yields a single
|
|
@@ -17,6 +25,10 @@ const NO_STORE_CACHE_CONTROL = "no-store, must-revalidate";
|
|
|
17
25
|
*/
|
|
18
26
|
function applyCdnResponseHeaders(headers, input) {
|
|
19
27
|
headers.delete("Cache-Control");
|
|
28
|
+
if (shouldUseNextDeployCacheControl() && isSharedCacheControl(input.cacheControl)) {
|
|
29
|
+
headers.set("Cache-Control", BROWSER_REVALIDATE_CACHE_CONTROL);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
20
32
|
const map = getCdnCacheAdapter().buildResponseHeaders(input);
|
|
21
33
|
for (const [name, value] of Object.entries(map)) {
|
|
22
34
|
if (value === null) {
|
|
@@ -53,4 +65,4 @@ function buildCachedRevalidateCacheControl(cacheState, revalidateSeconds, expire
|
|
|
53
65
|
return buildRevalidateCacheControl(revalidateSeconds, expireSeconds);
|
|
54
66
|
}
|
|
55
67
|
//#endregion
|
|
56
|
-
export { NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, buildCachedRevalidateCacheControl, buildRevalidateCacheControl };
|
|
68
|
+
export { BROWSER_REVALIDATE_CACHE_CONTROL, NEVER_CACHE_CONTROL, NO_STORE_CACHE_CONTROL, STATIC_CACHE_CONTROL, applyCdnResponseHeaders, buildCachedRevalidateCacheControl, buildRevalidateCacheControl, shouldUseNextDeployCacheControl };
|
|
@@ -43,7 +43,17 @@ declare function createSSRHandler(server: ViteDevServer, runner: ModuleImporter,
|
|
|
43
43
|
* `next.config`. When undefined or empty, no meta tags are emitted.
|
|
44
44
|
*/
|
|
45
45
|
|
|
46
|
-
clientTraceMetadata?: readonly string[], htmlLimitedBots?: string
|
|
46
|
+
clientTraceMetadata?: readonly string[], htmlLimitedBots?: string,
|
|
47
|
+
/**
|
|
48
|
+
* Whether `reactStrictMode: true` is set in next.config. When true, the dev
|
|
49
|
+
* hydration script sets `window.__VINEXT_REACT_STRICT_MODE__` so
|
|
50
|
+
* `wrapWithRouterContext` wraps the tree in `<React.StrictMode>` on the
|
|
51
|
+
* initial hydration and every navigation. Pages Router default is OFF
|
|
52
|
+
* (Next.js: `reactStrictMode === null ? false`), so callers pass
|
|
53
|
+
* `nextConfig?.reactStrictMode === true`.
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
reactStrictMode?: boolean): (req: IncomingMessage, res: ServerResponse, url: string, /** Status code override — propagated from middleware rewrite status. */
|
|
47
57
|
|
|
48
58
|
statusCode?: number,
|
|
49
59
|
/**
|