vinext 1.4.2 → 1.4.3
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 +4 -1
- package/dist/build/prerender-paths.d.ts +11 -1
- package/dist/build/prerender-paths.js +36 -10
- package/dist/cli.js +1 -1
- package/dist/client/dev-error-overlay.d.ts +2 -1
- package/dist/client/dev-error-overlay.js +8 -3
- package/dist/config/config-matchers.js +6 -2
- package/dist/config/next-config.d.ts +9 -0
- package/dist/entries/app-rsc-entry.js +24 -12
- package/dist/entries/pages-server-entry.js +17 -4
- package/dist/index.js +22 -25
- package/dist/init-platform.js +2 -2
- package/dist/init.js +42 -5
- package/dist/server/api-handler.js +7 -3
- package/dist/server/app-browser-entry.js +16 -37
- package/dist/server/app-browser-error.d.ts +1 -1
- package/dist/server/app-browser-error.js +13 -4
- package/dist/server/app-browser-supplemental-refresh.d.ts +13 -0
- package/dist/server/app-browser-supplemental-refresh.js +36 -4
- package/dist/server/app-middleware.d.ts +2 -0
- package/dist/server/app-middleware.js +1 -0
- package/dist/server/app-page-boundary-render.js +2 -0
- package/dist/server/app-page-dispatch.d.ts +1 -0
- package/dist/server/app-page-dispatch.js +5 -1
- package/dist/server/app-page-element-builder.d.ts +2 -0
- package/dist/server/app-page-element-builder.js +2 -1
- package/dist/server/app-page-route-wiring.d.ts +7 -5
- package/dist/server/app-page-route-wiring.js +3 -1
- package/dist/server/app-pages-bridge.d.ts +6 -0
- package/dist/server/app-pages-bridge.js +8 -3
- package/dist/server/app-request-stage-independent-entry.js +2 -3
- package/dist/server/app-router-entry.js +2 -3
- package/dist/server/app-rsc-cache-busting.d.ts +8 -0
- package/dist/server/app-rsc-cache-busting.js +13 -1
- package/dist/server/app-rsc-combined-handler.js +2 -1
- package/dist/server/app-rsc-handler.d.ts +4 -0
- package/dist/server/app-rsc-handler.js +39 -22
- package/dist/server/app-rsc-response-finalizer.d.ts +15 -3
- package/dist/server/app-rsc-response-finalizer.js +51 -7
- package/dist/server/app-ssr-entry.js +8 -0
- package/dist/server/config-headers.d.ts +7 -0
- package/dist/server/config-headers.js +20 -1
- package/dist/server/image-animation.d.ts +9 -0
- package/dist/server/image-animation.js +118 -0
- package/dist/server/image-optimization.d.ts +25 -5
- package/dist/server/image-optimization.js +305 -21
- package/dist/server/image-source-reader.d.ts +34 -0
- package/dist/server/image-source-reader.js +126 -0
- package/dist/server/metadata-route-response.d.ts +6 -1
- package/dist/server/metadata-route-response.js +22 -4
- package/dist/server/middleware-matcher.d.ts +1 -0
- package/dist/server/middleware-matcher.js +1 -1
- package/dist/server/middleware-runtime.d.ts +5 -0
- package/dist/server/middleware-runtime.js +48 -15
- package/dist/server/middleware.d.ts +1 -1
- package/dist/server/middleware.js +2 -1
- package/dist/server/nitro-request-target-plugin.d.ts +17 -0
- package/dist/server/nitro-request-target-plugin.js +22 -0
- package/dist/server/open-redirect.d.ts +2 -1
- package/dist/server/open-redirect.js +2 -1
- package/dist/server/pages-client-assets.d.ts +1 -0
- package/dist/server/pages-i18n.d.ts +7 -0
- package/dist/server/pages-i18n.js +14 -1
- package/dist/server/pages-node-compat.js +7 -3
- package/dist/server/pages-page-handler.js +4 -4
- package/dist/server/pages-request-pipeline.d.ts +9 -0
- package/dist/server/pages-request-pipeline.js +29 -10
- package/dist/server/pages-request-stage-entry.js +7 -2
- package/dist/server/pages-router-entry.js +3 -0
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.js +48 -54
- package/dist/server/srvx-middleware-origin.d.ts +13 -0
- package/dist/server/srvx-middleware-origin.js +19 -0
- package/dist/server/srvx-request-target.d.ts +12 -0
- package/dist/server/srvx-request-target.js +20 -0
- package/dist/server/static-file-cache.js +10 -22
- package/dist/server/worker-image-optimization.d.ts +8 -1
- package/dist/server/worker-image-optimization.js +25 -6
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/shims/error-boundary.d.ts +6 -2
- package/dist/shims/error-boundary.js +4 -2
- package/dist/shims/request-context.d.ts +3 -1
- package/dist/shims/url-utils.js +6 -1
- package/dist/utils/client-entry-manifest.d.ts +5 -0
- package/dist/utils/client-entry-manifest.js +1 -0
- package/dist/utils/client-runtime-metadata.d.ts +5 -0
- package/dist/utils/client-runtime-metadata.js +33 -7
- package/package.json +1 -1
package/dist/init.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import path, { toSlash } from "./deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { detectPackageManager, detectPackageManagerName, detectProject, ensureESModule, findViteConfigPath, hasViteConfig, renameCJSConfigs } from "./utils/project.js";
|
|
3
3
|
import { compactResourceName, cssModulesConfigSource, findConfigKeepingWorkerName, setupCloudflarePlatform, updateViteConfigForCssModules, usesCommonJsViteConfig, validateCloudflarePlatformSetup } from "./init-cloudflare.js";
|
|
4
|
-
import { getReactUpgradeDeps } from "./utils/react-version.js";
|
|
4
|
+
import { findPackageVersion, getReactUpgradeDeps } from "./utils/react-version.js";
|
|
5
5
|
import { getPluginReactUpgradeDeps } from "./utils/plugin-react-version.js";
|
|
6
|
+
import { createRequire } from "node:module";
|
|
6
7
|
import fs from "node:fs";
|
|
7
8
|
import { spawn, spawnSync } from "node:child_process";
|
|
8
9
|
//#region src/init.ts
|
|
@@ -297,6 +298,26 @@ function addDependencyEntries(root, deps, { dev }) {
|
|
|
297
298
|
if (added.length > 0) fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
298
299
|
return added;
|
|
299
300
|
}
|
|
301
|
+
/** The spec in the manifest sections `isDepInstalled` reads. */
|
|
302
|
+
function readDeclaredDependency(root, name) {
|
|
303
|
+
try {
|
|
304
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
|
|
305
|
+
return pkg.dependencies?.[name] ?? pkg.devDependencies?.[name] ?? pkg.peerDependencies?.[name];
|
|
306
|
+
} catch {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/** The declared spec, or the installed version of a package hoisted from elsewhere. */
|
|
311
|
+
function readCurrentDependencyVersion(root, name) {
|
|
312
|
+
const declared = readDeclaredDependency(root, name);
|
|
313
|
+
if (declared !== void 0) return declared;
|
|
314
|
+
try {
|
|
315
|
+
const resolved = createRequire(path.join(root, "package.json")).resolve(name);
|
|
316
|
+
return findPackageVersion(resolved, name) ?? void 0;
|
|
317
|
+
} catch {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
300
321
|
/**
|
|
301
322
|
* Check if react/react-dom need upgrading for react-server-dom-webpack compatibility.
|
|
302
323
|
*
|
|
@@ -578,12 +599,20 @@ async function init(options) {
|
|
|
578
599
|
let dependencyInstallNeedsApproval = false;
|
|
579
600
|
const dependencyEntriesAdded = [];
|
|
580
601
|
const devDependencyEntriesAdded = [];
|
|
602
|
+
const upgradedFrom = /* @__PURE__ */ new Map();
|
|
603
|
+
const recordUpgrades = (deps) => {
|
|
604
|
+
for (const dep of deps) {
|
|
605
|
+
const { name } = parseDependencySpecifier(dep);
|
|
606
|
+
upgradedFrom.set(name, readCurrentDependencyVersion(root, name));
|
|
607
|
+
}
|
|
608
|
+
};
|
|
581
609
|
if (isApp) {
|
|
582
610
|
const reactUpgrade = shouldInstall ? [.../* @__PURE__ */ new Set([...getReactUpgradeDeps(root), ...getReactUpgradeDeps(root, {
|
|
583
611
|
fromManifest: true,
|
|
584
612
|
installing: true
|
|
585
613
|
})])] : getReactUpgradeDeps(root, { fromManifest: true });
|
|
586
614
|
if (reactUpgrade.length > 0) {
|
|
615
|
+
recordUpgrades(reactUpgrade);
|
|
587
616
|
console.log(` ${terminalStyle.cyan(terminalStyle.bold("Upgrading dependencies:"))}`);
|
|
588
617
|
console.log(formatList(reactUpgrade.map((dep) => dep.replace(/@latest$/, "")), " "));
|
|
589
618
|
try {
|
|
@@ -601,6 +630,7 @@ async function init(options) {
|
|
|
601
630
|
}
|
|
602
631
|
const pluginReactUpgrade = getPluginReactUpgradeDeps(root);
|
|
603
632
|
if (pluginReactUpgrade.length > 0) {
|
|
633
|
+
recordUpgrades(pluginReactUpgrade);
|
|
604
634
|
console.log(` ${terminalStyle.cyan(terminalStyle.bold("Upgrading devDependencies:"))}`);
|
|
605
635
|
console.log(formatList(pluginReactUpgrade.map((dep) => dep.replace(/@latest$/, "")), " "));
|
|
606
636
|
try {
|
|
@@ -654,13 +684,20 @@ async function init(options) {
|
|
|
654
684
|
if (pmName === "pnpm" && shouldInstall && !dependencyInstallNeedsApproval && !options._exec && hasAutomaticallyIgnoredBuilds(inspectPnpmIgnoredBuilds(root))) dependencyInstallNeedsApproval = true;
|
|
655
685
|
else if (pmName === "pnpm" && shouldInstall && !dependencyInstallNeedsApproval && options._inspectPnpmIgnoredBuilds && hasAutomaticallyIgnoredBuilds(options._inspectPnpmIgnoredBuilds(root))) dependencyInstallNeedsApproval = true;
|
|
656
686
|
console.log(` ${terminalStyle.green(terminalStyle.bold("vinext init complete!"))}\n`);
|
|
657
|
-
|
|
687
|
+
const addedDependencies = dependencyEntriesAdded.filter((name) => !upgradedFrom.has(name));
|
|
688
|
+
const addedDevDependencies = devDependencyEntriesAdded.filter((name) => !upgradedFrom.has(name));
|
|
689
|
+
if (addedDependencies.length > 0) {
|
|
658
690
|
console.log(` ${terminalStyle.green("✓")} Added dependencies to dependencies:`);
|
|
659
|
-
console.log(formatList(
|
|
691
|
+
console.log(formatList(addedDependencies, " "));
|
|
660
692
|
}
|
|
661
|
-
if (
|
|
693
|
+
if (addedDevDependencies.length > 0) {
|
|
662
694
|
console.log(` ${terminalStyle.green("✓")} Added dependencies to devDependencies:`);
|
|
663
|
-
console.log(formatList(
|
|
695
|
+
console.log(formatList(addedDevDependencies, " "));
|
|
696
|
+
}
|
|
697
|
+
for (const [name, from] of upgradedFrom) {
|
|
698
|
+
const to = readDeclaredDependency(root, name);
|
|
699
|
+
if (to === void 0 || to === from) continue;
|
|
700
|
+
console.log(` ${terminalStyle.green("✓")} Upgraded ${name} ${from ?? "(not installed)"} \u2192 ${to}`);
|
|
664
701
|
}
|
|
665
702
|
if (dependencyInstallNeedsApproval) console.log(` ${terminalStyle.yellow("!")} Dependency installation is waiting for build-script approval`);
|
|
666
703
|
if (addedTypeModule) console.log(` ${terminalStyle.green("✓")} Added "type": "module" to package.json`);
|
|
@@ -186,10 +186,14 @@ function enhanceApiObjects(req, res, query, body, trustedRevalidateOrigin, allow
|
|
|
186
186
|
return this;
|
|
187
187
|
},
|
|
188
188
|
json(data) {
|
|
189
|
-
this.setHeader("Content-Type", "application/json");
|
|
189
|
+
this.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
190
190
|
this.end(JSON.stringify(data));
|
|
191
191
|
},
|
|
192
192
|
send(data) {
|
|
193
|
+
if (data === null || data === void 0) {
|
|
194
|
+
this.end();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
193
197
|
if (this.statusCode === 204 || this.statusCode === 304) {
|
|
194
198
|
this.removeHeader("Content-Type");
|
|
195
199
|
this.removeHeader("Content-Length");
|
|
@@ -208,8 +212,8 @@ function enhanceApiObjects(req, res, query, body, trustedRevalidateOrigin, allow
|
|
|
208
212
|
this.end(data);
|
|
209
213
|
return;
|
|
210
214
|
}
|
|
211
|
-
if (typeof data === "object"
|
|
212
|
-
this.setHeader("Content-Type", "application/json");
|
|
215
|
+
if (typeof data === "object" || typeof data === "number" || typeof data === "boolean") {
|
|
216
|
+
this.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
213
217
|
this.end(JSON.stringify(data));
|
|
214
218
|
} else {
|
|
215
219
|
if (!this.getHeader("Content-Type")) this.setHeader("Content-Type", "text/plain");
|
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import { addBasePathToPathname, stripBasePath } from "../utils/base-path.js";
|
|
2
1
|
import { VINEXT_MOUNTED_LAYOUTS_HEADER, VINEXT_PARAMS_HEADER, VINEXT_RENDERED_PATH_AND_SEARCH_HEADER, VINEXT_RSC_REDIRECT_HEADER, VINEXT_RSC_REDIRECT_TYPE_HEADER } from "./headers.js";
|
|
3
|
-
import { splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
4
2
|
import { AppRouterContext } from "../shims/internal/app-router-context.js";
|
|
5
|
-
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
6
3
|
import { installWindowNext, setWindowNextInternalSourcePage } from "../client/window-next.js";
|
|
7
4
|
import { retryScrollTo, scrollToHashTargetOnNextFrame } from "../shims/hash-scroll.js";
|
|
8
5
|
import { VINEXT_RSC_COMPATIBILITY_ID_HEADER, VINEXT_RSC_CONTENT_TYPE, createRscRequestHeaders, createRscRequestUrl, formatRscRequestPath, isRscCompatibilityIdCompatible } from "./app-rsc-cache-busting.js";
|
|
@@ -32,7 +29,7 @@ import { COMMITTED_CACHE_APP_NAVIGATION_PAYLOAD_ORIGIN, FRESH_APP_NAVIGATION_PAY
|
|
|
32
29
|
import { clearHardNavigationLoopGuard, createAppBrowserNavigationController, createBasePathStrippedPathAndSearch, navigateDocumentDirectly } from "./app-browser-navigation-controller.js";
|
|
33
30
|
import { createAppRouteTree } from "./app-route-tree.js";
|
|
34
31
|
import { shouldRecoverSamePathSearchCommitOnResponseCompletion } from "./app-browser-navigation-response.js";
|
|
35
|
-
import { createSupplementalRefreshCoordinator, mergeRefreshedParallelSlot, requireCompleteSupplementalRefresh, resolvePersistedSourcePageRefreshes, resolveServerActionSupplementalRefresh, resolveSupplementalRefreshes } from "./app-browser-supplemental-refresh.js";
|
|
32
|
+
import { createSupplementalRefreshCoordinator, mergeRefreshedParallelSlot, requireCompleteSupplementalRefresh, resolvePersistedRefreshInterceptions, resolvePersistedSourcePageRefreshes, resolveServerActionSupplementalRefresh, resolveSupplementalRefreshes } from "./app-browser-supplemental-refresh.js";
|
|
36
33
|
import { createAppBrowserNavigationAbortCoordinator } from "./app-browser-navigation-abort.js";
|
|
37
34
|
import { consumeInitialFormState, createVinextHydrateRootOptions, hydrateRootInTransition, resolveFetchedHydrationLocation } from "./app-browser-hydration.js";
|
|
38
35
|
import { AppBrowserHistoryController } from "./app-browser-history-controller.js";
|
|
@@ -278,36 +275,6 @@ function clearDynamicClientNavigationCaches() {
|
|
|
278
275
|
optimisticRouteTemplates.clear();
|
|
279
276
|
historyController.invalidateRestorableClientState();
|
|
280
277
|
}
|
|
281
|
-
function getMatchedUrlPathname(matchedUrl) {
|
|
282
|
-
return new URL(matchedUrl, "https://vinext.local").pathname;
|
|
283
|
-
}
|
|
284
|
-
function resolvePersistedRefreshInterceptions(state, routeManifest, refreshUrl, requestInterceptionContext) {
|
|
285
|
-
if (routeManifest === null) return [];
|
|
286
|
-
const refreshPathname = stripBasePath(refreshUrl.pathname, __basePath);
|
|
287
|
-
const refreshPathParts = splitPathnameForRouteMatch(refreshPathname);
|
|
288
|
-
const resolved = [];
|
|
289
|
-
for (const binding of state.slotBindings) {
|
|
290
|
-
if (binding.state !== "active" || !binding.activeRouteId) continue;
|
|
291
|
-
if (!binding.interceptionId || !binding.interceptionSourceMatchedUrl) continue;
|
|
292
|
-
const activeRoute = AppElementsWire.parseElementKey(binding.activeRouteId);
|
|
293
|
-
if (activeRoute?.kind !== "route") continue;
|
|
294
|
-
const match = routeManifest.segmentGraph.interceptions.get(binding.interceptionId);
|
|
295
|
-
if (!match) continue;
|
|
296
|
-
const retainedInterception = state.interception?.slotId === binding.slotId && matchRoutePattern(splitPathnameForRouteMatch(getMatchedUrlPathname(state.interception.targetMatchedUrl)), match.targetPatternParts) !== null ? state.interception : null;
|
|
297
|
-
const targetPathname = retainedInterception?.targetMatchedUrl ?? activeRoute.path;
|
|
298
|
-
const targetParts = splitPathnameForRouteMatch(getMatchedUrlPathname(targetPathname));
|
|
299
|
-
if (requestInterceptionContext !== null && state.interception?.slotId === binding.slotId && matchRoutePattern(refreshPathParts, match.targetPatternParts) !== null && matchRoutePattern(targetParts, match.targetPatternParts) !== null) continue;
|
|
300
|
-
const targetUrl = new URL(targetPathname, refreshUrl);
|
|
301
|
-
targetUrl.pathname = addBasePathToPathname(targetUrl.pathname, __basePath);
|
|
302
|
-
targetUrl.search = refreshUrl.search;
|
|
303
|
-
resolved.push({
|
|
304
|
-
interception: match,
|
|
305
|
-
interceptionContext: retainedInterception?.sourceMatchedUrl ?? binding.interceptionSourceMatchedUrl,
|
|
306
|
-
targetPathname: `${targetUrl.pathname}${targetUrl.search}`
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
return resolved;
|
|
310
|
-
}
|
|
311
278
|
async function fetchPersistedInterceptedSlotRefresh(options) {
|
|
312
279
|
const headers = createRscRequestHeaders({
|
|
313
280
|
interceptionContext: options.interceptionContext,
|
|
@@ -482,7 +449,13 @@ async function commitSameUrlNavigatePayload(nextElements, actionInitiation, retu
|
|
|
482
449
|
if (revalidation !== "none" && routeManifestLoaded) {
|
|
483
450
|
const refreshUrl = new URL(actionInitiation.href);
|
|
484
451
|
const requestInterceptionContext = resolveInterceptionContextFromPreviousNextUrl(actionInitiation.routerState.previousNextUrl, __basePath);
|
|
485
|
-
const persistedInterceptions = resolvePersistedRefreshInterceptions(
|
|
452
|
+
const persistedInterceptions = resolvePersistedRefreshInterceptions({
|
|
453
|
+
basePath: __basePath,
|
|
454
|
+
refreshUrl,
|
|
455
|
+
requestInterceptionContext,
|
|
456
|
+
routeManifest: getBrowserRouteManifest(),
|
|
457
|
+
state: actionInitiation.routerState
|
|
458
|
+
});
|
|
486
459
|
const sourcePageRefreshes = resolvePersistedSourcePageRefreshes({
|
|
487
460
|
basePath: __basePath,
|
|
488
461
|
refreshUrl,
|
|
@@ -1094,7 +1067,7 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1094
1067
|
const formState = consumeInitialFormState(getVinextBrowserGlobal());
|
|
1095
1068
|
const hydrateRootOptions = import.meta.env.DEV && devErrorOverlay ? createVinextHydrateRootOptions({
|
|
1096
1069
|
formState,
|
|
1097
|
-
onCaughtError: invalidateOnCaughtError(createDevOnCaughtError(devErrorOverlay.devOnCaughtError, onUncaughtError)),
|
|
1070
|
+
onCaughtError: invalidateOnCaughtError(createDevOnCaughtError(devErrorOverlay.devOnCaughtError, onUncaughtError, devErrorOverlay.reportRootErrorBoundaryCatch)),
|
|
1098
1071
|
onUncaughtError
|
|
1099
1072
|
}) : createVinextHydrateRootOptions({
|
|
1100
1073
|
formState,
|
|
@@ -1195,7 +1168,13 @@ function bootstrapHydration(rscStream, devErrorOverlay, initialRscBootstrap) {
|
|
|
1195
1168
|
const requestInterceptionContext = requestState.interceptionContext;
|
|
1196
1169
|
const requestPreviousNextUrl = requestState.previousNextUrl;
|
|
1197
1170
|
const shouldSupplementVisibleBranches = navigationKind === "refresh" || navigationKind === "traverse" && !reuseCurrentBfcacheIds;
|
|
1198
|
-
const persistedRefreshInterceptions = navigationKind === "refresh" ? resolvePersistedRefreshInterceptions(
|
|
1171
|
+
const persistedRefreshInterceptions = navigationKind === "refresh" ? resolvePersistedRefreshInterceptions({
|
|
1172
|
+
basePath: __basePath,
|
|
1173
|
+
refreshUrl: url,
|
|
1174
|
+
requestInterceptionContext,
|
|
1175
|
+
routeManifest: getBrowserRouteManifest(),
|
|
1176
|
+
state: navigationInitiationState
|
|
1177
|
+
}) : [];
|
|
1199
1178
|
const persistedSourcePageRefreshes = shouldSupplementVisibleBranches ? resolvePersistedSourcePageRefreshes({
|
|
1200
1179
|
activeRoutePaths: navigationKind === "traverse" ? readHistoryStateActiveRoutePaths(activeTraversalIntent?.historyState) ?? [] : void 0,
|
|
1201
1180
|
basePath: __basePath,
|
|
@@ -8,7 +8,7 @@ export declare function createOnUncaughtError(options?: {
|
|
|
8
8
|
coerceToError?: boolean;
|
|
9
9
|
}): HydrateRootErrorHandler;
|
|
10
10
|
export declare function createProdOnCaughtError(onImplicitRootError: HydrateRootErrorHandler): HydrateRootErrorHandler;
|
|
11
|
-
export declare function createDevOnCaughtError(onCaughtError: HydrateRootErrorHandler, onImplicitRootError: HydrateRootErrorHandler): HydrateRootErrorHandler;
|
|
11
|
+
export declare function createDevOnCaughtError(onCaughtError: HydrateRootErrorHandler, onImplicitRootError: HydrateRootErrorHandler, onRootErrorBoundaryCatch?: () => void): HydrateRootErrorHandler;
|
|
12
12
|
export declare function createProdOnRecoverableError(onReportedError: () => void): (error: unknown) => void;
|
|
13
13
|
//#endregion
|
|
14
14
|
export {};
|
|
@@ -2,10 +2,18 @@ import { isUnknownRecord } from "../utils/record.js";
|
|
|
2
2
|
import { isNavigationSignalError } from "../utils/navigation-signal.js";
|
|
3
3
|
import { isBailoutToCSRError } from "../shims/navigation-errors.js";
|
|
4
4
|
//#region src/server/app-browser-error.ts
|
|
5
|
-
function
|
|
6
|
-
if (!isUnknownRecord(errorInfo.errorBoundary)) return
|
|
5
|
+
function getErrorBoundaryProps(errorInfo) {
|
|
6
|
+
if (!isUnknownRecord(errorInfo.errorBoundary)) return {};
|
|
7
7
|
const props = errorInfo.errorBoundary.props;
|
|
8
|
-
return isUnknownRecord(props)
|
|
8
|
+
return isUnknownRecord(props) ? props : {};
|
|
9
|
+
}
|
|
10
|
+
function isImplicitRootErrorBoundary(errorInfo) {
|
|
11
|
+
return getErrorBoundaryProps(errorInfo).isImplicitRootErrorBoundary === true;
|
|
12
|
+
}
|
|
13
|
+
function isRootErrorBoundary(errorInfo) {
|
|
14
|
+
const props = getErrorBoundaryProps(errorInfo);
|
|
15
|
+
if (props.isGlobalErrorBoundary === true) return true;
|
|
16
|
+
return props.isImplicitRootErrorBoundary === true && props.wrapsGlobalErrorBoundary !== true;
|
|
9
17
|
}
|
|
10
18
|
function logCaughtError(error, errorInfo) {
|
|
11
19
|
console.error(error);
|
|
@@ -38,8 +46,9 @@ function createProdOnCaughtError(onImplicitRootError) {
|
|
|
38
46
|
logCaughtError(error, errorInfo);
|
|
39
47
|
};
|
|
40
48
|
}
|
|
41
|
-
function createDevOnCaughtError(onCaughtError, onImplicitRootError) {
|
|
49
|
+
function createDevOnCaughtError(onCaughtError, onImplicitRootError, onRootErrorBoundaryCatch) {
|
|
42
50
|
return (error, errorInfo) => {
|
|
51
|
+
if (!isNavigationSignalError(error) && isRootErrorBoundary(errorInfo)) onRootErrorBoundaryCatch?.();
|
|
43
52
|
if (isImplicitRootErrorBoundary(errorInfo)) {
|
|
44
53
|
onImplicitRootError(error, errorInfo);
|
|
45
54
|
return;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BrowserRouteManifest, BrowserRouteManifestInterception } from "../routing/browser-route-manifest.js";
|
|
1
2
|
import { AppElements } from "./app-elements-wire.js";
|
|
2
3
|
import "./app-elements.js";
|
|
3
4
|
import { AppRouterState } from "./app-browser-state.js";
|
|
@@ -31,6 +32,18 @@ export declare function resolvePersistedSourcePageRefreshes(options: {
|
|
|
31
32
|
refreshUrl: URL;
|
|
32
33
|
state: Pick<AppRouterState, "previousNextUrl" | "slotBindings">;
|
|
33
34
|
}): string[];
|
|
35
|
+
export type PersistedRefreshInterception = {
|
|
36
|
+
interception: BrowserRouteManifestInterception;
|
|
37
|
+
interceptionContext: string;
|
|
38
|
+
targetPathname: string;
|
|
39
|
+
};
|
|
40
|
+
export declare function resolvePersistedRefreshInterceptions(options: {
|
|
41
|
+
basePath: string;
|
|
42
|
+
refreshUrl: URL;
|
|
43
|
+
requestInterceptionContext: string | null;
|
|
44
|
+
routeManifest: BrowserRouteManifest | null;
|
|
45
|
+
state: Pick<AppRouterState, "interception" | "slotBindings">;
|
|
46
|
+
}): PersistedRefreshInterception[];
|
|
34
47
|
export declare function createSupplementalRefreshCoordinator(): {
|
|
35
48
|
abortAll(): void;
|
|
36
49
|
begin(options: {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { normalizePathnameForRouteMatch } from "../routing/utils.js";
|
|
1
|
+
import { removeTrailingSlash, restoreBasePath, stripBasePath } from "../utils/base-path.js";
|
|
2
|
+
import { normalizePathnameForRouteMatch, splitPathnameForRouteMatch } from "../routing/utils.js";
|
|
3
3
|
import { normalizePath } from "./normalize-path.js";
|
|
4
|
+
import { matchRoutePattern } from "../routing/route-pattern.js";
|
|
4
5
|
import { APP_BFCACHE_SEGMENT_IDENTITIES_KEY, APP_INTERCEPTION_CONTEXT_KEY, APP_INTERCEPTION_KEY, APP_SLOT_BINDINGS_KEY, AppElementsWire, normalizeAppElementsSlotBindings } from "./app-elements-wire.js";
|
|
5
6
|
import "./app-elements.js";
|
|
6
7
|
import { isNestedBfcacheSlotSegmentIdFor } from "./bfcache-identity.js";
|
|
@@ -131,7 +132,7 @@ function resolvePersistedSourcePageRefreshes(options) {
|
|
|
131
132
|
});
|
|
132
133
|
for (const activeRoutePath of activeRoutePaths) {
|
|
133
134
|
if (activeRoutePath !== refreshRoutePathname && (refreshRoutePathname === "/" || activeRoutePath.startsWith(refreshRoutePathname + "/"))) continue;
|
|
134
|
-
const pathname =
|
|
135
|
+
const pathname = restoreBasePath(activeRoutePath, options.basePath);
|
|
135
136
|
if (sourceUrlsByPathname.has(pathname)) continue;
|
|
136
137
|
const sourceUrl = new URL(pathname, options.refreshUrl);
|
|
137
138
|
sourceUrl.search = options.refreshUrl.search;
|
|
@@ -145,6 +146,37 @@ function resolvePersistedSourcePageRefreshes(options) {
|
|
|
145
146
|
}
|
|
146
147
|
return resolved;
|
|
147
148
|
}
|
|
149
|
+
function getMatchedUrlPathname(matchedUrl) {
|
|
150
|
+
return new URL(matchedUrl, "https://vinext.local").pathname;
|
|
151
|
+
}
|
|
152
|
+
function resolvePersistedRefreshInterceptions(options) {
|
|
153
|
+
const { basePath, refreshUrl, requestInterceptionContext, routeManifest, state } = options;
|
|
154
|
+
if (routeManifest === null) return [];
|
|
155
|
+
const refreshPathname = stripBasePath(refreshUrl.pathname, basePath);
|
|
156
|
+
const refreshPathParts = splitPathnameForRouteMatch(refreshPathname);
|
|
157
|
+
const resolved = [];
|
|
158
|
+
for (const binding of state.slotBindings) {
|
|
159
|
+
if (binding.state !== "active" || !binding.activeRouteId) continue;
|
|
160
|
+
if (!binding.interceptionId || !binding.interceptionSourceMatchedUrl) continue;
|
|
161
|
+
const activeRoute = AppElementsWire.parseElementKey(binding.activeRouteId);
|
|
162
|
+
if (activeRoute?.kind !== "route") continue;
|
|
163
|
+
const match = routeManifest.segmentGraph.interceptions.get(binding.interceptionId);
|
|
164
|
+
if (!match) continue;
|
|
165
|
+
const retainedInterception = state.interception?.slotId === binding.slotId && matchRoutePattern(splitPathnameForRouteMatch(getMatchedUrlPathname(state.interception.targetMatchedUrl)), match.targetPatternParts) !== null ? state.interception : null;
|
|
166
|
+
const targetPathname = retainedInterception?.targetMatchedUrl ?? activeRoute.path;
|
|
167
|
+
const targetParts = splitPathnameForRouteMatch(getMatchedUrlPathname(targetPathname));
|
|
168
|
+
if (requestInterceptionContext !== null && state.interception?.slotId === binding.slotId && matchRoutePattern(refreshPathParts, match.targetPatternParts) !== null && matchRoutePattern(targetParts, match.targetPatternParts) !== null) continue;
|
|
169
|
+
const targetUrl = new URL(targetPathname, refreshUrl);
|
|
170
|
+
targetUrl.pathname = restoreBasePath(targetUrl.pathname, basePath);
|
|
171
|
+
targetUrl.search = refreshUrl.search;
|
|
172
|
+
resolved.push({
|
|
173
|
+
interception: match,
|
|
174
|
+
interceptionContext: retainedInterception?.sourceMatchedUrl ?? binding.interceptionSourceMatchedUrl,
|
|
175
|
+
targetPathname: `${targetUrl.pathname}${targetUrl.search}`
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return resolved;
|
|
179
|
+
}
|
|
148
180
|
function createSupplementalRefreshCoordinator() {
|
|
149
181
|
const controllers = /* @__PURE__ */ new Set();
|
|
150
182
|
return {
|
|
@@ -202,4 +234,4 @@ async function resolveSupplementalRefreshes(options) {
|
|
|
202
234
|
}
|
|
203
235
|
}
|
|
204
236
|
//#endregion
|
|
205
|
-
export { SupplementalRefreshError, createSupplementalRefreshCoordinator, mergeRefreshedParallelSlot, requireCompleteSupplementalRefresh, resolvePersistedSourcePageRefreshes, resolveServerActionSupplementalRefresh, resolveSupplementalRefreshes };
|
|
237
|
+
export { SupplementalRefreshError, createSupplementalRefreshCoordinator, mergeRefreshedParallelSlot, requireCompleteSupplementalRefresh, resolvePersistedRefreshInterceptions, resolvePersistedSourcePageRefreshes, resolveServerActionSupplementalRefresh, resolveSupplementalRefreshes };
|
|
@@ -26,6 +26,8 @@ export type ApplyAppMiddlewareOptions = {
|
|
|
26
26
|
middlewareRequest?: Request;
|
|
27
27
|
module: MiddlewareModule;
|
|
28
28
|
request: Request;
|
|
29
|
+
/** Forwarded to `executeMiddleware`. */
|
|
30
|
+
restoreLocaleRootTrailingSlash?: boolean;
|
|
29
31
|
validateExternalRewriteRequest?: () => Promise<Response | null>;
|
|
30
32
|
/**
|
|
31
33
|
* Forwarded to `executeMiddleware` so the NextRequest exposes a NextURL with
|
|
@@ -203,6 +203,7 @@ async function applyAppMiddleware(options) {
|
|
|
203
203
|
},
|
|
204
204
|
requestBodyAlreadyIsolated: true,
|
|
205
205
|
request: middlewareRequest,
|
|
206
|
+
restoreLocaleRootTrailingSlash: options.restoreLocaleRootTrailingSlash,
|
|
206
207
|
skipTrailingSlashRedirect: options.skipTrailingSlashRedirect,
|
|
207
208
|
trailingSlash: options.trailingSlash
|
|
208
209
|
});
|
|
@@ -85,8 +85,10 @@ function wrapRenderedBoundaryElement(options) {
|
|
|
85
85
|
renderErrorBoundary(GlobalErrorComponent, children) {
|
|
86
86
|
return createElement(GlobalErrorBoundary, {
|
|
87
87
|
fallback: DEFAULT_GLOBAL_ERROR_COMPONENT,
|
|
88
|
+
wrapsGlobalErrorBoundary: true,
|
|
88
89
|
children: createElement(ErrorBoundary, {
|
|
89
90
|
fallback: GlobalErrorComponent,
|
|
91
|
+
isGlobalErrorBoundary: true,
|
|
90
92
|
children
|
|
91
93
|
})
|
|
92
94
|
});
|
|
@@ -166,6 +166,7 @@ export type DispatchAppPageOptions<TRoute extends AppPageDispatchRoute> = {
|
|
|
166
166
|
buildPageElement: (route: TRoute, params: AppPageParams, opts: AppPageDispatchInterceptOptions | undefined, searchParams: URLSearchParams, options?: {
|
|
167
167
|
isForceStatic?: boolean;
|
|
168
168
|
isUncacheableRender?: boolean;
|
|
169
|
+
routeTreeOnlyPrefetchShell?: boolean;
|
|
169
170
|
/** Layouts the navigating client holds, which the render may leave out. */
|
|
170
171
|
mountedLayouts?: ReadonlySet<string> | null;
|
|
171
172
|
observeMetadataSearchParamsAccess?: boolean;
|
|
@@ -293,7 +293,8 @@ async function dispatchAppPageInner(options) {
|
|
|
293
293
|
const isOnDemandRevalidate = _isOnDemandRevalidate();
|
|
294
294
|
const shouldReadCache = isStoredRender && !isOnDemandRevalidate;
|
|
295
295
|
const isCacheCandidate = isCacheEligibleRender && isStaticEligible && options.pprFallbackShell === void 0 && !isNeverStoredPath;
|
|
296
|
-
const
|
|
296
|
+
const routeTreeOnlyPrefetchShell = options.pprFallbackShell === void 0 && (options.pprRuntime === void 0 || !options.isProduction);
|
|
297
|
+
const isUncacheableRender = !(isCacheEligibleRender && isStaticEligible) && routeTreeOnlyPrefetchShell;
|
|
297
298
|
const mountedLayouts = isUncacheableRender && options.isRscRequest && (options.renderMode ?? "navigation") === "navigation" && options.interceptionContext === null && options.isProgressiveActionRender !== true ? parseMountedLayoutsHeader(options.request.headers.get(VINEXT_MOUNTED_LAYOUTS_HEADER)) : null;
|
|
298
299
|
if (shouldReadCache && isStaticEligible) {
|
|
299
300
|
traceOperation = resolveAppPageTraceOperation({
|
|
@@ -387,6 +388,7 @@ async function dispatchAppPageInner(options) {
|
|
|
387
388
|
isForceStatic: revalidationDynamicConfig === "force-static",
|
|
388
389
|
observeMetadataSearchParamsAccess: revalidationDynamicConfig !== "force-static",
|
|
389
390
|
observePageSearchParamsAccess: revalidationDynamicConfig !== "force-static",
|
|
391
|
+
routeTreeOnlyPrefetchShell,
|
|
390
392
|
serveStreamingMetadata: placeGeneratedMetadataInBody,
|
|
391
393
|
placeStreamedMetadataInHead: true,
|
|
392
394
|
onHeadPrepared(head) {
|
|
@@ -552,6 +554,7 @@ async function dispatchAppPageInner(options) {
|
|
|
552
554
|
observeMetadataSearchParamsAccess: interceptDynamicConfig !== "force-static",
|
|
553
555
|
observePageSearchParamsAccess: interceptDynamicConfig !== "force-static",
|
|
554
556
|
isUncacheableRender,
|
|
557
|
+
routeTreeOnlyPrefetchShell,
|
|
555
558
|
serveStreamingMetadata: placeGeneratedMetadataInBody,
|
|
556
559
|
placeStreamedMetadataInHead: options.renderWholeDocument === true,
|
|
557
560
|
onHeadPrepared
|
|
@@ -611,6 +614,7 @@ async function dispatchAppPageInner(options) {
|
|
|
611
614
|
observeMetadataSearchParamsAccess: !isForceStatic,
|
|
612
615
|
observePageSearchParamsAccess: !isForceStatic,
|
|
613
616
|
isUncacheableRender,
|
|
617
|
+
routeTreeOnlyPrefetchShell,
|
|
614
618
|
mountedLayouts: interceptResult.interceptOpts ? null : mountedLayouts,
|
|
615
619
|
serveStreamingMetadata: placeGeneratedMetadataInBody,
|
|
616
620
|
placeStreamedMetadataInHead: options.renderWholeDocument === true,
|
|
@@ -66,6 +66,8 @@ export type AppPagePageRequest<TModule extends AppPageModule = AppPageModule> =
|
|
|
66
66
|
isForceStatic?: boolean;
|
|
67
67
|
/** The render can never be stored (see buildAppPageElements). */
|
|
68
68
|
isUncacheableRender?: boolean;
|
|
69
|
+
/** A loading shell without a loading boundary is the route tree (see buildAppPageElements). */
|
|
70
|
+
routeTreeOnlyPrefetchShell?: boolean;
|
|
69
71
|
/** Layouts the navigating client holds (see buildAppPageElements). */
|
|
70
72
|
mountedLayouts?: ReadonlySet<string> | null;
|
|
71
73
|
/** Observe page metadata `searchParams` access for cache-safety classification. */
|
|
@@ -107,7 +107,7 @@ function traceAppPageInterceptLayoutModules(modules, branchSegments, layoutSegme
|
|
|
107
107
|
async function buildPageElements(options) {
|
|
108
108
|
const { route, params, routePath, displayPathname = routePath, pageRequest, globalErrorModule, rootNotFoundModule, rootForbiddenModule, rootUnauthorizedModule, metadataRoutes } = options;
|
|
109
109
|
const slotParamOverrides = resolveSlotParamOverrides(route, routePath);
|
|
110
|
-
const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false, isForceStatic = false, isUncacheableRender = false, mountedLayouts = null, serveStreamingMetadata, placeStreamedMetadataInHead = false, isProduction = process.env.NODE_ENV === "production", onHeadPrepared } = pageRequest;
|
|
110
|
+
const { opts, searchParams, isRscRequest, mountedSlotsHeader, renderMode = APP_RSC_RENDER_MODE_NAVIGATION, observeMetadataSearchParamsAccess = false, observePageSearchParamsAccess = false, isForceStatic = false, isUncacheableRender = false, routeTreeOnlyPrefetchShell = false, mountedLayouts = null, serveStreamingMetadata, placeStreamedMetadataInHead = false, isProduction = process.env.NODE_ENV === "production", onHeadPrepared } = pageRequest;
|
|
111
111
|
const pageModule = route.page;
|
|
112
112
|
const isSiblingIntercept = opts?.interceptSlotKey === "__vinext_page_intercept" && !!opts?.interceptPage;
|
|
113
113
|
const effectivePageModule = isSiblingIntercept ? opts.interceptPage : pageModule;
|
|
@@ -414,6 +414,7 @@ async function buildPageElements(options) {
|
|
|
414
414
|
globalErrorModule: globalErrorModule ?? DEFAULT_GLOBAL_ERROR_MODULE,
|
|
415
415
|
isRscRequest,
|
|
416
416
|
isUncacheableRender,
|
|
417
|
+
routeTreeOnlyPrefetchShell,
|
|
417
418
|
interceptionId: opts?.interceptionId ?? null,
|
|
418
419
|
mountedLayouts,
|
|
419
420
|
mountedSlotIds,
|
|
@@ -220,11 +220,7 @@ type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule,
|
|
|
220
220
|
isRscRequest?: boolean;
|
|
221
221
|
/**
|
|
222
222
|
* The render can never be stored and, in production, is never sent with
|
|
223
|
-
* static cache headers (see app-page-dispatch.ts)
|
|
224
|
-
* prefetch without a loading boundary may skip its layouts. A render that
|
|
225
|
-
* may be stored keeps them, so a layout's dynamic API read still keeps it
|
|
226
|
-
* out of the cache. An explicit CDN cache policy on a dynamic route can
|
|
227
|
-
* still store the route tree, as a CDN would store Next.js's.
|
|
223
|
+
* static cache headers (see app-page-dispatch.ts).
|
|
228
224
|
*/
|
|
229
225
|
isUncacheableRender?: boolean;
|
|
230
226
|
/**
|
|
@@ -236,6 +232,12 @@ type BuildAppPageElementsOptions<TModule extends AppPageModule = AppPageModule,
|
|
|
236
232
|
mountedLayouts?: ReadonlySet<string> | null;
|
|
237
233
|
mountedSlotIds?: ReadonlySet<string> | null;
|
|
238
234
|
renderIdentity?: AppPageRenderIdentity;
|
|
235
|
+
/**
|
|
236
|
+
* The render has no PPR (see app-page-dispatch.ts), so a loading-shell
|
|
237
|
+
* prefetch without a loading boundary sends only the route tree. Without it,
|
|
238
|
+
* the layouts render, as Next.js renders them with isRoutePPREnabled.
|
|
239
|
+
*/
|
|
240
|
+
routeTreeOnlyPrefetchShell?: boolean;
|
|
239
241
|
renderMode?: AppRscRenderMode;
|
|
240
242
|
routePath: string;
|
|
241
243
|
semanticPageIdentity?: Readonly<{
|
|
@@ -514,7 +514,7 @@ function buildAppPageElements(options) {
|
|
|
514
514
|
[pageElementId]: null,
|
|
515
515
|
[routeId]: null
|
|
516
516
|
};
|
|
517
|
-
if (isPrefetchLoadingShell && !shouldRenderPrefetchLoadingShell && options.
|
|
517
|
+
if (isPrefetchLoadingShell && !shouldRenderPrefetchLoadingShell && options.routeTreeOnlyPrefetchShell === true) return {
|
|
518
518
|
...metadataEntries,
|
|
519
519
|
...options.route.staticSiblings && options.route.staticSiblings.length > 0 ? { [APP_STATIC_SIBLINGS_KEY]: options.route.staticSiblings } : {},
|
|
520
520
|
[pageElementId]: null,
|
|
@@ -981,8 +981,10 @@ function buildAppPageElements(options) {
|
|
|
981
981
|
const globalErrorComponent = getErrorBoundaryExport(options.globalErrorModule);
|
|
982
982
|
routeChildren = /* @__PURE__ */ jsx(GlobalErrorBoundary, {
|
|
983
983
|
fallback: DEFAULT_GLOBAL_ERROR_COMPONENT,
|
|
984
|
+
wrapsGlobalErrorBoundary: globalErrorComponent !== null,
|
|
984
985
|
children: globalErrorComponent ? /* @__PURE__ */ jsx(ErrorBoundary, {
|
|
985
986
|
fallback: globalErrorComponent,
|
|
987
|
+
isGlobalErrorBoundary: true,
|
|
986
988
|
children: routeChildren
|
|
987
989
|
}) : routeChildren
|
|
988
990
|
});
|
|
@@ -57,6 +57,12 @@ type RenderPagesFallbackOptions = {
|
|
|
57
57
|
pathname?: string;
|
|
58
58
|
pagesDataRequest?: Request | null;
|
|
59
59
|
request: Request;
|
|
60
|
+
/**
|
|
61
|
+
* The basePath `request.url` still carries. The page renderer receives the
|
|
62
|
+
* URL without it, as in the Pages Router pipeline, so `req.url` and `asPath`
|
|
63
|
+
* leave it out like Next.js.
|
|
64
|
+
*/
|
|
65
|
+
requestBasePath?: string;
|
|
60
66
|
/** The shared cache entry answers every host; a request-time render is not stored. */
|
|
61
67
|
sharedAcrossHosts?: boolean;
|
|
62
68
|
url: URL;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
import { stripBasePath } from "../utils/base-path.js";
|
|
1
2
|
import { cloneRequestWithHeaders, cloneRequestWithUrl } from "./request-pipeline.js";
|
|
2
3
|
import { getRequestExecutionContext } from "../shims/request-context.js";
|
|
4
|
+
import { isLocaleRedirect, markLocaleRedirect } from "./pages-i18n.js";
|
|
3
5
|
import { beginRouteCacheability, markRouteCacheabilityDynamic } from "../shims/cacheability-classification.js";
|
|
4
6
|
import { mergeHeaders } from "./worker-utils.js";
|
|
5
7
|
import { pagesRouteHasPriorityOverAppRoute } from "./hybrid-route-priority.js";
|
|
@@ -18,7 +20,7 @@ function applyPagesMiddlewareContext(response, middlewareContext) {
|
|
|
18
20
|
* Fallback handler to route App Router requests to the Pages Router when no App Router route matches.
|
|
19
21
|
*/
|
|
20
22
|
async function renderPagesFallback(options, dependencies) {
|
|
21
|
-
const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, initialResponseHeaders, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, sharedAcrossHosts = false, url } = options;
|
|
23
|
+
const { allowRscDocumentFallback = false, appRouteMatch = null, isDataRequest = false, isRscRequest, initialResponseHeaders, matchKind, middlewareContext, pathname = options.url.pathname, pagesDataRequest = null, request, requestBasePath = "", sharedAcrossHosts = false, url } = options;
|
|
22
24
|
const { loadPagesEntry, buildRequestHeaders, applyRouteHandlerMiddlewareContext, getDraftModeCookieHeader } = dependencies;
|
|
23
25
|
if (isRscRequest && !allowRscDocumentFallback) return null;
|
|
24
26
|
const pagesEntry = await loadPagesEntry();
|
|
@@ -67,8 +69,10 @@ async function renderPagesFallback(options, dependencies) {
|
|
|
67
69
|
if (runtimeDataKind === "server" || runtimeDataKind === "initial") markRouteCacheabilityDynamic("getInitialProps render shares a cache entry across hosts");
|
|
68
70
|
}
|
|
69
71
|
const pagesRequest = claimPagesRequest();
|
|
72
|
+
const renderRequestUrl = new URL(pagesDataRequest?.url ?? pagesRequest.url);
|
|
73
|
+
if (!pagesDataRequest) renderRequestUrl.pathname = stripBasePath(renderRequestUrl.pathname, requestBasePath);
|
|
70
74
|
const renderArgs = [
|
|
71
|
-
|
|
75
|
+
renderRequestUrl.href === pagesRequest.url ? pagesRequest : cloneRequestWithUrl(pagesRequest, renderRequestUrl.href),
|
|
72
76
|
pagesUrl,
|
|
73
77
|
{},
|
|
74
78
|
getRequestExecutionContext() ?? void 0,
|
|
@@ -76,7 +80,8 @@ async function renderPagesFallback(options, dependencies) {
|
|
|
76
80
|
];
|
|
77
81
|
const pagesRes = isDataRequest ? await (initialResponseHeaders ? pagesEntry.renderPage(...renderArgs, { isDataReq: true }, initialResponseHeaders) : pagesEntry.renderPage(...renderArgs, { isDataReq: true })) : await (initialResponseHeaders ? pagesEntry.renderPage(...renderArgs, void 0, initialResponseHeaders) : pagesEntry.renderPage(...renderArgs));
|
|
78
82
|
if (pagesRes.status === 404 && pageMatch === null) return null;
|
|
79
|
-
|
|
83
|
+
const response = applyDraftModeCookie(applyPagesMiddlewareContext(pagesRes, middlewareContext), getDraftModeCookieHeader());
|
|
84
|
+
return isLocaleRedirect(pagesRes) ? markLocaleRedirect(response) : response;
|
|
80
85
|
}
|
|
81
86
|
/**
|
|
82
87
|
* Append a middleware-emitted `__prerender_bypass` Set-Cookie header to a Pages
|
|
@@ -9,7 +9,7 @@ import "./server-globals.js";
|
|
|
9
9
|
import { getExplicitCdnCacheAdapter } from "../shims/cdn-cache-state.js";
|
|
10
10
|
import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
|
|
11
11
|
import { registerLazyDataCacheHandler } from "../shims/cache-handler.js";
|
|
12
|
-
import {
|
|
12
|
+
import { readImageOptimizationSignal } from "./image-optimization.js";
|
|
13
13
|
import { consumeFrameworkRequestRoute, traceFrameworkRequest } from "./request-tracing.js";
|
|
14
14
|
import { createStaticAssetRequest, resolveStaticAssetSignal } from "./worker-utils.js";
|
|
15
15
|
import { readTrustedPrerenderStateFromHeaders } from "./prerender-route-params.js";
|
|
@@ -75,7 +75,6 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
|
|
|
75
75
|
if (cdnValidationResponse) return cdnValidationResponse;
|
|
76
76
|
}
|
|
77
77
|
const url = new URL(request.url);
|
|
78
|
-
const servesImages = Boolean(assets) && getImageOptimizer() !== null;
|
|
79
78
|
const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
|
|
80
79
|
if (protocolRelativeGuard) return protocolRelativeGuard;
|
|
81
80
|
try {
|
|
@@ -104,7 +103,7 @@ async function handleRequest(request, env, platformCtx, dispatchResponseStage, a
|
|
|
104
103
|
};
|
|
105
104
|
const handle = () => requestRscHandler(request, ctx, trackedDispatchResponseStage, probeMode, ctx.isPrerenderPathDiscovery === true, trustedPrerenderState);
|
|
106
105
|
let response = await runWithExecutionContext(ctx, handle);
|
|
107
|
-
const imageSignal =
|
|
106
|
+
const imageSignal = assets ? readImageOptimizationSignal(response) : null;
|
|
108
107
|
if (imageSignal && assets) {
|
|
109
108
|
const { fetchSignalledPublicFile, serveWorkerImageOptimization } = await import("./worker-image-optimization.js");
|
|
110
109
|
response = await serveWorkerImageOptimization(request, imageSignal, __imageAllowedWidths, __imageConfig, {
|
|
@@ -8,7 +8,7 @@ import { runWithExecutionContext } from "../shims/request-context.js";
|
|
|
8
8
|
import "./server-globals.js";
|
|
9
9
|
import { getCdnCacheAdapter } from "../shims/cdn-cache.js";
|
|
10
10
|
import { applyCdnResponseIdentityHeaders, validateCdnRequest } from "./cache-control.js";
|
|
11
|
-
import {
|
|
11
|
+
import { readImageOptimizationSignal } from "./image-optimization.js";
|
|
12
12
|
import { traceFrameworkRequest } from "./request-tracing.js";
|
|
13
13
|
import { createStaticAssetRequest, resolveStaticAssetSignal } from "./worker-utils.js";
|
|
14
14
|
import { readTrustedPrerenderRouteParams, serializePrerenderRouteParamsHeader } from "./prerender-route-params.js";
|
|
@@ -83,7 +83,6 @@ async function handleRequest(request, env, platformCtx) {
|
|
|
83
83
|
const cdnValidationResponse = await validateCdnRequest(request);
|
|
84
84
|
if (cdnValidationResponse) return cdnValidationResponse;
|
|
85
85
|
const url = new URL(request.url);
|
|
86
|
-
const servesImages = Boolean(assets) && getImageOptimizer() !== null;
|
|
87
86
|
const protocolRelativeGuard = guardProtocolRelativeUrl(url.pathname, url.search);
|
|
88
87
|
if (protocolRelativeGuard) return protocolRelativeGuard;
|
|
89
88
|
try {
|
|
@@ -109,7 +108,7 @@ async function handleRequest(request, env, platformCtx) {
|
|
|
109
108
|
const result = await (ctx ? runWithExecutionContext(ctx, handleFn) : handleFn());
|
|
110
109
|
if (result instanceof Response) {
|
|
111
110
|
let response = result;
|
|
112
|
-
const imageSignal =
|
|
111
|
+
const imageSignal = assets ? readImageOptimizationSignal(response) : null;
|
|
113
112
|
if (imageSignal && assets) {
|
|
114
113
|
const { fetchSignalledPublicFile, serveWorkerImageOptimization } = await import("./worker-image-optimization.js");
|
|
115
114
|
response = await serveWorkerImageOptimization(request, imageSignal, __imageAllowedWidths, __imageConfig, {
|
|
@@ -78,6 +78,14 @@ export declare function createRscRequestHeaders(options?: CreateRscRequestHeader
|
|
|
78
78
|
* their bytes can legitimately differ from the destination's full route.
|
|
79
79
|
*/
|
|
80
80
|
export declare function canonicalizePrewarmableRscRequestHeaders(headers: Headers): boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Convert a search-param shell prefetch to the canonical navigation of its
|
|
83
|
+
* page. The shell renders the page with an empty query (app-page-dispatch.ts),
|
|
84
|
+
* which is what the query-free navigation renders, as Next.js's static
|
|
85
|
+
* prefetch of a page segment never varies on search params. The caller drops
|
|
86
|
+
* the query from the URL.
|
|
87
|
+
*/
|
|
88
|
+
export declare function canonicalizeDynamicShellRscRequestHeaders(headers: Headers): boolean;
|
|
81
89
|
/**
|
|
82
90
|
* Convert an ordinary loading-boundary prefetch to the shared loading-shell
|
|
83
91
|
* variant. The payload is selected by the three retained mode headers; visible
|