vinext 0.1.2 → 0.1.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/dist/build/prerender.d.ts +9 -1
- package/dist/build/prerender.js +41 -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/vinext-next-data.d.ts +18 -1
- 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.js +73 -14
- package/dist/config/next-config.d.ts +46 -4
- package/dist/config/next-config.js +147 -48
- package/dist/deploy.d.ts +30 -11
- package/dist/deploy.js +180 -99
- 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 +64 -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 +53 -8
- package/dist/entries/pages-server-entry.js +41 -5
- package/dist/index.js +200 -62
- package/dist/plugins/extensionless-dynamic-import.d.ts +6 -0
- package/dist/plugins/extensionless-dynamic-import.js +152 -0
- 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/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 +44 -14
- 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 +19 -10
- package/dist/server/app-browser-entry.js +167 -90
- 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 +4 -2
- 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-stream.js +86 -43
- 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 +18 -0
- package/dist/server/app-pages-bridge.js +22 -5
- 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 +25 -0
- package/dist/server/app-rsc-handler.js +154 -54
- package/dist/server/app-rsc-route-matching.d.ts +3 -0
- package/dist/server/app-rsc-route-matching.js +2 -0
- 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 +42 -13
- package/dist/server/app-ssr-entry.d.ts +2 -0
- package/dist/server/app-ssr-entry.js +83 -10
- package/dist/server/cache-control.js +4 -0
- package/dist/server/dev-server.d.ts +2 -2
- package/dist/server/dev-server.js +244 -51
- 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/navigation-planner.d.ts +133 -30
- package/dist/server/navigation-planner.js +114 -0
- package/dist/server/navigation-trace.d.ts +8 -1
- package/dist/server/navigation-trace.js +8 -1
- 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 +8 -1
- package/dist/server/pages-data-route.js +11 -2
- 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-node-compat.js +2 -2
- package/dist/server/pages-page-data.d.ts +11 -2
- package/dist/server/pages-page-data.js +204 -33
- package/dist/server/pages-page-handler.d.ts +4 -2
- package/dist/server/pages-page-handler.js +59 -22
- package/dist/server/pages-page-response.d.ts +2 -1
- package/dist/server/pages-page-response.js +7 -4
- package/dist/server/pages-request-pipeline.d.ts +1 -0
- package/dist/server/pages-request-pipeline.js +73 -36
- 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.js +9 -3
- 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/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/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/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/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-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 +12 -5
- package/dist/shims/navigation.d.ts +8 -2
- package/dist/shims/navigation.js +61 -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 +13 -2
- package/dist/shims/router.js +419 -128
- 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/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/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
|
@@ -22,7 +22,8 @@ type PrerenderRouteResult = {
|
|
|
22
22
|
* Omitted for non-dynamic routes where pattern === path.
|
|
23
23
|
*/
|
|
24
24
|
path?: string; /** Which router produced this route. Used by cache seeding. */
|
|
25
|
-
router: "app" | "pages";
|
|
25
|
+
router: "app" | "pages"; /** Set to true when this is a PPR fallback shell. */
|
|
26
|
+
fallback?: boolean;
|
|
26
27
|
} | {
|
|
27
28
|
route: string;
|
|
28
29
|
status: "skipped";
|
|
@@ -31,6 +32,13 @@ type PrerenderRouteResult = {
|
|
|
31
32
|
route: string;
|
|
32
33
|
status: "error";
|
|
33
34
|
error: string;
|
|
35
|
+
/**
|
|
36
|
+
* Set when the error must fail the build in ALL modes (default included),
|
|
37
|
+
* not just `output: 'export'`. Used for a thrown generateStaticParams /
|
|
38
|
+
* getStaticPaths, which Next.js treats as a fatal build error rather than a
|
|
39
|
+
* silently-skipped route. Refs cloudflare/vinext#1982
|
|
40
|
+
*/
|
|
41
|
+
fatal?: true;
|
|
34
42
|
};
|
|
35
43
|
/** Called after each route is resolved (rendered, skipped, or error). */
|
|
36
44
|
type PrerenderProgressCallback = (update: {
|
package/dist/build/prerender.js
CHANGED
|
@@ -7,11 +7,11 @@ import { classifyAppRoute, classifyPagesRoute, getAppRouteRenderEntryPath } from
|
|
|
7
7
|
import { BLOCKED_PAGES } from "../shims/constants.js";
|
|
8
8
|
import { concatUint8Arrays, decodeRscEmbeddedChunk } from "../server/app-rsc-embedded-chunks.js";
|
|
9
9
|
import { navigationRuntimeRscBootstrapExpression } from "../server/app-ssr-stream.js";
|
|
10
|
+
import { createAppPprFallbackShells, markAppPprDynamicFallbackShellHtml } from "../server/app-ppr-fallback-shell.js";
|
|
10
11
|
import { encodePrerenderRouteParams, serializePrerenderRouteParamsHeader } from "../server/prerender-route-params.js";
|
|
11
12
|
import { readPrerenderSecret } from "./server-manifest.js";
|
|
12
13
|
import { getOutputPath, getRscOutputPath } from "../utils/prerender-output-paths.js";
|
|
13
14
|
import { startProdServer } from "../server/prod-server.js";
|
|
14
|
-
import { createAppPprFallbackShells } from "../server/app-ppr-fallback-shell.js";
|
|
15
15
|
import fs from "node:fs";
|
|
16
16
|
import path from "node:path";
|
|
17
17
|
import os from "node:os";
|
|
@@ -33,9 +33,21 @@ import os from "node:os";
|
|
|
33
33
|
* 'default' — skips SSR routes (served at request time); ISR routes rendered
|
|
34
34
|
* 'export' — SSR routes are build errors; ISR treated as static (no revalidate)
|
|
35
35
|
*/
|
|
36
|
+
const EXPERIMENTAL_PPR_FALLBACK_SHELLS_ENV = "__VINEXT_EXPERIMENTAL_PPR_FALLBACK_SHELLS";
|
|
37
|
+
function isExperimentalPprFallbackShellGenerationEnabled(env = process.env) {
|
|
38
|
+
return env[EXPERIMENTAL_PPR_FALLBACK_SHELLS_ENV] === "1";
|
|
39
|
+
}
|
|
36
40
|
function getErrorMessageWithStack(err) {
|
|
37
41
|
return err.stack || err.message;
|
|
38
42
|
}
|
|
43
|
+
var PrerenderUserFunctionError = class extends Error {};
|
|
44
|
+
function parsePrerenderEndpointError(text) {
|
|
45
|
+
try {
|
|
46
|
+
const parsed = JSON.parse(text);
|
|
47
|
+
if (parsed && typeof parsed === "object" && "error" in parsed) return typeof parsed.error === "string" && parsed.error.length > 0 ? parsed.error : "Unknown prerender endpoint error";
|
|
48
|
+
} catch {}
|
|
49
|
+
return text || "Unknown prerender endpoint error";
|
|
50
|
+
}
|
|
39
51
|
/** Sentinel path used to trigger 404 rendering without a real route match. */
|
|
40
52
|
const NOT_FOUND_SENTINEL_PATH = "/__vinext_nonexistent_for_404__";
|
|
41
53
|
const DEFAULT_CONCURRENCY = Math.min(os.availableParallelism(), 8);
|
|
@@ -275,6 +287,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
275
287
|
const res = await fetch(`${baseUrl}/__vinext/prerender/pages-static-paths?${search}`, { headers: secretHeaders });
|
|
276
288
|
const text = await res.text();
|
|
277
289
|
if (!res.ok) {
|
|
290
|
+
if (res.status === 500) throw new PrerenderUserFunctionError(parsePrerenderEndpointError(text));
|
|
278
291
|
console.warn(`[vinext] Warning: /__vinext/prerender/pages-static-paths returned ${res.status} for ${r.pattern}. Dynamic paths will be skipped. This may indicate a stale or missing prerender secret.`);
|
|
279
292
|
return {
|
|
280
293
|
paths: [],
|
|
@@ -322,10 +335,21 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
322
335
|
});
|
|
323
336
|
continue;
|
|
324
337
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
338
|
+
let pathsResult;
|
|
339
|
+
try {
|
|
340
|
+
pathsResult = await route.module.getStaticPaths({
|
|
341
|
+
locales: [],
|
|
342
|
+
defaultLocale: ""
|
|
343
|
+
});
|
|
344
|
+
} catch (e) {
|
|
345
|
+
results.push({
|
|
346
|
+
route: route.pattern,
|
|
347
|
+
status: "error",
|
|
348
|
+
error: `Failed to call getStaticPaths(): ${e.message}`,
|
|
349
|
+
...e instanceof PrerenderUserFunctionError ? { fatal: true } : {}
|
|
350
|
+
});
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
329
353
|
const fallback = pathsResult?.fallback ?? false;
|
|
330
354
|
if (mode === "export" && fallback !== false) {
|
|
331
355
|
results.push({
|
|
@@ -521,6 +545,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
521
545
|
const res = await fetch(`${baseUrl}/__vinext/prerender/static-params?${search}`, { headers: secretHeaders });
|
|
522
546
|
const text = await res.text();
|
|
523
547
|
if (!res.ok) {
|
|
548
|
+
if (res.status === 500) throw new PrerenderUserFunctionError(parsePrerenderEndpointError(text));
|
|
524
549
|
console.warn(`[vinext] Warning: /__vinext/prerender/static-params returned ${res.status} for ${pattern}. Static params will be skipped. This may indicate a stale or missing prerender secret.`);
|
|
525
550
|
return null;
|
|
526
551
|
}
|
|
@@ -642,7 +667,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
642
667
|
revalidate,
|
|
643
668
|
isSpeculative: false
|
|
644
669
|
});
|
|
645
|
-
if (config.cacheComponents === true) for (const fallbackShell of createAppPprFallbackShells(route, params)) {
|
|
670
|
+
if (config.cacheComponents === true && isExperimentalPprFallbackShellGenerationEnabled()) for (const fallbackShell of createAppPprFallbackShells(route, params)) {
|
|
646
671
|
if (queuedRouteUrls.has(fallbackShell.pathname)) continue;
|
|
647
672
|
queuedRouteUrls.add(fallbackShell.pathname);
|
|
648
673
|
urlsToRender.push({
|
|
@@ -650,7 +675,8 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
650
675
|
routePattern: route.pattern,
|
|
651
676
|
prerenderRouteParams: encodePrerenderRouteParams(route.pattern, fallbackShell.params, fallbackShell.fallbackParamNames),
|
|
652
677
|
revalidate,
|
|
653
|
-
isSpeculative: false
|
|
678
|
+
isSpeculative: false,
|
|
679
|
+
isFallback: true
|
|
654
680
|
});
|
|
655
681
|
}
|
|
656
682
|
}
|
|
@@ -660,7 +686,8 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
660
686
|
results.push({
|
|
661
687
|
route: route.pattern,
|
|
662
688
|
status: "error",
|
|
663
|
-
error: `Failed to call generateStaticParams(): ${detail}
|
|
689
|
+
error: `Failed to call generateStaticParams(): ${detail}`,
|
|
690
|
+
...e instanceof PrerenderUserFunctionError ? { fatal: true } : {}
|
|
664
691
|
});
|
|
665
692
|
}
|
|
666
693
|
else if (type === "unknown") urlsToRender.push({
|
|
@@ -684,7 +711,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
684
711
|
* exactly once per URL after this function returns, keeping the callback
|
|
685
712
|
* at a single, predictable call site.
|
|
686
713
|
*/
|
|
687
|
-
async function renderUrl({ urlPath, routePattern, prerenderRouteParams, revalidate, isSpeculative }) {
|
|
714
|
+
async function renderUrl({ urlPath, routePattern, prerenderRouteParams, revalidate, isSpeculative, isFallback }) {
|
|
688
715
|
try {
|
|
689
716
|
const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParams);
|
|
690
717
|
const htmlHeaders = new Headers();
|
|
@@ -736,7 +763,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
736
763
|
status: "error",
|
|
737
764
|
error: "RSC handler returned no prerender HTML"
|
|
738
765
|
};
|
|
739
|
-
const html = htmlRender.html;
|
|
766
|
+
const html = isFallback ? markAppPprDynamicFallbackShellHtml(htmlRender.html) : htmlRender.html;
|
|
740
767
|
let rscData = extractRscPayloadFromPrerenderedHtml(html);
|
|
741
768
|
if (rscData === null) {
|
|
742
769
|
const rscHeaders = new Headers({
|
|
@@ -772,7 +799,8 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
772
799
|
revalidate: renderedRevalidate,
|
|
773
800
|
...typeof renderedRevalidate === "number" ? { expire: renderedCacheControl.expire } : {},
|
|
774
801
|
router: "app",
|
|
775
|
-
...urlPath !== routePattern ? { path: urlPath } : {}
|
|
802
|
+
...urlPath !== routePattern ? { path: urlPath } : {},
|
|
803
|
+
...isFallback ? { fallback: true } : {}
|
|
776
804
|
};
|
|
777
805
|
} catch (e) {
|
|
778
806
|
if (isSpeculative) return {
|
|
@@ -878,7 +906,8 @@ function writePrerenderIndex(routes, outDir, options) {
|
|
|
878
906
|
revalidate: r.revalidate,
|
|
879
907
|
...typeof r.revalidate === "number" ? { expire: r.expire } : {},
|
|
880
908
|
router: r.router,
|
|
881
|
-
...r.path ? { path: r.path } : {}
|
|
909
|
+
...r.path ? { path: r.path } : {},
|
|
910
|
+
...r.fallback ? { fallback: true } : {}
|
|
882
911
|
};
|
|
883
912
|
if (r.status === "skipped") return {
|
|
884
913
|
route: r.route,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ResolvedNextConfig } from "../config/next-config.js";
|
|
2
|
-
import { PrerenderResult } from "./prerender.js";
|
|
2
|
+
import { PrerenderResult, PrerenderRouteResult } from "./prerender.js";
|
|
3
3
|
|
|
4
4
|
//#region src/build/run-prerender.d.ts
|
|
5
5
|
type RunPrerenderOptions = {
|
|
@@ -48,6 +48,14 @@ type RunPrerenderOptions = {
|
|
|
48
48
|
* If a required production bundle does not exist, an error is thrown directing
|
|
49
49
|
* the user to run `vinext build` first.
|
|
50
50
|
*/
|
|
51
|
+
/**
|
|
52
|
+
* Throw if any route is a `fatal` error (a thrown generateStaticParams /
|
|
53
|
+
* getStaticPaths). These fail the build in ALL modes — default included —
|
|
54
|
+
* matching `next build`, unlike intentionally-skipped dynamic/SSR routes and
|
|
55
|
+
* non-fatal errors (e.g. transport failures), which only fail under
|
|
56
|
+
* `output: 'export'`. Exported for direct unit testing. Refs cloudflare/vinext#1982
|
|
57
|
+
*/
|
|
58
|
+
declare function assertNoFatalPrerenderRoutes(routes: readonly PrerenderRouteResult[]): void;
|
|
51
59
|
declare function runPrerender(options: RunPrerenderOptions): Promise<PrerenderResult | null>;
|
|
52
60
|
//#endregion
|
|
53
|
-
export { runPrerender };
|
|
61
|
+
export { assertNoFatalPrerenderRoutes, runPrerender };
|
|
@@ -82,6 +82,19 @@ function readBuiltBuildId(serverDir) {
|
|
|
82
82
|
* If a required production bundle does not exist, an error is thrown directing
|
|
83
83
|
* the user to run `vinext build` first.
|
|
84
84
|
*/
|
|
85
|
+
/**
|
|
86
|
+
* Throw if any route is a `fatal` error (a thrown generateStaticParams /
|
|
87
|
+
* getStaticPaths). These fail the build in ALL modes — default included —
|
|
88
|
+
* matching `next build`, unlike intentionally-skipped dynamic/SSR routes and
|
|
89
|
+
* non-fatal errors (e.g. transport failures), which only fail under
|
|
90
|
+
* `output: 'export'`. Exported for direct unit testing. Refs cloudflare/vinext#1982
|
|
91
|
+
*/
|
|
92
|
+
function assertNoFatalPrerenderRoutes(routes) {
|
|
93
|
+
const fatalRoutes = routes.filter((r) => r.status === "error" && r.fatal === true);
|
|
94
|
+
if (fatalRoutes.length === 0) return;
|
|
95
|
+
const fatalList = fatalRoutes.map((r) => ` ${r.route}: ${r.error}`).join("\n");
|
|
96
|
+
throw new Error(`Prerender failed: ${fatalRoutes.length} route${fatalRoutes.length !== 1 ? "s" : ""} errored during static generation.\n${fatalList}`);
|
|
97
|
+
}
|
|
85
98
|
async function runPrerender(options) {
|
|
86
99
|
const { root } = options;
|
|
87
100
|
const appDir = findDir(root, "app", "src/app");
|
|
@@ -197,6 +210,7 @@ async function runPrerender(options) {
|
|
|
197
210
|
} finally {
|
|
198
211
|
progress.finish(rendered, skipped, errors);
|
|
199
212
|
}
|
|
213
|
+
assertNoFatalPrerenderRoutes(allRoutes);
|
|
200
214
|
if (mode === "export" && errors > 0) {
|
|
201
215
|
const errorRoutes = allRoutes.filter((r) => r.status === "error").map((r) => ` ${r.route}: ${r.error}`).join("\n");
|
|
202
216
|
throw new Error(`Static export failed: ${errors} route${errors !== 1 ? "s" : ""} cannot be statically exported.\n${errorRoutes}\n\nRemove server-side data fetching (getServerSideProps, force-dynamic, revalidate) from these routes, or remove \`output: "export"\` from next.config.js.`);
|
|
@@ -207,4 +221,4 @@ async function runPrerender(options) {
|
|
|
207
221
|
};
|
|
208
222
|
}
|
|
209
223
|
//#endregion
|
|
210
|
-
export { runPrerender };
|
|
224
|
+
export { assertNoFatalPrerenderRoutes, runPrerender };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
//#region src/client/app-nav-failure-handler.d.ts
|
|
2
|
+
declare function stageAppNavigationFailureTarget(href: string): void;
|
|
3
|
+
declare function getAppNavigationFailureTarget(href: string): URL | null;
|
|
4
|
+
declare function clearAppNavigationFailureTarget(target?: string | URL): void;
|
|
5
|
+
declare function handleAppNavigationFailure(error: unknown): boolean;
|
|
6
|
+
declare function installAppNavigationFailureListeners(): () => void;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { clearAppNavigationFailureTarget, getAppNavigationFailureTarget, handleAppNavigationFailure, installAppNavigationFailureListeners, stageAppNavigationFailureTarget };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { installWindowNext } from "./window-next.js";
|
|
2
|
+
//#region src/client/app-nav-failure-handler.ts
|
|
3
|
+
function getPendingUrl() {
|
|
4
|
+
if (typeof window === "undefined") return null;
|
|
5
|
+
return window.next?.__pendingUrl ?? null;
|
|
6
|
+
}
|
|
7
|
+
function stageAppNavigationFailureTarget(href) {
|
|
8
|
+
if (!process.env.__NEXT_APP_NAV_FAIL_HANDLING || typeof window === "undefined") return;
|
|
9
|
+
installWindowNext({ __pendingUrl: new URL(href, window.location.href) });
|
|
10
|
+
}
|
|
11
|
+
function getAppNavigationFailureTarget(href) {
|
|
12
|
+
const pendingUrl = getPendingUrl();
|
|
13
|
+
if (pendingUrl === null || typeof window === "undefined") return null;
|
|
14
|
+
return pendingUrl.href === new URL(href, window.location.href).href ? pendingUrl : null;
|
|
15
|
+
}
|
|
16
|
+
function clearAppNavigationFailureTarget(target) {
|
|
17
|
+
if (typeof window === "undefined" || window.next?.__pendingUrl === void 0) return;
|
|
18
|
+
if (target instanceof URL) {
|
|
19
|
+
if (window.next.__pendingUrl !== target) return;
|
|
20
|
+
} else if (target !== void 0 && window.next.__pendingUrl.href !== new URL(target, window.location.href).href) return;
|
|
21
|
+
delete window.next.__pendingUrl;
|
|
22
|
+
}
|
|
23
|
+
function handleAppNavigationFailure(error) {
|
|
24
|
+
if (!process.env.__NEXT_APP_NAV_FAIL_HANDLING || typeof window === "undefined") return false;
|
|
25
|
+
const pendingUrl = getPendingUrl();
|
|
26
|
+
if (pendingUrl === null || pendingUrl.href === window.location.href) return false;
|
|
27
|
+
console.error("Error occurred during navigation, falling back to hard navigation", error);
|
|
28
|
+
window.location.assign(pendingUrl.href);
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
function installAppNavigationFailureListeners() {
|
|
32
|
+
if (!process.env.__NEXT_APP_NAV_FAIL_HANDLING || typeof window === "undefined") return () => {};
|
|
33
|
+
const listener = (event) => {
|
|
34
|
+
handleAppNavigationFailure("reason" in event ? event.reason : event.error);
|
|
35
|
+
};
|
|
36
|
+
window.addEventListener("error", listener);
|
|
37
|
+
window.addEventListener("unhandledrejection", listener);
|
|
38
|
+
return () => {
|
|
39
|
+
window.removeEventListener("error", listener);
|
|
40
|
+
window.removeEventListener("unhandledrejection", listener);
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//#endregion
|
|
44
|
+
export { clearAppNavigationFailureTarget, getAppNavigationFailureTarget, handleAppNavigationFailure, installAppNavigationFailureListeners, stageAppNavigationFailureTarget };
|
|
@@ -3,6 +3,23 @@ import { NEXT_DATA } from "../shims/internal/utils.js";
|
|
|
3
3
|
//#region src/client/vinext-next-data.d.ts
|
|
4
4
|
type VinextLinkPrefetchRoute = {
|
|
5
5
|
canPrefetchLoadingShell: boolean;
|
|
6
|
+
documentOnly?: boolean;
|
|
7
|
+
isDynamic: boolean;
|
|
8
|
+
patternParts: string[];
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Pages Router route pattern exposed to the client so the App Router's
|
|
12
|
+
* navigation runtime can decide whether a soft-navigated URL should be
|
|
13
|
+
* handled by Pages (hard nav) or App (RSC). Mirrors the public shape of
|
|
14
|
+
* `VinextLinkPrefetchRoute` so a single trie matcher handles both.
|
|
15
|
+
*
|
|
16
|
+
* `canPrefetchLoadingShell` is always `false` for Pages routes — Pages
|
|
17
|
+
* does not have a separate loading boundary and its prefetch surface is
|
|
18
|
+
* `_next/data/<buildId>/<page>.json`.
|
|
19
|
+
*/
|
|
20
|
+
type VinextPagesLinkPrefetchRoute = {
|
|
21
|
+
canPrefetchLoadingShell: false;
|
|
22
|
+
documentOnly?: boolean;
|
|
6
23
|
isDynamic: boolean;
|
|
7
24
|
patternParts: string[];
|
|
8
25
|
};
|
|
@@ -24,4 +41,4 @@ declare function extractVinextNextDataJson(html: string): string | null;
|
|
|
24
41
|
declare function parseVinextNextDataJson(json: string): BrowserVinextNextData;
|
|
25
42
|
declare function applyVinextLocaleGlobals(target: VinextLocaleGlobalTarget, nextData: VinextNextData): void;
|
|
26
43
|
//#endregion
|
|
27
|
-
export { VinextLinkPrefetchRoute, VinextNextData, applyVinextLocaleGlobals, extractVinextNextDataJson, parseVinextNextDataJson };
|
|
44
|
+
export { VinextLinkPrefetchRoute, VinextNextData, VinextPagesLinkPrefetchRoute, applyVinextLocaleGlobals, extractVinextNextDataJson, parseVinextNextDataJson };
|
|
@@ -163,5 +163,6 @@ type WindowNext = {
|
|
|
163
163
|
* resets state.
|
|
164
164
|
*/
|
|
165
165
|
declare function installWindowNext(fields: Partial<WindowNext>): void;
|
|
166
|
+
declare function setWindowNextInternalSourcePage(sourcePage: string | null): void;
|
|
166
167
|
//#endregion
|
|
167
|
-
export { PagesRouterPublicInstance, installWindowNext };
|
|
168
|
+
export { PagesRouterPublicInstance, installWindowNext, setWindowNextInternalSourcePage };
|
|
@@ -42,5 +42,16 @@ function installWindowNext(fields) {
|
|
|
42
42
|
...fields
|
|
43
43
|
};
|
|
44
44
|
}
|
|
45
|
+
function setWindowNextInternalSourcePage(sourcePage) {
|
|
46
|
+
if (typeof window === "undefined") return;
|
|
47
|
+
installWindowNext({});
|
|
48
|
+
if (sourcePage === null) {
|
|
49
|
+
delete window.next?.__internal_src_page;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const next = window.next;
|
|
53
|
+
if (!next) return;
|
|
54
|
+
next.__internal_src_page = sourcePage;
|
|
55
|
+
}
|
|
45
56
|
//#endregion
|
|
46
|
-
export { installWindowNext };
|
|
57
|
+
export { installWindowNext, setWindowNextInternalSourcePage };
|
|
@@ -73,7 +73,12 @@ var CloudflareCdnCacheAdapter = class {
|
|
|
73
73
|
async set(_key, _data, _ctx) {}
|
|
74
74
|
buildResponseHeaders(input) {
|
|
75
75
|
if (!input.cacheControl) return { "Cache-Control": NO_STORE };
|
|
76
|
-
if (/\b(?:no-store|no-cache|private)\b/.test(input.cacheControl)) return {
|
|
76
|
+
if (/\b(?:no-store|no-cache|private)\b/.test(input.cacheControl)) return {
|
|
77
|
+
"Cache-Control": input.cacheControl,
|
|
78
|
+
"CDN-Cache-Control": null,
|
|
79
|
+
"Cloudflare-CDN-Cache-Control": null,
|
|
80
|
+
"Cache-Tag": null
|
|
81
|
+
};
|
|
77
82
|
const headers = {
|
|
78
83
|
"Cache-Control": BROWSER_REVALIDATE,
|
|
79
84
|
"CDN-Cache-Control": toEdgeCacheControl(input.cacheControl)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { VINEXT_MW_CTX_HEADER, VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../server/headers.js";
|
|
2
2
|
import { buildRequestHeadersFromMiddlewareResponse } from "../server/middleware-request-headers.js";
|
|
3
|
+
import { parseCookieHeader } from "../utils/parse-cookie.js";
|
|
3
4
|
//#region src/config/config-matchers.ts
|
|
4
5
|
/**
|
|
5
6
|
* Cache for compiled regex patterns in matchConfigPattern.
|
|
@@ -343,16 +344,7 @@ function shouldEvaluateRule(ruleBasePath, state) {
|
|
|
343
344
|
* Parse a Cookie header string into a key-value record.
|
|
344
345
|
*/
|
|
345
346
|
function parseCookies(cookieHeader) {
|
|
346
|
-
|
|
347
|
-
const cookies = {};
|
|
348
|
-
for (const part of cookieHeader.split(";")) {
|
|
349
|
-
const eq = part.indexOf("=");
|
|
350
|
-
if (eq === -1) continue;
|
|
351
|
-
const key = part.slice(0, eq).trim();
|
|
352
|
-
const value = part.slice(eq + 1).trim();
|
|
353
|
-
if (key) cookies[key] = value;
|
|
354
|
-
}
|
|
355
|
-
return cookies;
|
|
347
|
+
return parseCookieHeader(cookieHeader);
|
|
356
348
|
}
|
|
357
349
|
/**
|
|
358
350
|
* Build a RequestContext from a Web Request object.
|
|
@@ -442,8 +434,8 @@ function matchSingleCondition(condition, ctx) {
|
|
|
442
434
|
return _matchConditionValue(headerValue, condition.value);
|
|
443
435
|
}
|
|
444
436
|
case "cookie": {
|
|
437
|
+
if (!Object.hasOwn(ctx.cookies, condition.key)) return null;
|
|
445
438
|
const cookieValue = ctx.cookies[condition.key];
|
|
446
|
-
if (cookieValue === void 0) return null;
|
|
447
439
|
return _matchConditionValue(cookieValue, condition.value);
|
|
448
440
|
}
|
|
449
441
|
case "query": {
|
|
@@ -541,7 +533,7 @@ function matchConfigPattern(pathname, pattern) {
|
|
|
541
533
|
pathname = stripTrailingSlashForConfigMatch(pathname);
|
|
542
534
|
const catchAllAnchor = /:[\w-]+[*+]/.test(pattern);
|
|
543
535
|
const namedParamCount = (pattern.match(/:[\w-]+/g) || []).length;
|
|
544
|
-
if (pattern.includes("(") || pattern.includes("\\") || /:[\w-]+[*+][^/]/.test(pattern) || /:[\w-]+\./.test(pattern) || catchAllAnchor && namedParamCount > 1) try {
|
|
536
|
+
if (pattern.includes("(") || pattern.includes("\\") || /:[\w-]+[*+][^/]/.test(pattern) || /:[\w-]+\./.test(pattern) || /[^/]:[\w-]+/.test(pattern) || catchAllAnchor && namedParamCount > 1) try {
|
|
545
537
|
const compiled = getCachedRegex(_compiledPatternCache, pattern, () => {
|
|
546
538
|
const paramNames = [];
|
|
547
539
|
let regexStr = "";
|
|
@@ -716,10 +708,11 @@ function matchRewrite(pathname, rewrites, ctx, basePathState = _BASEPATH_DEFAULT
|
|
|
716
708
|
if (params) {
|
|
717
709
|
const conditionParams = rewrite.has || rewrite.missing ? collectConditionParams(rewrite.has, rewrite.missing, ctx) : _emptyParams();
|
|
718
710
|
if (!conditionParams) continue;
|
|
719
|
-
|
|
711
|
+
const rewriteParams = {
|
|
720
712
|
...params,
|
|
721
713
|
...conditionParams
|
|
722
|
-
}
|
|
714
|
+
};
|
|
715
|
+
return substituteAndSanitizeRewriteDestination(rewrite.destination, rewriteParams);
|
|
723
716
|
}
|
|
724
717
|
}
|
|
725
718
|
return null;
|
|
@@ -753,6 +746,72 @@ function substituteAndSanitizeDestination(destination, params) {
|
|
|
753
746
|
return sanitizeDestination(substituteDestinationParams(destination, params));
|
|
754
747
|
}
|
|
755
748
|
/**
|
|
749
|
+
* Match Next.js's rewrite-specific prepareDestination behavior: source params
|
|
750
|
+
* that are not consumed by the destination path/host are exposed to the target
|
|
751
|
+
* page through query.
|
|
752
|
+
*
|
|
753
|
+
* https://github.com/vercel/next.js/blob/canary/packages/next/src/shared/lib/router/utils/prepare-destination.ts
|
|
754
|
+
*/
|
|
755
|
+
function substituteAndSanitizeRewriteDestination(destination, params) {
|
|
756
|
+
const rewritten = substituteAndSanitizeDestination(destination, params);
|
|
757
|
+
if (!shouldAppendRewriteParamsToQuery(destination, params)) return rewritten;
|
|
758
|
+
const existingQueryKeys = getDestinationQueryKeys(destination);
|
|
759
|
+
const paramsToAppend = [];
|
|
760
|
+
for (const [key, value] of Object.entries(params)) {
|
|
761
|
+
if (key === "nextInternalLocale" || existingQueryKeys.has(key)) continue;
|
|
762
|
+
paramsToAppend.push([key, value]);
|
|
763
|
+
}
|
|
764
|
+
if (paramsToAppend.length === 0) return rewritten;
|
|
765
|
+
return appendQueryParams(rewritten, paramsToAppend);
|
|
766
|
+
}
|
|
767
|
+
function shouldAppendRewriteParamsToQuery(destination, params) {
|
|
768
|
+
const keys = Object.keys(params).filter((key) => key !== "nextInternalLocale");
|
|
769
|
+
if (keys.length === 0) return false;
|
|
770
|
+
return !destinationPathOrHostUsesParam(destination, keys);
|
|
771
|
+
}
|
|
772
|
+
function destinationPathOrHostUsesParam(destination, keys) {
|
|
773
|
+
const pathAndHost = getDestinationPathAndHost(destination);
|
|
774
|
+
if (!pathAndHost) return false;
|
|
775
|
+
for (const key of keys) {
|
|
776
|
+
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
777
|
+
if (new RegExp(`:${escapedKey}([+*])?(?![A-Za-z0-9_])`).test(pathAndHost)) return true;
|
|
778
|
+
}
|
|
779
|
+
return false;
|
|
780
|
+
}
|
|
781
|
+
function getDestinationPathAndHost(destination) {
|
|
782
|
+
const hashIndex = destination.indexOf("#");
|
|
783
|
+
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
784
|
+
const hash = hashIndex === -1 ? "" : destination.slice(hashIndex);
|
|
785
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
786
|
+
const beforeQuery = queryIndex === -1 ? beforeHash : beforeHash.slice(0, queryIndex);
|
|
787
|
+
const schemeMatch = /^[a-z][a-z0-9+.-]*:\/\//i.exec(beforeQuery);
|
|
788
|
+
if (!schemeMatch) return `${beforeQuery}${hash}`;
|
|
789
|
+
const withoutScheme = beforeQuery.slice(schemeMatch[0].length);
|
|
790
|
+
const slashIndex = withoutScheme.indexOf("/");
|
|
791
|
+
if (slashIndex === -1) return `${withoutScheme}${hash}`;
|
|
792
|
+
return `${withoutScheme.slice(0, slashIndex)}${withoutScheme.slice(slashIndex)}${hash}`;
|
|
793
|
+
}
|
|
794
|
+
function getDestinationQueryKeys(destination) {
|
|
795
|
+
const hashIndex = destination.indexOf("#");
|
|
796
|
+
const beforeHash = hashIndex === -1 ? destination : destination.slice(0, hashIndex);
|
|
797
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
798
|
+
if (queryIndex === -1) return /* @__PURE__ */ new Set();
|
|
799
|
+
const query = beforeHash.slice(queryIndex + 1);
|
|
800
|
+
return new Set(new URLSearchParams(query).keys());
|
|
801
|
+
}
|
|
802
|
+
function appendQueryParams(url, params) {
|
|
803
|
+
const hashIndex = url.indexOf("#");
|
|
804
|
+
const beforeHash = hashIndex === -1 ? url : url.slice(0, hashIndex);
|
|
805
|
+
const hash = hashIndex === -1 ? "" : url.slice(hashIndex);
|
|
806
|
+
const queryIndex = beforeHash.indexOf("?");
|
|
807
|
+
const base = queryIndex === -1 ? beforeHash : beforeHash.slice(0, queryIndex);
|
|
808
|
+
const query = queryIndex === -1 ? "" : beforeHash.slice(queryIndex + 1);
|
|
809
|
+
const merged = new URLSearchParams(query);
|
|
810
|
+
for (const [key, value] of params) merged.append(key, value);
|
|
811
|
+
const search = merged.toString();
|
|
812
|
+
return `${base}${search ? `?${search}` : ""}${hash}`;
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
756
815
|
* Sanitize a redirect/rewrite destination to collapse protocol-relative URLs.
|
|
757
816
|
*
|
|
758
817
|
* After parameter substitution, a destination like `/:path*` can become
|
|
@@ -117,14 +117,20 @@ type NextConfig = {
|
|
|
117
117
|
domains?: string[];
|
|
118
118
|
unoptimized?: boolean; /** Allowed device widths for image optimization. Defaults to Next.js defaults: [640, 750, 828, 1080, 1200, 1920, 2048, 3840] */
|
|
119
119
|
deviceSizes?: number[]; /** Allowed image sizes for fixed-width images. Defaults to Next.js defaults: [16, 32, 48, 64, 96, 128, 256, 384] */
|
|
120
|
-
imageSizes?: number[]; /**
|
|
120
|
+
imageSizes?: number[]; /** Allowed image qualities. When unset, any quality from 1-100 is permitted (matches Next.js). */
|
|
121
|
+
qualities?: number[]; /** Allow SVG images through the image optimization endpoint. SVG can contain scripts, so only enable if you trust all image sources. */
|
|
121
122
|
dangerouslyAllowSVG?: boolean; /** Allow image optimization for hostnames that resolve to private IP addresses. This is a security risk (SSRF) — only enable for private networks when you understand the risk. */
|
|
122
123
|
dangerouslyAllowLocalIP?: boolean; /** Content-Disposition header for image responses. Defaults to "inline". */
|
|
123
124
|
contentDispositionType?: "inline" | "attachment"; /** Content-Security-Policy header for image responses. Defaults to "script-src 'none'; frame-src 'none'; sandbox;" */
|
|
124
125
|
contentSecurityPolicy?: string;
|
|
125
126
|
}; /** Build output mode: 'export' for full static export, 'standalone' for single server */
|
|
126
127
|
output?: "export" | "standalone"; /** File extensions treated as routable pages/routes (Next.js pageExtensions) */
|
|
127
|
-
pageExtensions?: string[];
|
|
128
|
+
pageExtensions?: string[]; /** Turbopack-compatible module resolution options. */
|
|
129
|
+
turbopack?: {
|
|
130
|
+
resolveAlias?: Record<string, unknown>;
|
|
131
|
+
resolveExtensions?: string[];
|
|
132
|
+
[key: string]: unknown;
|
|
133
|
+
};
|
|
128
134
|
/**
|
|
129
135
|
* Module specifiers that are required for side effects on the client before
|
|
130
136
|
* hydration, in array order, ahead of the user's `instrumentation-client.{ts,js}`.
|
|
@@ -182,6 +188,7 @@ type NextConfig = {
|
|
|
182
188
|
defineServer?: Record<string, string | number | boolean>;
|
|
183
189
|
};
|
|
184
190
|
experimental?: {
|
|
191
|
+
/** Enables hard-navigation recovery when App Router navigation rendering fails. */appNavFailHandling?: boolean;
|
|
185
192
|
/**
|
|
186
193
|
* Enables the experimental App Router gesture transition API:
|
|
187
194
|
* `useRouter().experimental_gesturePush()`.
|
|
@@ -236,8 +243,11 @@ type ResolvedNextConfig = {
|
|
|
236
243
|
trailingSlash: boolean;
|
|
237
244
|
output: "" | "export" | "standalone";
|
|
238
245
|
pageExtensions: string[];
|
|
246
|
+
resolveExtensions: string[] | null;
|
|
247
|
+
serverResolveExtensions: string[] | null;
|
|
239
248
|
instrumentationClientInject: string[];
|
|
240
249
|
cacheComponents: boolean;
|
|
250
|
+
appNavFailHandling: boolean;
|
|
241
251
|
/**
|
|
242
252
|
* Enables the experimental App Router gesture transition API:
|
|
243
253
|
* `useRouter().experimental_gesturePush()`.
|
|
@@ -337,6 +347,13 @@ type ResolvedNextConfig = {
|
|
|
337
347
|
* `test/e2e/optimized-loading` test fixture.
|
|
338
348
|
*/
|
|
339
349
|
disableOptimizedLoading: boolean;
|
|
350
|
+
/**
|
|
351
|
+
* Mirrors Next.js `experimental.scrollRestoration`. When true, the Pages
|
|
352
|
+
* Router client takes ownership of browser history scroll restoration by
|
|
353
|
+
* setting `window.history.scrollRestoration = "manual"` and snapshotting
|
|
354
|
+
* scroll positions per history entry.
|
|
355
|
+
*/
|
|
356
|
+
scrollRestoration: boolean;
|
|
340
357
|
/**
|
|
341
358
|
* Build-time constant replacement map applied to BOTH client and server
|
|
342
359
|
* bundles. Sourced from `compiler.define` in next.config. Values are
|
|
@@ -378,6 +395,28 @@ type ResolvedNextConfig = {
|
|
|
378
395
|
dynamic: number;
|
|
379
396
|
static: number;
|
|
380
397
|
};
|
|
398
|
+
/**
|
|
399
|
+
* Mirrors Next.js `experimental.useLightningcss`. When `true`, switch
|
|
400
|
+
* Vite's CSS pipeline from PostCSS to lightningcss for both transforms
|
|
401
|
+
* and minification, so the user's `lightningCssFeatures` config takes
|
|
402
|
+
* effect (without this flag set, Next.js's own
|
|
403
|
+
* `lightningCssFeatures` option is also a no-op).
|
|
404
|
+
*
|
|
405
|
+
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/useLightningcss
|
|
406
|
+
*/
|
|
407
|
+
useLightningcss: boolean;
|
|
408
|
+
/**
|
|
409
|
+
* Resolved `experimental.lightningCssFeatures` from next.config, converted
|
|
410
|
+
* from dash-case feature names into the numeric bitmask form expected by
|
|
411
|
+
* the lightningcss `transform()` API (`include` / `exclude` options). When
|
|
412
|
+
* the user did not supply the option, both masks are `0` (a no-op).
|
|
413
|
+
*
|
|
414
|
+
* @see https://nextjs.org/docs/app/api-reference/config/next-config-js/lightningCssFeatures
|
|
415
|
+
*/
|
|
416
|
+
lightningCssFeatures: {
|
|
417
|
+
include: number;
|
|
418
|
+
exclude: number;
|
|
419
|
+
};
|
|
381
420
|
};
|
|
382
421
|
/**
|
|
383
422
|
* Whole-word substring check for any of the CJS-style globals that the
|
|
@@ -457,11 +496,14 @@ declare function normalizeAssetPrefix(value: unknown): string;
|
|
|
457
496
|
* resolve it once and share it — see `__VINEXT_SHARED_RSC_COMPATIBILITY_ID`.
|
|
458
497
|
*/
|
|
459
498
|
declare function createRscCompatibilityId(nextConfig: Pick<ResolvedNextConfig, "deploymentId">): string;
|
|
499
|
+
declare function lightningCssFeatureNamesToMask(names: readonly string[]): number;
|
|
460
500
|
/**
|
|
461
501
|
* Resolve a NextConfig into a fully-resolved ResolvedNextConfig.
|
|
462
502
|
* Awaits async functions for redirects/rewrites/headers.
|
|
463
503
|
*/
|
|
464
|
-
declare function resolveNextConfig(config: NextConfig | null, root?: string
|
|
504
|
+
declare function resolveNextConfig(config: NextConfig | null, root?: string, options?: {
|
|
505
|
+
dev?: boolean;
|
|
506
|
+
}): Promise<ResolvedNextConfig>;
|
|
465
507
|
/**
|
|
466
508
|
* Extract MDX compilation options (remark/rehype/recma plugins) from
|
|
467
509
|
* a Next.js config that uses @next/mdx.
|
|
@@ -489,4 +531,4 @@ declare function extractMdxOptions(config: NextConfig, root?: string): Promise<M
|
|
|
489
531
|
*/
|
|
490
532
|
declare function detectNextIntlConfig(root: string, resolved: ResolvedNextConfig): void;
|
|
491
533
|
//#endregion
|
|
492
|
-
export { HasCondition, MdxOptions, NextConfig, NextConfigInput, NextHeader, NextI18nConfig, NextRedirect, NextRewrite, PHASE_PRODUCTION_BUILD, ResolvedNextConfig, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|
|
534
|
+
export { HasCondition, MdxOptions, NextConfig, NextConfigInput, NextHeader, NextI18nConfig, NextRedirect, NextRewrite, PHASE_PRODUCTION_BUILD, ResolvedNextConfig, createRscCompatibilityId, detectNextIntlConfig, extractMdxOptions, findNextConfigPath, lightningCssFeatureNamesToMask, loadNextConfig, normalizeAssetPrefix, parseBodySizeLimit, reassignsModuleExports, referencesCjsGlobals, resolveNextConfig, resolveNextConfigInput };
|