vinext 0.1.2 → 0.1.4
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/client-build-config.d.ts +11 -2
- package/dist/build/client-build-config.js +17 -6
- package/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +42 -12
- package/dist/build/run-prerender.d.ts +10 -2
- package/dist/build/run-prerender.js +15 -1
- package/dist/client/app-nav-failure-handler.d.ts +8 -0
- package/dist/client/app-nav-failure-handler.js +44 -0
- package/dist/client/pages-router-link-navigation.d.ts +33 -7
- package/dist/client/pages-router-link-navigation.js +32 -2
- package/dist/client/vinext-next-data.d.ts +18 -1
- package/dist/client/vinext-next-data.js +2 -0
- package/dist/client/window-next.d.ts +2 -1
- package/dist/client/window-next.js +12 -1
- package/dist/cloudflare/src/cache/cdn-adapter.runtime.js +6 -1
- package/dist/config/config-matchers.d.ts +11 -1
- package/dist/config/config-matchers.js +87 -16
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/config/tsconfig-paths.js +14 -1
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +200 -112
- package/dist/entries/app-browser-entry.d.ts +9 -3
- package/dist/entries/app-browser-entry.js +21 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +65 -5
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/app-ssr-entry.js +1 -1
- package/dist/entries/pages-client-entry.js +66 -20
- package/dist/entries/pages-server-entry.js +47 -31
- package/dist/index.js +417 -102
- package/dist/plugins/dynamic-preload-metadata.js +2 -4
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- package/dist/plugins/fonts.js +5 -4
- package/dist/plugins/optimize-imports.d.ts +2 -1
- package/dist/plugins/optimize-imports.js +11 -9
- package/dist/plugins/postcss.js +7 -7
- package/dist/plugins/strip-server-exports.d.ts +9 -7
- package/dist/plugins/strip-server-exports.js +493 -46
- package/dist/plugins/typeof-window.d.ts +14 -0
- package/dist/plugins/typeof-window.js +150 -0
- package/dist/routing/app-route-graph.d.ts +2 -1
- package/dist/routing/app-route-graph.js +46 -16
- package/dist/routing/file-matcher.d.ts +10 -1
- package/dist/routing/file-matcher.js +22 -1
- package/dist/routing/pages-router.js +3 -3
- package/dist/routing/utils.d.ts +35 -6
- package/dist/routing/utils.js +59 -7
- package/dist/server/api-handler.d.ts +6 -1
- package/dist/server/api-handler.js +21 -15
- package/dist/server/app-browser-action-result.d.ts +19 -6
- package/dist/server/app-browser-action-result.js +20 -11
- package/dist/server/app-browser-entry.js +175 -91
- package/dist/server/app-browser-error.d.ts +10 -6
- package/dist/server/app-browser-error.js +43 -8
- package/dist/server/app-browser-hydration.d.ts +2 -0
- package/dist/server/app-browser-hydration.js +1 -0
- package/dist/server/app-browser-navigation-controller.d.ts +5 -3
- package/dist/server/app-browser-navigation-controller.js +23 -2
- package/dist/server/app-browser-server-action-navigation.d.ts +6 -0
- package/dist/server/app-browser-server-action-navigation.js +9 -0
- package/dist/server/app-browser-state.d.ts +1 -1
- package/dist/server/app-browser-state.js +19 -11
- package/dist/server/app-browser-stream.js +86 -43
- package/dist/server/app-browser-visible-commit.d.ts +1 -1
- package/dist/server/app-elements-wire.d.ts +6 -1
- package/dist/server/app-elements-wire.js +14 -4
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +2 -2
- package/dist/server/app-fallback-renderer.d.ts +1 -0
- package/dist/server/app-fallback-renderer.js +3 -1
- package/dist/server/app-optimistic-routing.js +2 -2
- package/dist/server/app-page-boundary-render.d.ts +1 -0
- package/dist/server/app-page-boundary-render.js +27 -14
- package/dist/server/app-page-cache-render.d.ts +53 -0
- package/dist/server/app-page-cache-render.js +91 -0
- package/dist/server/app-page-cache.d.ts +16 -2
- package/dist/server/app-page-cache.js +62 -1
- package/dist/server/app-page-dispatch.d.ts +26 -0
- package/dist/server/app-page-dispatch.js +149 -92
- package/dist/server/app-page-element-builder.d.ts +1 -0
- package/dist/server/app-page-element-builder.js +5 -2
- package/dist/server/app-page-execution.d.ts +6 -1
- package/dist/server/app-page-execution.js +21 -1
- package/dist/server/app-page-probe.d.ts +1 -0
- package/dist/server/app-page-probe.js +4 -0
- package/dist/server/app-page-render-observation.d.ts +3 -1
- package/dist/server/app-page-render-observation.js +17 -1
- package/dist/server/app-page-render.d.ts +12 -1
- package/dist/server/app-page-render.js +42 -4
- package/dist/server/app-page-request.d.ts +2 -0
- package/dist/server/app-page-request.js +2 -1
- package/dist/server/app-page-route-wiring.d.ts +3 -1
- package/dist/server/app-page-route-wiring.js +14 -5
- package/dist/server/app-page-stream.d.ts +15 -3
- package/dist/server/app-page-stream.js +11 -5
- package/dist/server/app-pages-bridge.d.ts +23 -1
- package/dist/server/app-pages-bridge.js +26 -17
- package/dist/server/app-ppr-fallback-shell-render.d.ts +17 -0
- package/dist/server/app-ppr-fallback-shell-render.js +26 -0
- package/dist/server/app-ppr-fallback-shell.d.ts +13 -1
- package/dist/server/app-ppr-fallback-shell.js +8 -1
- package/dist/server/app-route-handler-dispatch.js +9 -2
- package/dist/server/app-route-handler-policy.d.ts +1 -0
- package/dist/server/app-router-entry.js +5 -0
- package/dist/server/app-rsc-cache-busting.js +2 -0
- package/dist/server/app-rsc-handler.d.ts +28 -0
- package/dist/server/app-rsc-handler.js +195 -59
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +8 -2
- package/dist/server/app-segment-config.d.ts +9 -1
- package/dist/server/app-segment-config.js +12 -3
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +47 -15
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +84 -39
- package/dist/server/before-interactive-head.d.ts +17 -0
- package/dist/server/before-interactive-head.js +35 -0
- package/dist/server/cache-control.js +4 -0
- package/dist/server/csp.js +1 -4
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +321 -83
- package/dist/server/hybrid-route-priority.d.ts +22 -0
- package/dist/server/hybrid-route-priority.js +33 -0
- package/dist/server/image-optimization.d.ts +18 -9
- package/dist/server/image-optimization.js +37 -23
- package/dist/server/implicit-tags.d.ts +2 -1
- package/dist/server/implicit-tags.js +4 -1
- package/dist/server/middleware-matcher.js +12 -3
- package/dist/server/middleware-runtime.d.ts +3 -4
- package/dist/server/middleware-runtime.js +2 -0
- package/dist/server/navigation-planner.d.ts +135 -41
- package/dist/server/navigation-planner.js +138 -0
- package/dist/server/navigation-trace.d.ts +9 -1
- package/dist/server/navigation-trace.js +9 -1
- package/dist/server/operation-token.d.ts +40 -0
- package/dist/server/operation-token.js +85 -0
- package/dist/server/pages-api-route.d.ts +6 -0
- package/dist/server/pages-api-route.js +13 -2
- package/dist/server/pages-asset-tags.d.ts +2 -1
- package/dist/server/pages-asset-tags.js +6 -2
- package/dist/server/pages-data-route.d.ts +9 -2
- package/dist/server/pages-data-route.js +18 -6
- package/dist/server/pages-dev-module-url.d.ts +4 -0
- package/dist/server/pages-dev-module-url.js +15 -0
- package/dist/server/pages-document-initial-props.d.ts +4 -15
- package/dist/server/pages-document-initial-props.js +27 -56
- package/dist/server/pages-get-initial-props.d.ts +54 -4
- package/dist/server/pages-get-initial-props.js +43 -1
- package/dist/server/pages-i18n.js +2 -2
- package/dist/server/pages-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +207 -34
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +62 -23
- package/dist/server/pages-page-response.d.ts +4 -1
- package/dist/server/pages-page-response.js +11 -8
- package/dist/server/pages-readiness.js +1 -1
- package/dist/server/pages-request-pipeline.d.ts +8 -7
- package/dist/server/pages-request-pipeline.js +126 -47
- package/dist/server/pregenerated-concrete-paths.d.ts +1 -17
- package/dist/server/pregenerated-concrete-paths.js +2 -19
- package/dist/server/prerender-manifest.d.ts +33 -0
- package/dist/server/prerender-manifest.js +54 -0
- package/dist/server/prerender-route-params.d.ts +1 -2
- package/dist/server/prod-server.d.ts +3 -1
- package/dist/server/prod-server.js +50 -13
- package/dist/server/request-pipeline.d.ts +3 -15
- package/dist/server/request-pipeline.js +58 -47
- package/dist/server/rsc-stream-hints.d.ts +5 -1
- package/dist/server/rsc-stream-hints.js +6 -1
- package/dist/server/seed-cache.js +10 -18
- package/dist/server/static-file-cache.js +16 -4
- package/dist/shims/app-router-scroll-state.d.ts +3 -1
- package/dist/shims/app-router-scroll-state.js +14 -2
- package/dist/shims/app-router-scroll.d.ts +3 -0
- package/dist/shims/app-router-scroll.js +28 -18
- package/dist/shims/before-interactive-context.d.ts +14 -3
- package/dist/shims/cache-runtime.js +3 -2
- package/dist/shims/cache.d.ts +1 -0
- package/dist/shims/cache.js +1 -1
- package/dist/shims/cdn-cache.d.ts +5 -5
- package/dist/shims/document.d.ts +15 -20
- package/dist/shims/document.js +5 -8
- package/dist/shims/dynamic-preload-chunks.js +6 -4
- package/dist/shims/error-boundary.d.ts +2 -0
- package/dist/shims/error-boundary.js +7 -0
- package/dist/shims/error.js +3 -2
- package/dist/shims/error.react-server.d.ts +9 -0
- package/dist/shims/error.react-server.js +6 -0
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +45 -20
- package/dist/shims/hash-scroll.js +6 -1
- package/dist/shims/headers.js +29 -4
- package/dist/shims/image.js +9 -2
- package/dist/shims/internal/als-registry.js +28 -1
- package/dist/shims/internal/app-route-detection.js +8 -17
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +31 -0
- package/dist/shims/internal/hybrid-client-route-owner.js +143 -0
- package/dist/shims/internal/navigation-untracked.d.ts +35 -0
- package/dist/shims/internal/navigation-untracked.js +55 -0
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +6 -7
- package/dist/shims/internal/pages-data-fetch-dedup.js +67 -14
- package/dist/shims/internal/pages-data-target.d.ts +7 -2
- package/dist/shims/internal/pages-data-target.js +17 -8
- package/dist/shims/internal/pages-router-accessor.d.ts +19 -0
- package/dist/shims/internal/pages-router-accessor.js +13 -0
- package/dist/shims/internal/router-context.d.ts +2 -1
- package/dist/shims/internal/router-context.js +3 -1
- package/dist/shims/link.js +47 -19
- package/dist/shims/metadata.js +4 -4
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +63 -31
- package/dist/shims/ppr-fallback-shell.d.ts +5 -1
- package/dist/shims/ppr-fallback-shell.js +28 -7
- package/dist/shims/router.d.ts +18 -3
- package/dist/shims/router.js +512 -142
- package/dist/shims/script.js +8 -4
- package/dist/shims/server.d.ts +16 -1
- package/dist/shims/server.js +44 -12
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/built-asset-url.d.ts +4 -0
- package/dist/utils/built-asset-url.js +11 -0
- package/dist/utils/commonjs-loader.d.ts +16 -0
- package/dist/utils/commonjs-loader.js +100 -0
- package/dist/utils/deployment-id.d.ts +8 -0
- package/dist/utils/deployment-id.js +22 -0
- package/dist/utils/has-trailing-comma.d.ts +24 -0
- package/dist/utils/has-trailing-comma.js +62 -0
- package/dist/utils/html-limited-bots.d.ts +18 -1
- package/dist/utils/html-limited-bots.js +23 -1
- package/dist/utils/parse-cookie.d.ts +13 -0
- package/dist/utils/parse-cookie.js +52 -0
- package/dist/utils/path.d.ts +7 -1
- package/dist/utils/path.js +9 -1
- package/dist/utils/text-stream.d.ts +1 -1
- package/dist/utils/text-stream.js +2 -2
- package/dist/utils/vite-version.d.ts +12 -1
- package/dist/utils/vite-version.js +9 -1
- package/package.json +2 -2
- package/dist/shims/internal/parse-cookie-header.d.ts +0 -14
- package/dist/shims/internal/parse-cookie-header.js +0 -30
|
@@ -6,6 +6,7 @@ import "./app-elements.js";
|
|
|
6
6
|
import { resolveHardNavigationTargetFromRscResponse, resolveRscCompatibilityNavigationDecision } from "./app-rsc-cache-busting.js";
|
|
7
7
|
import { resolveRscRedirectLifecycleHop, resolveStreamedRscRedirectLifecycleHop } from "./app-browser-rsc-redirect.js";
|
|
8
8
|
import { NavigationTraceReasonCodes, createNavigationLifecycleTraceFields, createNavigationTrace } from "./navigation-trace.js";
|
|
9
|
+
import { verifyOperationTokenForCacheReuse } from "./operation-token.js";
|
|
9
10
|
//#region src/server/navigation-planner.ts
|
|
10
11
|
const ROUTE_INTERCEPTION_CONTEXT_SEPARATOR = "\0";
|
|
11
12
|
const CACHE_ENTRY_PROOF_MISSING_CODE = "CP_CACHE_ENTRY_PROOF_MISSING";
|
|
@@ -213,6 +214,71 @@ function classifyEarlyNavigationIntent(facts) {
|
|
|
213
214
|
trace: createEarlyNavigationIntentTrace(NavigationTraceReasonCodes.crossDocumentFlight, facts)
|
|
214
215
|
};
|
|
215
216
|
}
|
|
217
|
+
function classifyVisitedResponseCacheCandidate(facts) {
|
|
218
|
+
if (facts.candidate === "missing") return { kind: "miss" };
|
|
219
|
+
if (!facts.mountedSlotsMatch) return {
|
|
220
|
+
kind: "evict",
|
|
221
|
+
reason: "mountedSlotsMismatch"
|
|
222
|
+
};
|
|
223
|
+
if (facts.navigationKind === "refresh") return {
|
|
224
|
+
kind: "evict",
|
|
225
|
+
reason: "refresh"
|
|
226
|
+
};
|
|
227
|
+
if (!facts.fresh) return {
|
|
228
|
+
kind: "evict",
|
|
229
|
+
reason: "stale"
|
|
230
|
+
};
|
|
231
|
+
return { kind: "reuse" };
|
|
232
|
+
}
|
|
233
|
+
function createNavigationReuseTrace(code, facts, fields = {}) {
|
|
234
|
+
return createNavigationTrace(code, {
|
|
235
|
+
eventKind: facts.navigationKind,
|
|
236
|
+
targetHref: facts.targetHref,
|
|
237
|
+
...fields
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function createFreshFetchDecision(facts, reason) {
|
|
241
|
+
return {
|
|
242
|
+
kind: "fetchFresh",
|
|
243
|
+
reason,
|
|
244
|
+
trace: createNavigationReuseTrace(NavigationTraceReasonCodes.fetchFresh, facts, { freshFetchReason: reason })
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function classifyNavigationReuse(facts) {
|
|
248
|
+
if (facts.navigationKind === "refresh") return createFreshFetchDecision(facts, "refresh");
|
|
249
|
+
if (!facts.bypassNavigationCache && facts.visitedResponse.status === "available") return {
|
|
250
|
+
kind: "reuseVisitedResponse",
|
|
251
|
+
trace: createNavigationReuseTrace(NavigationTraceReasonCodes.visitedResponseReuse, facts)
|
|
252
|
+
};
|
|
253
|
+
if (!facts.bypassNavigationCache && facts.prefetch.status === "available") return {
|
|
254
|
+
kind: "consumePrefetch",
|
|
255
|
+
trace: createNavigationReuseTrace(NavigationTraceReasonCodes.prefetchResponseReuse, facts)
|
|
256
|
+
};
|
|
257
|
+
if (facts.navigationKind === "navigate") {
|
|
258
|
+
if (facts.optimisticRouteShell.status === "available") return {
|
|
259
|
+
kind: "attemptOptimisticRouteShell",
|
|
260
|
+
trace: createNavigationReuseTrace(NavigationTraceReasonCodes.optimisticRouteShell, facts)
|
|
261
|
+
};
|
|
262
|
+
return createFreshFetchDecision(facts, facts.bypassNavigationCache ? "cacheBypassed" : facts.optimisticRouteShell.reason);
|
|
263
|
+
}
|
|
264
|
+
if (facts.bypassNavigationCache) return createFreshFetchDecision(facts, "cacheBypassed");
|
|
265
|
+
return createFreshFetchDecision(facts, "cacheMiss");
|
|
266
|
+
}
|
|
267
|
+
function classifyNavigationPrefetchProbe(facts) {
|
|
268
|
+
if (facts.visitedResponse.status === "available") return {
|
|
269
|
+
kind: "skip",
|
|
270
|
+
reason: "visitedResponseAvailable"
|
|
271
|
+
};
|
|
272
|
+
if (facts.navigationKind === "refresh") return {
|
|
273
|
+
kind: "skip",
|
|
274
|
+
reason: "refresh"
|
|
275
|
+
};
|
|
276
|
+
if (facts.bypassNavigationCache) return {
|
|
277
|
+
kind: "skip",
|
|
278
|
+
reason: "cacheBypassed"
|
|
279
|
+
};
|
|
280
|
+
return { kind: "probe" };
|
|
281
|
+
}
|
|
216
282
|
function createSnapshotRouteTopology(snapshot) {
|
|
217
283
|
return {
|
|
218
284
|
layoutIds: snapshot.layoutIds,
|
|
@@ -466,6 +532,18 @@ function createCacheProofRejectedDecision(options) {
|
|
|
466
532
|
url: options.event.result.href
|
|
467
533
|
};
|
|
468
534
|
}
|
|
535
|
+
function createCacheReuseTokenRejectedDecision(options) {
|
|
536
|
+
return {
|
|
537
|
+
kind: "hardNavigate",
|
|
538
|
+
reason: "cacheReuseTokenRejected",
|
|
539
|
+
token: options.event.token,
|
|
540
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.cacheReuseTokenRejected, {
|
|
541
|
+
...options.traceFields,
|
|
542
|
+
cacheReuseTokenReason: options.reason
|
|
543
|
+
}),
|
|
544
|
+
url: options.event.result.href
|
|
545
|
+
};
|
|
546
|
+
}
|
|
469
547
|
function createAcceptedCacheProofTraceFields(traceFields, decision) {
|
|
470
548
|
if (decision === null) return traceFields;
|
|
471
549
|
return {
|
|
@@ -554,6 +632,17 @@ function planFlightResponseArrived(options) {
|
|
|
554
632
|
traceFields
|
|
555
633
|
});
|
|
556
634
|
const acceptedCacheEntryDecision = cacheEntryProofEvaluation.decision;
|
|
635
|
+
if (acceptedCacheEntryDecision !== null) {
|
|
636
|
+
const reuseVerdict = verifyOperationTokenForCacheReuse(options.event.token, {
|
|
637
|
+
graphVersion: options.routeManifest?.graphVersion ?? null,
|
|
638
|
+
installedCacheVariantFingerprint: null
|
|
639
|
+
});
|
|
640
|
+
if (!reuseVerdict.authorized) return createCacheReuseTokenRejectedDecision({
|
|
641
|
+
event: options.event,
|
|
642
|
+
reason: reuseVerdict.reason,
|
|
643
|
+
traceFields
|
|
644
|
+
});
|
|
645
|
+
}
|
|
557
646
|
const commitTraceFields = createAcceptedCacheProofTraceFields(traceFields, acceptedCacheEntryDecision);
|
|
558
647
|
const cacheEntryProposalFields = createCacheEntryProposalFields(acceptedCacheEntryDecision);
|
|
559
648
|
if (targetSnapshot.interception !== null) {
|
|
@@ -680,10 +769,59 @@ function planNavigation(input) {
|
|
|
680
769
|
}
|
|
681
770
|
}
|
|
682
771
|
}
|
|
772
|
+
function classifyServerActionResult(facts) {
|
|
773
|
+
if (facts.clientCompatibilityId === null) return {
|
|
774
|
+
kind: "proceed",
|
|
775
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.proceedToCommit, {})
|
|
776
|
+
};
|
|
777
|
+
if (!facts.isRscContentType) return {
|
|
778
|
+
kind: "proceed",
|
|
779
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.proceedToCommit, {})
|
|
780
|
+
};
|
|
781
|
+
if (resolveRscCompatibilityNavigationDecision({
|
|
782
|
+
clientCompatibilityId: facts.clientCompatibilityId,
|
|
783
|
+
currentHref: facts.currentHref,
|
|
784
|
+
origin: facts.origin,
|
|
785
|
+
responseCompatibilityId: facts.compatibilityIdHeader,
|
|
786
|
+
responseUrl: facts.responseUrl
|
|
787
|
+
}).kind === "compatible") return {
|
|
788
|
+
kind: "proceed",
|
|
789
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.proceedToCommit, {})
|
|
790
|
+
};
|
|
791
|
+
if (facts.actionRedirectHref !== null) return {
|
|
792
|
+
kind: "hardNavigate",
|
|
793
|
+
url: facts.actionRedirectHref,
|
|
794
|
+
historyMode: facts.actionRedirectType === "push" ? "assign" : "replace",
|
|
795
|
+
clearClientNavigationCaches: true,
|
|
796
|
+
reason: "serverActionRedirectCompatibilityMismatch",
|
|
797
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.serverActionRedirectCompatibilityMismatch, { targetHref: facts.actionRedirectHref })
|
|
798
|
+
};
|
|
799
|
+
const targetUrl = facts.currentHref;
|
|
800
|
+
return {
|
|
801
|
+
kind: "hardNavigate",
|
|
802
|
+
url: targetUrl,
|
|
803
|
+
clearClientNavigationCaches: false,
|
|
804
|
+
reason: "serverActionRscCompatibilityMismatch",
|
|
805
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.serverActionRscCompatibilityMismatch, { targetHref: targetUrl })
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
function classifyRscNavigationError(facts) {
|
|
809
|
+
return {
|
|
810
|
+
kind: "hardNavigate",
|
|
811
|
+
url: facts.currentHref,
|
|
812
|
+
reason: "rscNavigationError",
|
|
813
|
+
trace: createNavigationTrace(NavigationTraceReasonCodes.rscNavigationError, { targetHref: facts.currentHref })
|
|
814
|
+
};
|
|
815
|
+
}
|
|
683
816
|
const navigationPlanner = {
|
|
684
817
|
classifyEarlyNavigationIntent,
|
|
818
|
+
classifyNavigationPrefetchProbe,
|
|
819
|
+
classifyNavigationReuse,
|
|
685
820
|
classifyRscFetchResult,
|
|
821
|
+
classifyRscNavigationError,
|
|
686
822
|
classifyRootBoundaryTransition,
|
|
823
|
+
classifyServerActionResult,
|
|
824
|
+
classifyVisitedResponseCacheCandidate,
|
|
687
825
|
plan: planNavigation,
|
|
688
826
|
resolveCurrentRootBoundaryElementPersistence,
|
|
689
827
|
resolveMountedParallelSlotPersistence,
|
|
@@ -3,8 +3,10 @@ declare const NAVIGATION_TRACE_SCHEMA_VERSION = 0;
|
|
|
3
3
|
type NavigationTraceSchemaVersion = 0;
|
|
4
4
|
declare const NavigationTraceReasonCodes: {
|
|
5
5
|
cacheProofRejected: "NC_CACHE_REJECT";
|
|
6
|
+
cacheReuseTokenRejected: "NC_CACHE_TOKEN_REJECT";
|
|
6
7
|
commitCurrent: "NC_COMMIT";
|
|
7
8
|
crossDocumentFlight: "NC_CROSS_DOC_FLIGHT";
|
|
9
|
+
fetchFresh: "NC_FETCH_FRESH";
|
|
8
10
|
invalidRscPayload: "NC_RSC_INVALID";
|
|
9
11
|
interceptedCommitCurrent: "NC_INTERCEPT_COMMIT";
|
|
10
12
|
interceptedRejectedIncompatibleRoot: "NC_INTERCEPT_REJECT_ROOT";
|
|
@@ -13,7 +15,9 @@ declare const NavigationTraceReasonCodes: {
|
|
|
13
15
|
interceptedRejectedTargetMismatch: "NC_INTERCEPT_REJECT_TARGET";
|
|
14
16
|
interceptedRejectedUndeclaredTopology: "NC_INTERCEPT_REJECT_GRAPH";
|
|
15
17
|
interceptedRejectedUnknownSource: "NC_INTERCEPT_REJECT_SOURCE";
|
|
18
|
+
optimisticRouteShell: "NC_OPTIMISTIC_SHELL";
|
|
16
19
|
prefetchOnly: "NC_PREFETCH_ONLY";
|
|
20
|
+
prefetchResponseReuse: "NC_PREFETCH_REUSE";
|
|
17
21
|
proceedToCommit: "NC_RSC_PROCEED";
|
|
18
22
|
redirectFollow: "NC_RSC_REDIRECT_FOLLOW";
|
|
19
23
|
redirectTerminalDepth: "NC_RSC_REDIRECT_DEPTH";
|
|
@@ -22,10 +26,14 @@ declare const NavigationTraceReasonCodes: {
|
|
|
22
26
|
rootBoundaryChanged: "NC_ROOT";
|
|
23
27
|
rootBoundaryUnknown: "NC_ROOT_UNKNOWN";
|
|
24
28
|
rscCompatibilityMismatch: "NC_RSC_COMPAT_MISMATCH";
|
|
29
|
+
rscNavigationError: "NC_RSC_NAV_ERROR";
|
|
25
30
|
sameDocumentScroll: "NC_SAME_DOC_SCROLL";
|
|
26
31
|
samePageSearch: "NC_SAME_PAGE_SEARCH";
|
|
32
|
+
serverActionRedirectCompatibilityMismatch: "NC_SA_REDIRECT_COMPAT";
|
|
33
|
+
serverActionRscCompatibilityMismatch: "NC_SA_RSC_COMPAT";
|
|
27
34
|
staleOperation: "NC_STALE";
|
|
28
35
|
streamedRedirectLoop: "NC_RSC_STREAMED_REDIRECT_LOOP";
|
|
36
|
+
visitedResponseReuse: "NC_VISITED_REUSE";
|
|
29
37
|
};
|
|
30
38
|
declare const NavigationTraceTransactionCodes: {
|
|
31
39
|
hardNavigate: "NT_HARD_NAVIGATE";
|
|
@@ -35,7 +43,7 @@ declare const NavigationTraceTransactionCodes: {
|
|
|
35
43
|
type NavigationTraceReasonCode = (typeof NavigationTraceReasonCodes)[keyof typeof NavigationTraceReasonCodes];
|
|
36
44
|
type NavigationTraceTransactionCode = (typeof NavigationTraceTransactionCodes)[keyof typeof NavigationTraceTransactionCodes];
|
|
37
45
|
type NavigationTraceCode = NavigationTraceReasonCode | NavigationTraceTransactionCode;
|
|
38
|
-
type NavigationTraceFieldName = "activeNavigationId" | "cacheProofCode" | "cacheProofMode" | "cacheProofReuseClass" | "cacheProofScope" | "currentRootLayoutTreePath" | "currentVisibleCommitVersion" | "nextRootLayoutTreePath" | "eventKind" | "fetchResultSource" | "operationLane" | "pendingOperationId" | "redirectDepth" | "redirectSignal" | "startedVisibleCommitVersion" | "startedNavigationId" | "targetHref" | "traverseDirection";
|
|
46
|
+
type NavigationTraceFieldName = "activeNavigationId" | "cacheProofCode" | "cacheProofMode" | "cacheProofReuseClass" | "cacheProofScope" | "cacheReuseTokenReason" | "currentRootLayoutTreePath" | "currentVisibleCommitVersion" | "nextRootLayoutTreePath" | "eventKind" | "fetchResultSource" | "freshFetchReason" | "operationLane" | "pendingOperationId" | "redirectDepth" | "redirectSignal" | "startedVisibleCommitVersion" | "startedNavigationId" | "targetHref" | "traverseDirection";
|
|
39
47
|
type NavigationTraceFieldValue = string | number | boolean | null;
|
|
40
48
|
type NavigationTraceFields = Readonly<Partial<Record<NavigationTraceFieldName, NavigationTraceFieldValue>>>;
|
|
41
49
|
type NavigationTraceEntry = Readonly<{
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
const NAVIGATION_TRACE_SCHEMA_VERSION = 0;
|
|
3
3
|
const NavigationTraceReasonCodes = {
|
|
4
4
|
cacheProofRejected: "NC_CACHE_REJECT",
|
|
5
|
+
cacheReuseTokenRejected: "NC_CACHE_TOKEN_REJECT",
|
|
5
6
|
commitCurrent: "NC_COMMIT",
|
|
6
7
|
crossDocumentFlight: "NC_CROSS_DOC_FLIGHT",
|
|
8
|
+
fetchFresh: "NC_FETCH_FRESH",
|
|
7
9
|
invalidRscPayload: "NC_RSC_INVALID",
|
|
8
10
|
interceptedCommitCurrent: "NC_INTERCEPT_COMMIT",
|
|
9
11
|
interceptedRejectedIncompatibleRoot: "NC_INTERCEPT_REJECT_ROOT",
|
|
@@ -12,7 +14,9 @@ const NavigationTraceReasonCodes = {
|
|
|
12
14
|
interceptedRejectedTargetMismatch: "NC_INTERCEPT_REJECT_TARGET",
|
|
13
15
|
interceptedRejectedUndeclaredTopology: "NC_INTERCEPT_REJECT_GRAPH",
|
|
14
16
|
interceptedRejectedUnknownSource: "NC_INTERCEPT_REJECT_SOURCE",
|
|
17
|
+
optimisticRouteShell: "NC_OPTIMISTIC_SHELL",
|
|
15
18
|
prefetchOnly: "NC_PREFETCH_ONLY",
|
|
19
|
+
prefetchResponseReuse: "NC_PREFETCH_REUSE",
|
|
16
20
|
proceedToCommit: "NC_RSC_PROCEED",
|
|
17
21
|
redirectFollow: "NC_RSC_REDIRECT_FOLLOW",
|
|
18
22
|
redirectTerminalDepth: "NC_RSC_REDIRECT_DEPTH",
|
|
@@ -21,10 +25,14 @@ const NavigationTraceReasonCodes = {
|
|
|
21
25
|
rootBoundaryChanged: "NC_ROOT",
|
|
22
26
|
rootBoundaryUnknown: "NC_ROOT_UNKNOWN",
|
|
23
27
|
rscCompatibilityMismatch: "NC_RSC_COMPAT_MISMATCH",
|
|
28
|
+
rscNavigationError: "NC_RSC_NAV_ERROR",
|
|
24
29
|
sameDocumentScroll: "NC_SAME_DOC_SCROLL",
|
|
25
30
|
samePageSearch: "NC_SAME_PAGE_SEARCH",
|
|
31
|
+
serverActionRedirectCompatibilityMismatch: "NC_SA_REDIRECT_COMPAT",
|
|
32
|
+
serverActionRscCompatibilityMismatch: "NC_SA_RSC_COMPAT",
|
|
26
33
|
staleOperation: "NC_STALE",
|
|
27
|
-
streamedRedirectLoop: "NC_RSC_STREAMED_REDIRECT_LOOP"
|
|
34
|
+
streamedRedirectLoop: "NC_RSC_STREAMED_REDIRECT_LOOP",
|
|
35
|
+
visitedResponseReuse: "NC_VISITED_REUSE"
|
|
28
36
|
};
|
|
29
37
|
const NavigationTraceTransactionCodes = {
|
|
30
38
|
hardNavigate: "NT_HARD_NAVIGATE",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
//#region src/server/operation-token.d.ts
|
|
2
|
+
type OperationLane = "hmr" | "navigation" | "prefetch" | "refresh" | "server-action" | "traverse";
|
|
3
|
+
type OperationToken = {
|
|
4
|
+
operationId: number;
|
|
5
|
+
lane: OperationLane;
|
|
6
|
+
navigationId: number;
|
|
7
|
+
baseVisibleCommitVersion: number;
|
|
8
|
+
graphVersion: string | null;
|
|
9
|
+
deploymentVersion: string | null;
|
|
10
|
+
targetSnapshotFingerprint: string;
|
|
11
|
+
cacheVariantFingerprint?: string;
|
|
12
|
+
};
|
|
13
|
+
declare const verifiedOperationTokenBrand: unique symbol;
|
|
14
|
+
type VerifiedOperationToken = OperationToken & {
|
|
15
|
+
readonly [verifiedOperationTokenBrand]: true;
|
|
16
|
+
};
|
|
17
|
+
type OperationTokenAuthority = {
|
|
18
|
+
activeNavigationId: number;
|
|
19
|
+
visibleCommitVersion: number;
|
|
20
|
+
graphVersion: string | null;
|
|
21
|
+
installedCacheVariantFingerprint: string | null;
|
|
22
|
+
};
|
|
23
|
+
type OperationTokenDimension = "navigation" | "visibleCommit" | "graphVersion" | "cacheVariant";
|
|
24
|
+
type OperationTokenRejectionReason = "staleNavigation" | "staleVisibleCommit" | "graphVersionMismatch" | "graphVersionMissing" | "cacheVariantMismatch" | "cacheVariantMissing";
|
|
25
|
+
type OperationTokenVerdict = {
|
|
26
|
+
readonly authorized: true;
|
|
27
|
+
readonly token: VerifiedOperationToken;
|
|
28
|
+
} | {
|
|
29
|
+
readonly authorized: false;
|
|
30
|
+
readonly reason: OperationTokenRejectionReason;
|
|
31
|
+
};
|
|
32
|
+
type OperationTokenVerificationPolicy = {
|
|
33
|
+
check: readonly OperationTokenDimension[];
|
|
34
|
+
require: readonly OperationTokenDimension[];
|
|
35
|
+
};
|
|
36
|
+
declare function verifyOperationToken(token: OperationToken, authority: OperationTokenAuthority, policy: OperationTokenVerificationPolicy): OperationTokenVerdict;
|
|
37
|
+
declare function verifyOperationTokenForCommit(token: OperationToken, authority: Pick<OperationTokenAuthority, "activeNavigationId" | "visibleCommitVersion">): OperationTokenVerdict;
|
|
38
|
+
declare function verifyOperationTokenForCacheReuse(token: OperationToken, authority: Pick<OperationTokenAuthority, "graphVersion" | "installedCacheVariantFingerprint">): OperationTokenVerdict;
|
|
39
|
+
//#endregion
|
|
40
|
+
export { OperationLane, OperationToken, OperationTokenAuthority, OperationTokenRejectionReason, OperationTokenVerdict, OperationTokenVerificationPolicy, VerifiedOperationToken, verifyOperationToken, verifyOperationTokenForCacheReuse, verifyOperationTokenForCommit };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
//#region src/server/operation-token.ts
|
|
2
|
+
const DIMENSION_ORDER = [
|
|
3
|
+
"navigation",
|
|
4
|
+
"visibleCommit",
|
|
5
|
+
"graphVersion",
|
|
6
|
+
"cacheVariant"
|
|
7
|
+
];
|
|
8
|
+
function evaluateDimension(dimension, token, authority) {
|
|
9
|
+
switch (dimension) {
|
|
10
|
+
case "navigation": return token.navigationId === authority.activeNavigationId ? { kind: "satisfied" } : {
|
|
11
|
+
kind: "mismatch",
|
|
12
|
+
reason: "staleNavigation"
|
|
13
|
+
};
|
|
14
|
+
case "visibleCommit": return token.baseVisibleCommitVersion === authority.visibleCommitVersion ? { kind: "satisfied" } : {
|
|
15
|
+
kind: "mismatch",
|
|
16
|
+
reason: "staleVisibleCommit"
|
|
17
|
+
};
|
|
18
|
+
case "graphVersion":
|
|
19
|
+
if (token.graphVersion === null || authority.graphVersion === null) return {
|
|
20
|
+
kind: "absent",
|
|
21
|
+
missingReason: "graphVersionMissing"
|
|
22
|
+
};
|
|
23
|
+
return token.graphVersion === authority.graphVersion ? { kind: "satisfied" } : {
|
|
24
|
+
kind: "mismatch",
|
|
25
|
+
reason: "graphVersionMismatch"
|
|
26
|
+
};
|
|
27
|
+
case "cacheVariant": {
|
|
28
|
+
const tokenVariant = token.cacheVariantFingerprint;
|
|
29
|
+
const installedVariant = authority.installedCacheVariantFingerprint;
|
|
30
|
+
if (tokenVariant === void 0 || installedVariant === null) return {
|
|
31
|
+
kind: "absent",
|
|
32
|
+
missingReason: "cacheVariantMissing"
|
|
33
|
+
};
|
|
34
|
+
return tokenVariant === installedVariant ? { kind: "satisfied" } : {
|
|
35
|
+
kind: "mismatch",
|
|
36
|
+
reason: "cacheVariantMismatch"
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
default: throw new Error("[vinext] Unknown operation-token dimension: " + String(dimension));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function verifyOperationToken(token, authority, policy) {
|
|
43
|
+
const required = new Set(policy.require);
|
|
44
|
+
const evaluated = new Set([...policy.check, ...policy.require]);
|
|
45
|
+
for (const dimension of DIMENSION_ORDER) {
|
|
46
|
+
if (!evaluated.has(dimension)) continue;
|
|
47
|
+
const status = evaluateDimension(dimension, token, authority);
|
|
48
|
+
if (status.kind === "mismatch") return {
|
|
49
|
+
authorized: false,
|
|
50
|
+
reason: status.reason
|
|
51
|
+
};
|
|
52
|
+
if (status.kind === "absent" && required.has(dimension)) return {
|
|
53
|
+
authorized: false,
|
|
54
|
+
reason: status.missingReason
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
authorized: true,
|
|
59
|
+
token
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function verifyOperationTokenForCommit(token, authority) {
|
|
63
|
+
return verifyOperationToken(token, {
|
|
64
|
+
activeNavigationId: authority.activeNavigationId,
|
|
65
|
+
visibleCommitVersion: authority.visibleCommitVersion,
|
|
66
|
+
graphVersion: token.graphVersion,
|
|
67
|
+
installedCacheVariantFingerprint: token.cacheVariantFingerprint ?? null
|
|
68
|
+
}, {
|
|
69
|
+
check: ["navigation", "visibleCommit"],
|
|
70
|
+
require: ["navigation", "visibleCommit"]
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function verifyOperationTokenForCacheReuse(token, authority) {
|
|
74
|
+
return verifyOperationToken(token, {
|
|
75
|
+
activeNavigationId: token.navigationId,
|
|
76
|
+
visibleCommitVersion: token.baseVisibleCommitVersion,
|
|
77
|
+
graphVersion: authority.graphVersion,
|
|
78
|
+
installedCacheVariantFingerprint: authority.installedCacheVariantFingerprint
|
|
79
|
+
}, {
|
|
80
|
+
check: ["graphVersion", "cacheVariant"],
|
|
81
|
+
require: []
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//#endregion
|
|
85
|
+
export { verifyOperationToken, verifyOperationTokenForCacheReuse, verifyOperationTokenForCommit };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NextI18nConfig } from "../config/next-config.js";
|
|
1
2
|
import { Route } from "../routing/pages-router.js";
|
|
2
3
|
import { ExecutionContextLike } from "../shims/request-context.js";
|
|
3
4
|
import { PagesReqResRequest, PagesReqResResponse, PagesRequestQuery } from "./pages-node-compat.js";
|
|
@@ -71,6 +72,11 @@ type HandlePagesApiRouteOptions = {
|
|
|
71
72
|
reportRequestError?: (error: Error, routePattern: string) => void | Promise<void>;
|
|
72
73
|
request: Request;
|
|
73
74
|
url: string;
|
|
75
|
+
nextConfig?: {
|
|
76
|
+
basePath?: string;
|
|
77
|
+
i18n?: NextI18nConfig | null;
|
|
78
|
+
trailingSlash?: boolean;
|
|
79
|
+
};
|
|
74
80
|
};
|
|
75
81
|
declare function handlePagesApiRoute(options: HandlePagesApiRouteOptions): Promise<Response>;
|
|
76
82
|
//#endregion
|
|
@@ -2,7 +2,8 @@ import "./server-globals.js";
|
|
|
2
2
|
import { runWithExecutionContext } from "../shims/request-context.js";
|
|
3
3
|
import { NextRequest } from "../shims/server.js";
|
|
4
4
|
import { internalServerErrorResponse } from "./http-error-responses.js";
|
|
5
|
-
import {
|
|
5
|
+
import { cloneRequestWithUrl } from "./request-pipeline.js";
|
|
6
|
+
import { mergeRouteParamsIntoQuery, parseQueryString, urlQueryToSearchParams } from "../utils/query.js";
|
|
6
7
|
import { PagesBodyParseError } from "./pages-media-type.js";
|
|
7
8
|
import { isEdgeApiRuntime } from "./edge-api-runtime.js";
|
|
8
9
|
import { resolveBodyParserConfig } from "./pages-body-parser-config.js";
|
|
@@ -14,6 +15,12 @@ function resolveModuleRuntime(module) {
|
|
|
14
15
|
function buildPagesApiQuery(url, params) {
|
|
15
16
|
return mergeRouteParamsIntoQuery(parseQueryString(url), params);
|
|
16
17
|
}
|
|
18
|
+
function createEdgeApiRequest(request, url, params) {
|
|
19
|
+
const resolvedUrl = new URL(request.url);
|
|
20
|
+
resolvedUrl.search = urlQueryToSearchParams(buildPagesApiQuery(url, params)).toString();
|
|
21
|
+
const resolvedUrlString = resolvedUrl.toString();
|
|
22
|
+
return resolvedUrlString === request.url ? request : cloneRequestWithUrl(request, resolvedUrlString);
|
|
23
|
+
}
|
|
17
24
|
function isEdgeApiRouteModule(module) {
|
|
18
25
|
return typeof module.default === "function" && isEdgeApiRuntime(resolveModuleRuntime(module));
|
|
19
26
|
}
|
|
@@ -29,7 +36,11 @@ async function _handlePagesApiRoute(options) {
|
|
|
29
36
|
const { route, params } = options.match;
|
|
30
37
|
try {
|
|
31
38
|
if (isEdgeApiRouteModule(route.module)) {
|
|
32
|
-
const nextRequest = new NextRequest(options.request)
|
|
39
|
+
const nextRequest = new NextRequest(createEdgeApiRequest(options.request, options.url, params), options.nextConfig ? { nextConfig: {
|
|
40
|
+
basePath: options.nextConfig.basePath,
|
|
41
|
+
i18n: options.nextConfig.i18n ?? void 0,
|
|
42
|
+
trailingSlash: options.nextConfig.trailingSlash
|
|
43
|
+
} } : void 0);
|
|
33
44
|
const response = await route.module.default(nextRequest);
|
|
34
45
|
if (response instanceof Response) return response;
|
|
35
46
|
throw new Error("Edge API route did not return a Response");
|
|
@@ -30,7 +30,7 @@ declare function getManifestFilesForModule(manifest: Record<string, string[]> |
|
|
|
30
30
|
* asset URLs. SSR-manifest values are base-anchored; re-anchor under any
|
|
31
31
|
* configured `assetPrefix` (default `""` keeps the legacy `"/" + file`).
|
|
32
32
|
*/
|
|
33
|
-
declare function resolveClientModuleUrl(manifest: Record<string, string[]> | null | undefined, moduleId: string | null | undefined, basePath?: string, assetPrefix?: string): string | undefined;
|
|
33
|
+
declare function resolveClientModuleUrl(manifest: Record<string, string[]> | null | undefined, moduleId: string | null | undefined, basePath?: string, assetPrefix?: string, _deploymentId?: string): string | undefined;
|
|
34
34
|
type CollectAssetTagsOptions = {
|
|
35
35
|
/**
|
|
36
36
|
* SSR manifest mapping module file paths to their associated asset list.
|
|
@@ -57,6 +57,7 @@ type CollectAssetTagsOptions = {
|
|
|
57
57
|
*/
|
|
58
58
|
basePath?: string;
|
|
59
59
|
assetPrefix?: string;
|
|
60
|
+
deploymentId?: string;
|
|
60
61
|
};
|
|
61
62
|
/**
|
|
62
63
|
* Build the HTML `<link>` and `<script>` tag string for the SSR response.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { appendDeploymentIdQuery } from "../utils/deployment-id.js";
|
|
1
2
|
import { createNonceAttribute } from "./html.js";
|
|
2
3
|
import { assetServingUrlFromBaseAnchored } from "../utils/manifest-paths.js";
|
|
3
4
|
//#region src/server/pages-asset-tags.ts
|
|
@@ -41,7 +42,7 @@ function getManifestFilesForModule(manifest, moduleId) {
|
|
|
41
42
|
* asset URLs. SSR-manifest values are base-anchored; re-anchor under any
|
|
42
43
|
* configured `assetPrefix` (default `""` keeps the legacy `"/" + file`).
|
|
43
44
|
*/
|
|
44
|
-
function resolveClientModuleUrl(manifest, moduleId, basePath = "", assetPrefix = "") {
|
|
45
|
+
function resolveClientModuleUrl(manifest, moduleId, basePath = "", assetPrefix = "", _deploymentId) {
|
|
45
46
|
const files = getManifestFilesForModule(resolveSsrManifest(manifest), moduleId);
|
|
46
47
|
if (!files) return void 0;
|
|
47
48
|
for (let i = 0; i < files.length; i++) {
|
|
@@ -72,7 +73,10 @@ function collectAssetTags(options) {
|
|
|
72
73
|
const deferAttr = options.disableOptimizedLoading ? "" : " defer";
|
|
73
74
|
const basePath = options.basePath ?? "";
|
|
74
75
|
const assetPrefix = options.assetPrefix ?? "";
|
|
75
|
-
const href = (value) =>
|
|
76
|
+
const href = (value) => {
|
|
77
|
+
const url = assetServingUrlFromBaseAnchored(value, basePath, assetPrefix);
|
|
78
|
+
return value.endsWith(".js") ? url : appendDeploymentIdQuery(url, options.deploymentId);
|
|
79
|
+
};
|
|
76
80
|
const lazyChunks = typeof globalThis !== "undefined" && globalThis.__VINEXT_LAZY_CHUNKS__ || null;
|
|
77
81
|
const lazySet = lazyChunks && lazyChunks.length > 0 ? new Set(lazyChunks) : null;
|
|
78
82
|
if (typeof globalThis !== "undefined" && globalThis.__VINEXT_CLIENT_ENTRY__) {
|
|
@@ -60,6 +60,13 @@ declare function parseNextDataPathname(pathname: string, buildId: string): NextD
|
|
|
60
60
|
* { pageProps: {...}, /* optional locale data, redirect markers, etc. *\/ }
|
|
61
61
|
*/
|
|
62
62
|
declare function buildNextDataJsonResponse(pageProps: Record<string, unknown>, safeJsonStringify: (value: unknown) => string, init?: ResponseInit): Response;
|
|
63
|
+
/**
|
|
64
|
+
* Build a `_next/data` JSON response from the full Pages props object returned
|
|
65
|
+
* through `_app.getInitialProps`. Next.js serializes the same outer props
|
|
66
|
+
* object that would be passed to `<App />`, so custom app-level props remain
|
|
67
|
+
* siblings of `pageProps` in the data envelope.
|
|
68
|
+
*/
|
|
69
|
+
declare function buildNextDataPropsJsonResponse(props: Record<string, unknown>, safeJsonStringify: (value: unknown) => string, init?: ResponseInit): Response;
|
|
63
70
|
/**
|
|
64
71
|
* Build the 404 response Next.js returns for an unknown `_next/data` page.
|
|
65
72
|
* Next.js renders this as a normal 404 page, but the body shape that clients
|
|
@@ -109,6 +116,6 @@ type NormalizePagesDataRequestResult = {
|
|
|
109
116
|
* Extracted from `entries/pages-server-entry.ts` so both `renderPage` and
|
|
110
117
|
* `runMiddleware` share a single implementation.
|
|
111
118
|
*/
|
|
112
|
-
declare function normalizePagesDataRequest(request: Request, buildId: string | null): NormalizePagesDataRequestResult;
|
|
119
|
+
declare function normalizePagesDataRequest(request: Request, buildId: string | null, basePath?: string): NormalizePagesDataRequestResult;
|
|
113
120
|
//#endregion
|
|
114
|
-
export { buildNextDataJsonResponse, buildNextDataNotFoundResponse, isNextDataPathname, normalizePagesDataRequest, parseNextDataPathname };
|
|
121
|
+
export { buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, isNextDataPathname, normalizePagesDataRequest, parseNextDataPathname };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addBasePathToPathname, hasBasePath, stripBasePath } from "../utils/base-path.js";
|
|
1
2
|
import { NEXTJS_DEPLOYMENT_ID_HEADER } from "./headers.js";
|
|
2
3
|
//#region src/server/pages-data-route.ts
|
|
3
4
|
/**
|
|
@@ -66,7 +67,16 @@ function parseNextDataPathname(pathname, buildId) {
|
|
|
66
67
|
* { pageProps: {...}, /* optional locale data, redirect markers, etc. *\/ }
|
|
67
68
|
*/
|
|
68
69
|
function buildNextDataJsonResponse(pageProps, safeJsonStringify, init) {
|
|
69
|
-
|
|
70
|
+
return buildNextDataPropsJsonResponse({ pageProps }, safeJsonStringify, init);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Build a `_next/data` JSON response from the full Pages props object returned
|
|
74
|
+
* through `_app.getInitialProps`. Next.js serializes the same outer props
|
|
75
|
+
* object that would be passed to `<App />`, so custom app-level props remain
|
|
76
|
+
* siblings of `pageProps` in the data envelope.
|
|
77
|
+
*/
|
|
78
|
+
function buildNextDataPropsJsonResponse(props, safeJsonStringify, init) {
|
|
79
|
+
const body = safeJsonStringify(props);
|
|
70
80
|
return new Response(body, {
|
|
71
81
|
status: init?.status ?? 200,
|
|
72
82
|
statusText: init?.statusText,
|
|
@@ -114,16 +124,18 @@ function buildNextDataNotFoundResponse() {
|
|
|
114
124
|
* Extracted from `entries/pages-server-entry.ts` so both `renderPage` and
|
|
115
125
|
* `runMiddleware` share a single implementation.
|
|
116
126
|
*/
|
|
117
|
-
function normalizePagesDataRequest(request, buildId) {
|
|
127
|
+
function normalizePagesDataRequest(request, buildId, basePath = "") {
|
|
118
128
|
const reqUrl = new URL(request.url);
|
|
119
|
-
|
|
129
|
+
const hadBasePath = !!basePath && hasBasePath(reqUrl.pathname, basePath);
|
|
130
|
+
const dataPathname = basePath ? stripBasePath(reqUrl.pathname, basePath) : reqUrl.pathname;
|
|
131
|
+
if (!isNextDataPathname(dataPathname)) return {
|
|
120
132
|
isDataReq: false,
|
|
121
133
|
request,
|
|
122
134
|
normalizedPathname: null,
|
|
123
135
|
search: "",
|
|
124
136
|
notFoundResponse: null
|
|
125
137
|
};
|
|
126
|
-
const dataMatch = buildId ? parseNextDataPathname(
|
|
138
|
+
const dataMatch = buildId ? parseNextDataPathname(dataPathname, buildId) : null;
|
|
127
139
|
if (!dataMatch) return {
|
|
128
140
|
isDataReq: false,
|
|
129
141
|
request,
|
|
@@ -132,7 +144,7 @@ function normalizePagesDataRequest(request, buildId) {
|
|
|
132
144
|
notFoundResponse: buildNextDataNotFoundResponse()
|
|
133
145
|
};
|
|
134
146
|
const normalizedUrl = new URL(reqUrl);
|
|
135
|
-
normalizedUrl.pathname = dataMatch.pagePathname;
|
|
147
|
+
normalizedUrl.pathname = hadBasePath ? addBasePathToPathname(dataMatch.pagePathname, basePath) : dataMatch.pagePathname;
|
|
136
148
|
return {
|
|
137
149
|
isDataReq: true,
|
|
138
150
|
request: new Request(normalizedUrl, request),
|
|
@@ -142,4 +154,4 @@ function normalizePagesDataRequest(request, buildId) {
|
|
|
142
154
|
};
|
|
143
155
|
}
|
|
144
156
|
//#endregion
|
|
145
|
-
export { buildNextDataJsonResponse, buildNextDataNotFoundResponse, isNextDataPathname, normalizePagesDataRequest, parseNextDataPathname };
|
|
157
|
+
export { buildNextDataJsonResponse, buildNextDataNotFoundResponse, buildNextDataPropsJsonResponse, isNextDataPathname, normalizePagesDataRequest, parseNextDataPathname };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
//#region src/server/pages-dev-module-url.ts
|
|
3
|
+
function normalizeBase(base) {
|
|
4
|
+
if (!base || base === "/") return "/";
|
|
5
|
+
return `/${base.replace(/^\/+|\/+$/g, "")}/`;
|
|
6
|
+
}
|
|
7
|
+
function encodeModulePath(modulePath) {
|
|
8
|
+
return encodeURI(modulePath).replace(/%5B/gi, "[").replace(/%5D/gi, "]").replace(/\?/g, "%3F").replace(/#/g, "%23");
|
|
9
|
+
}
|
|
10
|
+
function createPagesDevModuleUrl(viteRoot, moduleFilePath, viteBase) {
|
|
11
|
+
const relativePath = (/^[A-Za-z]:[\\/]/.test(viteRoot) ? path.win32 : path).relative(viteRoot, moduleFilePath).replace(/\\/g, "/");
|
|
12
|
+
return normalizeBase(viteBase) + encodeModulePath(relativePath);
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { createPagesDevModuleUrl };
|
|
@@ -45,12 +45,6 @@ type DocumentRenderPageInput = {
|
|
|
45
45
|
* the head nodes returned by `getInitialProps` (forward them to
|
|
46
46
|
* `setDocumentInitialHead()` — do NOT call
|
|
47
47
|
* `callDocumentGetInitialProps()` as well).
|
|
48
|
-
* - `consumed` — `getInitialProps` WAS invoked but no body was produced
|
|
49
|
-
* (it never called `renderPage`, returned no `{ html }`, or
|
|
50
|
-
* threw). Callers must NOT re-invoke `getInitialProps` (that
|
|
51
|
-
* would call it a second time) — render the streaming body,
|
|
52
|
-
* spread `docProps` (possibly empty) onto `<Document>`, and
|
|
53
|
-
* forward `head` to `setDocumentInitialHead()`.
|
|
54
48
|
*/
|
|
55
49
|
type RunDocumentRenderPageResult = {
|
|
56
50
|
status: "skipped";
|
|
@@ -60,10 +54,6 @@ type RunDocumentRenderPageResult = {
|
|
|
60
54
|
stylesHTML: string;
|
|
61
55
|
docProps: Record<string, unknown>;
|
|
62
56
|
head: ReactNode[];
|
|
63
|
-
} | {
|
|
64
|
-
status: "consumed";
|
|
65
|
-
docProps: Record<string, unknown>;
|
|
66
|
-
head: ReactNode[];
|
|
67
57
|
};
|
|
68
58
|
/**
|
|
69
59
|
* Run a user `_document.getInitialProps()` with a `ctx.renderPage()` that
|
|
@@ -75,11 +65,10 @@ type RunDocumentRenderPageResult = {
|
|
|
75
65
|
* prod (`pages-page-response.ts`) and dev (`dev-server.ts`) SSR pipelines so
|
|
76
66
|
* the `getInitialProps` + `renderPage` contract lives in one place.
|
|
77
67
|
*
|
|
78
|
-
* `getInitialProps` is invoked at most once here. When this returns `
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* this contract guarantees).
|
|
68
|
+
* `getInitialProps` is invoked at most once here. When this returns `rendered`,
|
|
69
|
+
* callers MUST treat that as the single invocation and must not call
|
|
70
|
+
* `loadUserDocumentInitialProps` again. Errors intentionally propagate to the
|
|
71
|
+
* Pages Router's normal error-page pipeline, matching Next.js.
|
|
83
72
|
*
|
|
84
73
|
* @see .nextjs-ref/packages/next/src/server/render.tsx (search `renderPage`)
|
|
85
74
|
*/
|