vinext 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +72 -1
- package/THIRD_PARTY_LICENSES.md +26 -0
- package/dist/build/app-page-static-eligibility.d.ts +15 -0
- package/dist/build/app-page-static-eligibility.js +82 -0
- package/dist/build/lifecycle.js +10 -10
- package/dist/build/pages-client-assets-module.js +6 -1
- package/dist/build/precompress.js +1 -1
- package/dist/build/prerender-paths.js +6 -85
- package/dist/build/prerender.d.ts +8 -1
- package/dist/build/prerender.js +167 -46
- package/dist/build/run-prerender.js +4 -3
- package/dist/build/server-entry.d.ts +2 -0
- package/dist/build/server-entry.js +7 -1
- package/dist/build/server-manifest.d.ts +7 -0
- package/dist/build/server-manifest.js +11 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/client/browser-globals.d.ts +4 -0
- package/dist/client/browser-globals.js +5 -0
- package/dist/client/navigation-runtime.d.ts +11 -1
- package/dist/client/navigation-runtime.js +3 -3
- package/dist/config/config-matchers.js +3 -1
- package/dist/config/dotenv.js +14 -3
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.js +18 -3
- package/dist/entries/app-rsc-entry.d.ts +2 -0
- package/dist/entries/app-rsc-entry.js +67 -45
- package/dist/index.d.ts +4 -1
- package/dist/index.js +200 -100
- package/dist/init-cloudflare.d.ts +1 -1
- package/dist/init-cloudflare.js +6 -6
- package/dist/init-platform.js +1 -1
- package/dist/init.js +4 -2
- package/dist/plugins/cache-flight-codec.d.ts +19 -0
- package/dist/plugins/cache-flight-codec.js +68 -0
- package/dist/plugins/commonjs-esm-facade.d.ts +35 -0
- package/dist/plugins/commonjs-esm-facade.js +80 -0
- package/dist/plugins/commonjs-syntax.d.ts +16 -0
- package/dist/plugins/commonjs-syntax.js +22 -0
- package/dist/plugins/fonts.d.ts +8 -11
- package/dist/plugins/fonts.js +71 -34
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +54 -3
- package/dist/plugins/import-meta-url.js +6 -6
- package/dist/plugins/og-asset-ownership.d.ts +2 -0
- package/dist/plugins/og-asset-ownership.js +24 -13
- package/dist/plugins/og-assets.d.ts +18 -0
- package/dist/plugins/og-assets.js +50 -8
- package/dist/plugins/og-harfbuzz.js +38 -27
- package/dist/plugins/optimize-imports.js +2 -1
- package/dist/plugins/require-context.d.ts +1 -0
- package/dist/plugins/require-context.js +28 -1
- package/dist/plugins/scan-build-css.d.ts +12 -0
- package/dist/plugins/scan-build-css.js +39 -0
- package/dist/plugins/strip-server-exports.d.ts +2 -0
- package/dist/plugins/strip-server-exports.js +3 -1
- package/dist/plugins/transform-result.d.ts +18 -0
- package/dist/plugins/transform-result.js +23 -2
- package/dist/plugins/typeof-window.d.ts +10 -0
- package/dist/plugins/typeof-window.js +33 -9
- package/dist/routing/app-route-graph.d.ts +0 -1
- package/dist/routing/app-route-graph.js +2 -4
- package/dist/routing/app-route-ids.d.ts +3 -0
- package/dist/routing/app-route-ids.js +6 -0
- package/dist/routing/file-matcher.d.ts +1 -0
- package/dist/routing/file-matcher.js +1 -1
- package/dist/server/api-handler.js +17 -7
- package/dist/server/app-bfcache-id.d.ts +1 -0
- package/dist/server/app-bfcache-id.js +7 -1
- package/dist/server/app-bfcache-identity.js +1 -2
- package/dist/server/app-browser-entry.js +15 -9
- package/dist/server/app-browser-history-controller.d.ts +2 -0
- package/dist/server/app-browser-history-controller.js +8 -0
- package/dist/server/app-browser-hydration.d.ts +1 -1
- package/dist/server/app-browser-hydration.js +2 -2
- package/dist/server/app-browser-interception-context.js +26 -2
- package/dist/server/app-browser-navigation-controller.d.ts +7 -1
- package/dist/server/app-browser-navigation-controller.js +94 -11
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-browser-stream.d.ts +1 -1
- package/dist/server/app-fallback-renderer.d.ts +2 -0
- package/dist/server/app-fallback-renderer.js +1 -0
- package/dist/server/app-history-state.d.ts +3 -1
- package/dist/server/app-history-state.js +9 -5
- package/dist/server/app-middleware.js +2 -1
- package/dist/server/app-optimistic-routing.js +1 -1
- package/dist/server/app-page-boundary-render.d.ts +5 -0
- package/dist/server/app-page-boundary-render.js +6 -4
- package/dist/server/app-page-cache-finalizer.d.ts +11 -0
- package/dist/server/app-page-cache-finalizer.js +41 -7
- package/dist/server/app-page-cache-render.d.ts +18 -0
- package/dist/server/app-page-cache-render.js +65 -44
- package/dist/server/app-page-cache.d.ts +5 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +9 -1
- package/dist/server/app-page-dispatch.js +47 -30
- package/dist/server/app-page-element-builder.d.ts +7 -0
- package/dist/server/app-page-element-builder.js +27 -42
- package/dist/server/app-page-execution.d.ts +15 -12
- package/dist/server/app-page-execution.js +30 -40
- package/dist/server/app-page-head.d.ts +5 -0
- package/dist/server/app-page-head.js +9 -3
- package/dist/server/app-page-probe.d.ts +0 -109
- package/dist/server/app-page-probe.js +3 -136
- package/dist/server/app-page-render-identity.d.ts +0 -1
- package/dist/server/app-page-render-identity.js +1 -1
- package/dist/server/app-page-render-observation.js +2 -2
- package/dist/server/app-page-render.d.ts +13 -5
- package/dist/server/app-page-render.js +219 -118
- package/dist/server/app-page-request.d.ts +0 -1
- package/dist/server/app-page-request.js +1 -2
- package/dist/server/app-page-response.d.ts +4 -3
- package/dist/server/app-page-response.js +4 -3
- package/dist/server/app-page-route-wiring.d.ts +17 -5
- package/dist/server/app-page-route-wiring.js +55 -33
- package/dist/server/app-page-rsc-render-status.d.ts +48 -0
- package/dist/server/app-page-rsc-render-status.js +54 -0
- package/dist/server/app-page-search-params-observation.js +1 -1
- package/dist/server/app-page-stream.d.ts +15 -8
- package/dist/server/app-page-stream.js +7 -1
- package/dist/server/app-page-tracing.js +2 -1
- package/dist/server/app-pages-bridge.js +3 -2
- package/dist/server/app-render-abort-error.d.ts +3 -0
- package/dist/server/app-render-abort-error.js +8 -0
- package/dist/server/app-request-stage-dispatch.js +1 -1
- package/dist/server/app-request-stage-independent-entry.js +8 -11
- package/dist/server/app-response-header-provenance.d.ts +2 -0
- package/dist/server/app-response-header-provenance.js +10 -4
- package/dist/server/app-route-handler-cache.d.ts +2 -1
- package/dist/server/app-route-handler-cache.js +11 -7
- package/dist/server/app-route-handler-dispatch.js +11 -4
- package/dist/server/app-route-handler-execution.d.ts +9 -1
- package/dist/server/app-route-handler-execution.js +28 -13
- package/dist/server/app-route-handler-policy.js +2 -2
- package/dist/server/app-route-handler-response.d.ts +1 -1
- package/dist/server/app-route-handler-response.js +14 -5
- package/dist/server/app-router-entry.d.ts +2 -1
- package/dist/server/app-router-entry.js +8 -12
- package/dist/server/app-rsc-errors.d.ts +0 -1
- package/dist/server/app-rsc-errors.js +2 -6
- package/dist/server/app-rsc-handler.d.ts +5 -0
- package/dist/server/app-rsc-handler.js +229 -102
- package/dist/server/app-rsc-request-normalization.d.ts +4 -2
- package/dist/server/app-rsc-request-normalization.js +7 -4
- package/dist/server/app-rsc-response-finalizer.js +4 -1
- package/dist/server/app-rsc-response-stage.d.ts +1 -1
- package/dist/server/app-rsc-response-stage.js +6 -4
- package/dist/server/app-rsc-route-matching.d.ts +9 -1
- package/dist/server/app-rsc-route-matching.js +37 -20
- package/dist/server/app-server-action-execution.d.ts +2 -1
- package/dist/server/app-server-action-execution.js +1 -1
- package/dist/server/app-ssr-entry.d.ts +3 -2
- package/dist/server/app-ssr-entry.js +9 -7
- package/dist/server/app-ssr-search-params-gate.js +1 -1
- package/dist/server/app-ssr-stream.d.ts +6 -1
- package/dist/server/app-ssr-stream.js +35 -16
- package/dist/server/app-worker-stages.d.ts +2 -2
- package/dist/server/app-worker-stages.js +3 -3
- package/dist/server/cache-control.js +3 -11
- package/dist/server/cacheability-request.js +56 -52
- package/dist/server/config-headers.js +3 -1
- package/dist/server/dev-server.js +23 -5
- package/dist/server/headers.d.ts +16 -0
- package/dist/server/headers.js +19 -1
- package/dist/server/http-error-responses.js +1 -0
- package/dist/server/image-optimization.d.ts +16 -0
- package/dist/server/image-optimization.js +26 -6
- package/dist/server/isr-cache.d.ts +2 -0
- package/dist/server/isr-cache.js +8 -3
- package/dist/server/metadata-route-response.js +94 -37
- package/dist/server/middleware-matcher-pattern.js +8 -4
- package/dist/server/middleware-response-headers.js +2 -0
- package/dist/server/multi-stage.d.ts +8 -0
- package/dist/server/navigation-planner.js +1 -1
- package/dist/server/node-response-signal.d.ts +16 -0
- package/dist/server/node-response-signal.js +26 -0
- package/dist/server/open-redirect.d.ts +47 -0
- package/dist/server/open-redirect.js +74 -1
- package/dist/server/pages-api-route.js +8 -2
- package/dist/server/pages-asset-tags.d.ts +1 -0
- package/dist/server/pages-asset-tags.js +73 -22
- package/dist/server/pages-client-assets.d.ts +2 -0
- package/dist/server/pages-page-data.d.ts +6 -1
- package/dist/server/pages-page-data.js +71 -65
- package/dist/server/pages-page-handler.js +50 -15
- package/dist/server/pages-page-response.js +3 -1
- package/dist/server/pages-request-pipeline.d.ts +2 -1
- package/dist/server/pages-request-pipeline.js +20 -5
- package/dist/server/pages-request-stage-entry.js +14 -8
- package/dist/server/prerender-manifest.d.ts +6 -0
- package/dist/server/prerender-manifest.js +1 -1
- package/dist/server/prod-server.d.ts +8 -7
- package/dist/server/prod-server.js +152 -78
- package/dist/server/request-pipeline.d.ts +20 -8
- package/dist/server/request-pipeline.js +21 -7
- package/dist/server/response-compression.d.ts +43 -0
- package/dist/server/response-compression.js +111 -0
- package/dist/server/response-stage-cacheability.js +1 -1
- package/dist/server/seed-cache.js +10 -7
- package/dist/server/socket-error-backstop.d.ts +14 -0
- package/dist/server/socket-error-backstop.js +27 -4
- package/dist/server/worker-revalidation-context.d.ts +2 -1
- package/dist/server/worker-revalidation-context.js +1 -0
- package/dist/server/workers-tracing.d.ts +17 -0
- package/dist/server/workers-tracing.js +48 -8
- package/dist/shims/cache-adapter-instantiate.d.ts +50 -0
- package/dist/shims/cache-adapter-instantiate.js +118 -0
- package/dist/shims/cache-callable-runtime.d.ts +2 -40
- package/dist/shims/cache-callable-runtime.js +50 -168
- package/dist/shims/cache-flight-arguments.d.ts +22 -0
- package/dist/shims/cache-flight-arguments.js +56 -0
- package/dist/shims/cache-request-state.d.ts +18 -14
- package/dist/shims/cache-request-state.js +33 -21
- package/dist/shims/cache-runtime.d.ts +6 -19
- package/dist/shims/cache-runtime.js +168 -226
- package/dist/shims/cache.d.ts +3 -2
- package/dist/shims/cache.js +8 -5
- package/dist/shims/cacheability-classification.d.ts +8 -1
- package/dist/shims/cacheability-classification.js +2 -2
- package/dist/shims/cdn-cache.d.ts +10 -1
- package/dist/shims/cdn-cache.js +16 -9
- package/dist/shims/error-boundary-navigation.d.ts +7 -0
- package/dist/shims/error-boundary-navigation.js +19 -1
- package/dist/shims/error-boundary.d.ts +10 -10
- package/dist/shims/error-boundary.js +26 -7
- package/dist/shims/error.d.ts +4 -18
- package/dist/shims/error.js +17 -10
- package/dist/shims/error.react-server.d.ts +4 -6
- package/dist/shims/error.react-server.js +4 -1
- package/dist/shims/fetch-cache.d.ts +6 -0
- package/dist/shims/fetch-cache.js +23 -4
- package/dist/shims/form.js +1 -1
- package/dist/shims/headers.d.ts +19 -69
- package/dist/shims/headers.js +82 -183
- package/dist/shims/internal/app-page-props-cache-key.d.ts +5 -2
- package/dist/shims/internal/app-page-props-cache-key.js +24 -15
- package/dist/shims/internal/cache-context-accessor.d.ts +16 -0
- package/dist/shims/internal/cache-context-accessor.js +15 -0
- package/dist/shims/internal/headers-state.d.ts +73 -0
- package/dist/shims/internal/headers-state.js +157 -0
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/navigation-errors.d.ts +6 -0
- package/dist/shims/navigation-errors.js +11 -1
- package/dist/shims/navigation.d.ts +7 -0
- package/dist/shims/navigation.js +16 -6
- package/dist/shims/request-context.d.ts +9 -0
- package/dist/shims/request-state-types.d.ts +2 -1
- package/dist/shims/root-params.js +1 -1
- package/dist/shims/server.js +52 -2
- package/dist/shims/thenable-params.d.ts +4 -0
- package/dist/shims/thenable-params.js +25 -3
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/utils/encode-cache-tag.d.ts +1 -0
- package/dist/utils/encode-cache-tag.js +11 -1
- package/dist/utils/mdx-scan.d.ts +5 -0
- package/dist/utils/mdx-scan.js +8 -1
- package/dist/utils/regex-safety.d.ts +10 -0
- package/dist/utils/regex-safety.js +70 -18
- package/dist/utils/vite-cli-invocation.js +8 -1
- package/package.json +8 -4
- package/dist/server/metadata-route-cache-policy.d.ts +0 -5
- package/dist/server/metadata-route-cache-policy.js +0 -6
package/dist/build/prerender.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
2
2
|
import { createValidFileMatcher, findFileWithExtensions } from "../routing/file-matcher.js";
|
|
3
|
+
import { isUnknownRecord } from "../utils/record.js";
|
|
3
4
|
import { BLOCKED_PAGES } from "../shims/constants.js";
|
|
4
5
|
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
|
|
5
6
|
import { appRouteLayoutStaticParamsGroups } from "../routing/app-router.js";
|
|
6
|
-
import { NEXT_CACHE_TAGS_HEADER, VINEXT_METADATA_ROUTE_CACHE_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_METADATA_ROUTES_PATH, VINEXT_PRERENDER_RENDER_ERROR_HEADER } from "../server/headers.js";
|
|
7
|
+
import { NEXT_CACHE_TAGS_HEADER, VINEXT_METADATA_ROUTE_CACHE_HEADER, VINEXT_PRERENDER_CACHE_LIFE_HEADER, VINEXT_PRERENDER_METADATA_ROUTES_PATH, VINEXT_PRERENDER_RENDER_ERROR_HEADER, VINEXT_PRERENDER_SPECIAL_ERROR_HEADER } from "../server/headers.js";
|
|
8
|
+
import { extractLocaleFromUrl } from "../server/pages-i18n.js";
|
|
7
9
|
import { classifyAppRoute, classifyPagesRoute, getAppRouteRenderEntryPath } from "./report.js";
|
|
8
10
|
import { resolveClientStaleTimeSeconds } from "../utils/cache-control-metadata.js";
|
|
9
11
|
import { NoOpCacheHandler, getCacheHandler, setCacheHandler } from "../shims/cache-handler.js";
|
|
10
12
|
import { headersContextFromRequest, runWithHeadersContext } from "../shims/headers.js";
|
|
11
13
|
import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
|
|
12
14
|
import { normalizeStaticPathsEntry } from "../routing/route-pattern.js";
|
|
15
|
+
import { createRscRequestUrl } from "../server/app-rsc-cache-busting.js";
|
|
13
16
|
import { readPrerenderSecret } from "./server-manifest.js";
|
|
14
17
|
import { buildPregeneratedConcretePathTable } from "../server/prerender-manifest.js";
|
|
15
18
|
import { concatUint8Arrays, decodeRscEmbeddedChunk } from "../server/app-rsc-embedded-chunks.js";
|
|
@@ -21,7 +24,6 @@ import { startProdServer } from "../server/prod-server.js";
|
|
|
21
24
|
import { prerenderPoolAvailable, resolvePrerenderPoolSize, startPrerenderServerPool } from "./prerender-server-pool.js";
|
|
22
25
|
import { enterPrerenderPhase } from "./prerender-phase.js";
|
|
23
26
|
import { buildAppRouteCacheValue } from "../server/app-route-handler-response.js";
|
|
24
|
-
import { isMetadataResponseCacheable } from "../server/metadata-route-cache-policy.js";
|
|
25
27
|
import fs from "node:fs";
|
|
26
28
|
import os from "node:os";
|
|
27
29
|
//#region src/build/prerender.ts
|
|
@@ -337,6 +339,14 @@ function routeStaticParamSets(route, paramSets, options = {}) {
|
|
|
337
339
|
function layoutOnlyParamSets(route, parentParamSets) {
|
|
338
340
|
return parentParamSets.length > 0 && parentParamSets.every((params) => route.params.every((name) => name in params)) ? parentParamSets : null;
|
|
339
341
|
}
|
|
342
|
+
function localizePagesPath(pathname, locale, i18n) {
|
|
343
|
+
if (!i18n || !locale) return pathname;
|
|
344
|
+
if (locale === i18n.defaultLocale) {
|
|
345
|
+
const firstSegment = pathname.split("/")[1]?.toLowerCase();
|
|
346
|
+
if (!i18n.locales.some((candidate) => candidate.toLowerCase() === firstSegment)) return pathname;
|
|
347
|
+
}
|
|
348
|
+
return pathname === "/" ? `/${locale}` : `/${locale}${pathname}`;
|
|
349
|
+
}
|
|
340
350
|
/**
|
|
341
351
|
* Run the prerender phase for Pages Router.
|
|
342
352
|
*
|
|
@@ -379,6 +389,8 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
379
389
|
port: 0,
|
|
380
390
|
host: "127.0.0.1",
|
|
381
391
|
outDir: path.dirname(path.dirname(pagesBundlePath)),
|
|
392
|
+
serverDir: path.dirname(pagesBundlePath),
|
|
393
|
+
serverEntryPath: pagesBundlePath,
|
|
382
394
|
noCompression: true,
|
|
383
395
|
purpose: "prerender"
|
|
384
396
|
});
|
|
@@ -428,7 +440,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
428
440
|
for (const route of bundlePageRoutes) {
|
|
429
441
|
if (BLOCKED_PAGES.includes(route.pattern)) continue;
|
|
430
442
|
if (route.pattern === "/404") continue;
|
|
431
|
-
const { type, revalidate: classifiedRevalidate } = classifyPagesRoute(route.filePath);
|
|
443
|
+
const { type, revalidate: classifiedRevalidate, hasStaticProps = false } = classifyPagesRoute(route.filePath);
|
|
432
444
|
if (type === "ssr") {
|
|
433
445
|
if (mode === "export") results.push({
|
|
434
446
|
route: route.pattern,
|
|
@@ -460,8 +472,8 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
460
472
|
let pathsResult;
|
|
461
473
|
try {
|
|
462
474
|
pathsResult = await route.module.getStaticPaths({
|
|
463
|
-
locales: [],
|
|
464
|
-
defaultLocale: ""
|
|
475
|
+
locales: [...config.i18n?.locales ?? []],
|
|
476
|
+
defaultLocale: config.i18n?.defaultLocale ?? ""
|
|
465
477
|
});
|
|
466
478
|
} catch (e) {
|
|
467
479
|
results.push({
|
|
@@ -483,21 +495,38 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
483
495
|
}
|
|
484
496
|
const paths = pathsResult?.paths ?? [];
|
|
485
497
|
let entryError = null;
|
|
498
|
+
const seenPaths = /* @__PURE__ */ new Set();
|
|
486
499
|
for (const item of paths) {
|
|
487
|
-
|
|
500
|
+
let locale = config.i18n?.defaultLocale;
|
|
501
|
+
let pathEntry = item;
|
|
502
|
+
if (config.i18n && typeof item === "string") {
|
|
503
|
+
const localized = extractLocaleFromUrl(item, config.i18n);
|
|
504
|
+
locale = localized.locale;
|
|
505
|
+
pathEntry = localized.url;
|
|
506
|
+
} else if (item && typeof item === "object" && item.locale !== void 0) locale = item.locale;
|
|
507
|
+
const normalized = normalizeStaticPathsEntry(pathEntry, route.pattern);
|
|
488
508
|
if ("error" in normalized) {
|
|
489
509
|
entryError = normalized.error;
|
|
490
510
|
break;
|
|
491
511
|
}
|
|
512
|
+
if (locale !== void 0 && !config.i18n?.locales.includes(locale)) {
|
|
513
|
+
entryError = `Invalid locale returned from getStaticPaths for ${route.pattern}: ${locale}`;
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
492
516
|
const { params } = normalized;
|
|
493
517
|
try {
|
|
494
|
-
const urlPath = buildUrlFromParams(route.pattern, params);
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
518
|
+
const urlPath = localizePagesPath(buildUrlFromParams(route.pattern, params), locale, config.i18n);
|
|
519
|
+
if (!seenPaths.has(urlPath)) {
|
|
520
|
+
seenPaths.add(urlPath);
|
|
521
|
+
pagesToRender.push({
|
|
522
|
+
route,
|
|
523
|
+
urlPath,
|
|
524
|
+
params,
|
|
525
|
+
revalidate,
|
|
526
|
+
hasStaticProps,
|
|
527
|
+
locale
|
|
528
|
+
});
|
|
529
|
+
}
|
|
501
530
|
} catch (e) {
|
|
502
531
|
entryError = e.message;
|
|
503
532
|
break;
|
|
@@ -511,25 +540,58 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
511
540
|
});
|
|
512
541
|
continue;
|
|
513
542
|
}
|
|
514
|
-
} else pagesToRender.push({
|
|
543
|
+
} else for (const locale of config.i18n?.locales ?? [void 0]) pagesToRender.push({
|
|
515
544
|
route,
|
|
516
|
-
urlPath: route.pattern,
|
|
545
|
+
urlPath: localizePagesPath(route.pattern, locale, config.i18n),
|
|
517
546
|
params: {},
|
|
518
|
-
revalidate
|
|
547
|
+
revalidate,
|
|
548
|
+
hasStaticProps,
|
|
549
|
+
locale
|
|
519
550
|
});
|
|
520
551
|
}
|
|
521
552
|
if (!options._prodServer && pagesBundlePath && prerenderPoolAvailable()) {
|
|
522
553
|
const poolSize = resolvePrerenderPoolSize(pagesToRender.length, concurrency);
|
|
523
554
|
if (poolSize > 1) {
|
|
524
|
-
renderPool = await startOptionalPrerenderServerPool(path.dirname(path.dirname(pagesBundlePath)), poolSize);
|
|
555
|
+
renderPool = await startOptionalPrerenderServerPool(path.dirname(path.dirname(pagesBundlePath)), poolSize, void 0, path.dirname(pagesBundlePath));
|
|
525
556
|
if (renderPool) renderPorts = renderPool.ports;
|
|
526
557
|
}
|
|
527
558
|
}
|
|
528
559
|
let completed = 0;
|
|
529
|
-
const pageResults = await runWithConcurrency(pagesToRender, concurrency, async ({ route, urlPath, revalidate }) => {
|
|
560
|
+
const pageResults = await runWithConcurrency(pagesToRender, concurrency, async ({ route, urlPath, revalidate, hasStaticProps, locale }) => {
|
|
530
561
|
let result;
|
|
531
562
|
try {
|
|
532
563
|
const response = await renderPage(urlPath);
|
|
564
|
+
if (mode === "default" && response.headers.get("x-vinext-prerender-rewritten") !== "0") {
|
|
565
|
+
response.body?.cancel().catch(() => {});
|
|
566
|
+
const skipped = {
|
|
567
|
+
route: route.pattern,
|
|
568
|
+
status: "skipped",
|
|
569
|
+
reason: "dynamic"
|
|
570
|
+
};
|
|
571
|
+
onProgress?.({
|
|
572
|
+
completed: ++completed,
|
|
573
|
+
total: pagesToRender.length,
|
|
574
|
+
route: urlPath,
|
|
575
|
+
status: skipped.status
|
|
576
|
+
});
|
|
577
|
+
return skipped;
|
|
578
|
+
}
|
|
579
|
+
const contentType = response.headers.get("content-type");
|
|
580
|
+
const isStaticPropsResponse = mode === "default" && hasStaticProps && response.headers.get("X-Vinext-Cache") === "MISS";
|
|
581
|
+
const notFound = isStaticPropsResponse && response.status === 404;
|
|
582
|
+
const redirect = isStaticPropsResponse && [
|
|
583
|
+
301,
|
|
584
|
+
302,
|
|
585
|
+
303,
|
|
586
|
+
307,
|
|
587
|
+
308
|
|
588
|
+
].includes(response.status);
|
|
589
|
+
let redirectProps;
|
|
590
|
+
if (redirect) {
|
|
591
|
+
const props = await response.json();
|
|
592
|
+
if (!isUnknownRecord(props) || !isUnknownRecord(props.pageProps) || typeof props.pageProps.__N_REDIRECT !== "string" || props.pageProps.__N_REDIRECT_STATUS !== response.status || props.pageProps.__N_REDIRECT_BASE_PATH !== void 0 && typeof props.pageProps.__N_REDIRECT_BASE_PATH !== "boolean") throw new Error(`Invalid prerendered Pages redirect props for ${urlPath}`);
|
|
593
|
+
redirectProps = props;
|
|
594
|
+
}
|
|
533
595
|
const outputFiles = [];
|
|
534
596
|
const htmlOutputPath = getOutputPath(urlPath, config.trailingSlash, mode === "export" ? config.basePath : "");
|
|
535
597
|
const htmlFullPath = path.join(outDir, htmlOutputPath);
|
|
@@ -539,7 +601,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
539
601
|
fs.writeFileSync(htmlFullPath, html, "utf-8");
|
|
540
602
|
outputFiles.push(htmlOutputPath);
|
|
541
603
|
} else {
|
|
542
|
-
if (!response.ok) throw new Error(`renderPage returned ${response.status} for ${urlPath}`);
|
|
604
|
+
if (!response.ok && !notFound) throw new Error(`renderPage returned ${response.status} for ${urlPath}`);
|
|
543
605
|
const html = await response.text();
|
|
544
606
|
fs.mkdirSync(path.dirname(htmlFullPath), { recursive: true });
|
|
545
607
|
fs.writeFileSync(htmlFullPath, html, "utf-8");
|
|
@@ -552,7 +614,19 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
552
614
|
revalidate,
|
|
553
615
|
...typeof revalidate === "number" ? { expire: config.expireTime } : {},
|
|
554
616
|
router: "pages",
|
|
555
|
-
...urlPath !== route.pattern ? { path: urlPath } : {}
|
|
617
|
+
...urlPath !== route.pattern ? { path: urlPath } : {},
|
|
618
|
+
...locale ? { locale } : {},
|
|
619
|
+
...response.ok ? { responseStatus: response.status } : {},
|
|
620
|
+
...response.ok && contentType ? { headers: { "content-type": contentType } } : {},
|
|
621
|
+
...notFound ? {
|
|
622
|
+
notFound: true,
|
|
623
|
+
responseStatus: 404
|
|
624
|
+
} : {},
|
|
625
|
+
...redirect ? {
|
|
626
|
+
responseStatus: response.status,
|
|
627
|
+
redirectProps,
|
|
628
|
+
headers: { location: response.headers.get("location") ?? "/" }
|
|
629
|
+
} : {}
|
|
556
630
|
};
|
|
557
631
|
} catch (e) {
|
|
558
632
|
renderPool?.recordRenderError(e);
|
|
@@ -575,21 +649,41 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
575
649
|
renderPool?.assertHealthy();
|
|
576
650
|
const hasCustom404 = findFileWithExtensions(path.join(pagesDir, "404"), fileMatcher);
|
|
577
651
|
const hasErrorPage = findFileWithExtensions(path.join(pagesDir, "_error"), fileMatcher);
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
652
|
+
for (const locale of config.i18n?.locales ?? [void 0]) {
|
|
653
|
+
if (!hasCustom404 && !hasErrorPage) break;
|
|
654
|
+
try {
|
|
655
|
+
const notFoundRes = await renderPage(localizePagesPath(hasCustom404 ? "/404" : NOT_FOUND_SENTINEL_PATH, locale, config.i18n));
|
|
656
|
+
if (mode === "default" && notFoundRes.headers.get("x-vinext-prerender-rewritten") !== "0") {
|
|
657
|
+
notFoundRes.body?.cancel().catch(() => {});
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
const contentType = notFoundRes.headers.get("content-type") ?? "";
|
|
661
|
+
if (notFoundRes.status === 404 && contentType.includes("text/html")) {
|
|
662
|
+
const html404 = await notFoundRes.text();
|
|
663
|
+
const pathname = localizePagesPath("/404", locale, config.i18n);
|
|
664
|
+
let outputFiles;
|
|
665
|
+
if (pathname === "/404") outputFiles = emitStatic404Files(outDir, html404, config.trailingSlash);
|
|
666
|
+
else {
|
|
667
|
+
const outputPath = getOutputPath(pathname, config.trailingSlash);
|
|
668
|
+
const fullPath = path.join(outDir, outputPath);
|
|
669
|
+
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
670
|
+
fs.writeFileSync(fullPath, html404, "utf8");
|
|
671
|
+
outputFiles = [outputPath];
|
|
672
|
+
}
|
|
673
|
+
results.push({
|
|
674
|
+
route: "/404",
|
|
675
|
+
status: "rendered",
|
|
676
|
+
outputFiles,
|
|
677
|
+
revalidate: false,
|
|
678
|
+
router: "pages",
|
|
679
|
+
headers: { "content-type": contentType },
|
|
680
|
+
...pathname !== "/404" ? { path: pathname } : {},
|
|
681
|
+
...locale ? { locale } : {}
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
} catch (e) {
|
|
685
|
+
renderPool?.recordRenderError(e);
|
|
590
686
|
}
|
|
591
|
-
} catch (e) {
|
|
592
|
-
renderPool?.recordRenderError(e);
|
|
593
687
|
}
|
|
594
688
|
renderPool?.assertHealthy();
|
|
595
689
|
if (!skipManifest) writePrerenderIndex(results, manifestDir, {
|
|
@@ -900,7 +994,8 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
900
994
|
};
|
|
901
995
|
}
|
|
902
996
|
const cacheControl = response.headers.get("cache-control") ?? "";
|
|
903
|
-
|
|
997
|
+
const requestCacheLife = readPrerenderCacheLifeHeader(response.headers);
|
|
998
|
+
if (requestCacheLife?.revalidate === 0) {
|
|
904
999
|
await response.body?.cancel();
|
|
905
1000
|
return {
|
|
906
1001
|
route: routePattern,
|
|
@@ -908,15 +1003,14 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
908
1003
|
reason: "dynamic"
|
|
909
1004
|
};
|
|
910
1005
|
}
|
|
911
|
-
const requestCacheLife = readPrerenderCacheLifeHeader(response.headers);
|
|
912
1006
|
const collectedTags = readPrerenderCacheTagsHeader(response.headers);
|
|
913
|
-
const cacheValue = await buildAppRouteCacheValue(response);
|
|
1007
|
+
const cacheValue = await buildAppRouteCacheValue(response, cacheControl);
|
|
914
1008
|
cacheValue.headers[VINEXT_METADATA_ROUTE_CACHE_HEADER] = "1";
|
|
915
1009
|
const outputPath = getAppRouteOutputPath(urlPath);
|
|
916
1010
|
const fullPath = path.join(outDir, outputPath);
|
|
917
1011
|
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
|
|
918
1012
|
fs.writeFileSync(fullPath, new Uint8Array(cacheValue.body));
|
|
919
|
-
const renderedCacheControl = resolveRenderedCacheControl(requestCacheLife ?? {},
|
|
1013
|
+
const renderedCacheControl = resolveRenderedCacheControl(requestCacheLife ?? {}, "", config.expireTime);
|
|
920
1014
|
const renderedRevalidate = renderedCacheControl.revalidate ?? false;
|
|
921
1015
|
const renderedStale = resolveClientStaleTimeSeconds(requestCacheLife ?? void 0);
|
|
922
1016
|
return {
|
|
@@ -948,17 +1042,22 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
948
1042
|
const responseCacheLife = readPrerenderCacheLifeHeader(response.headers);
|
|
949
1043
|
const cacheTags = readPrerenderCacheTagsHeader(response.headers);
|
|
950
1044
|
const fatal = response.headers.get(VINEXT_PRERENDER_RENDER_ERROR_HEADER) === "1";
|
|
951
|
-
|
|
1045
|
+
const specialError = mode === "export" ? null : readPrerenderSpecialErrorHeader(response.headers);
|
|
1046
|
+
const isSpecialError = specialError !== null;
|
|
1047
|
+
const ok = response.ok || isSpecialError;
|
|
1048
|
+
if (!ok || cacheControl.includes("no-store")) {
|
|
952
1049
|
await response.body?.cancel();
|
|
953
1050
|
return {
|
|
954
1051
|
cacheControl,
|
|
955
1052
|
linkHeader,
|
|
956
1053
|
html: null,
|
|
957
|
-
ok
|
|
1054
|
+
ok,
|
|
958
1055
|
requestCacheLife: null,
|
|
959
1056
|
tags: [],
|
|
960
1057
|
status: response.status,
|
|
961
|
-
fatal
|
|
1058
|
+
fatal,
|
|
1059
|
+
specialErrorLocation: null,
|
|
1060
|
+
isSpecialError
|
|
962
1061
|
};
|
|
963
1062
|
}
|
|
964
1063
|
const html = await response.text();
|
|
@@ -971,7 +1070,9 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
971
1070
|
requestCacheLife: responseCacheLife ?? processCacheLife,
|
|
972
1071
|
status: response.status,
|
|
973
1072
|
tags: cacheTags,
|
|
974
|
-
fatal: false
|
|
1073
|
+
fatal: false,
|
|
1074
|
+
specialErrorLocation: specialError?.location ?? null,
|
|
1075
|
+
isSpecialError
|
|
975
1076
|
};
|
|
976
1077
|
});
|
|
977
1078
|
const htmlCacheControl = htmlRender.cacheControl;
|
|
@@ -999,7 +1100,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
999
1100
|
error: "RSC handler returned no prerender HTML"
|
|
1000
1101
|
};
|
|
1001
1102
|
const html = isFallback ? markAppPprDynamicFallbackShellHtml(htmlRender.html) : htmlRender.html;
|
|
1002
|
-
let rscData = extractRscPayloadFromPrerenderedHtml(html);
|
|
1103
|
+
let rscData = htmlRender.isSpecialError ? null : extractRscPayloadFromPrerenderedHtml(html);
|
|
1003
1104
|
if (rscData === null) {
|
|
1004
1105
|
const rscHeaders = new Headers({
|
|
1005
1106
|
Accept: "text/x-component",
|
|
@@ -1007,7 +1108,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
1007
1108
|
});
|
|
1008
1109
|
if (prerenderRouteParamsHeader !== null) rscHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
1009
1110
|
if (isSpeculative) rscHeaders.set(VINEXT_PRERENDER_SPECULATIVE_HEADER, "1");
|
|
1010
|
-
const rscRequest = new Request(`http://localhost${requestPath}`, { headers: rscHeaders });
|
|
1111
|
+
const rscRequest = new Request(`http://localhost${await createRscRequestUrl(requestPath, rscHeaders)}`, { headers: rscHeaders });
|
|
1011
1112
|
const rscRes = await runWithHeadersContext(headersContextFromRequest(rscRequest), () => rscHandler(rscRequest));
|
|
1012
1113
|
if (!rscRes.ok) {
|
|
1013
1114
|
await rscRes.body?.cancel();
|
|
@@ -1042,7 +1143,11 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
1042
1143
|
...renderedStale === void 0 ? {} : { stale: renderedStale },
|
|
1043
1144
|
router: "app",
|
|
1044
1145
|
...htmlRender.tags.length > 0 ? { tags: htmlRender.tags } : {},
|
|
1045
|
-
...htmlRender.linkHeader
|
|
1146
|
+
...htmlRender.linkHeader || htmlRender.specialErrorLocation !== null ? { headers: {
|
|
1147
|
+
...htmlRender.linkHeader ? { link: htmlRender.linkHeader } : {},
|
|
1148
|
+
...htmlRender.specialErrorLocation !== null ? { location: htmlRender.specialErrorLocation } : {}
|
|
1149
|
+
} } : {},
|
|
1150
|
+
...htmlRender.isSpecialError ? { responseStatus: htmlRender.status } : {},
|
|
1046
1151
|
...urlPath !== routePattern ? { path: urlPath } : {},
|
|
1047
1152
|
...isFallback ? { fallback: true } : {}
|
|
1048
1153
|
};
|
|
@@ -1146,6 +1251,19 @@ function readPrerenderCacheLifeHeader(headers) {
|
|
|
1146
1251
|
return null;
|
|
1147
1252
|
}
|
|
1148
1253
|
}
|
|
1254
|
+
/** Reads the special-error marker: the page's stored headers, or null. */
|
|
1255
|
+
function readPrerenderSpecialErrorHeader(headers) {
|
|
1256
|
+
const value = headers.get(VINEXT_PRERENDER_SPECIAL_ERROR_HEADER);
|
|
1257
|
+
if (!value) return null;
|
|
1258
|
+
try {
|
|
1259
|
+
const parsed = JSON.parse(value);
|
|
1260
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
1261
|
+
const location = parsed.location;
|
|
1262
|
+
return { location: typeof location === "string" ? location : null };
|
|
1263
|
+
} catch {
|
|
1264
|
+
return null;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1149
1267
|
function readPrerenderCacheTagsHeader(headers) {
|
|
1150
1268
|
const value = headers.get(NEXT_CACHE_TAGS_HEADER);
|
|
1151
1269
|
if (!value) return [];
|
|
@@ -1187,6 +1305,9 @@ function writePrerenderIndex(routes, outDir, options) {
|
|
|
1187
1305
|
...r.routeSegments ? { routeSegments: r.routeSegments } : {},
|
|
1188
1306
|
...r.headers ? { headers: r.headers } : {},
|
|
1189
1307
|
...typeof r.responseStatus === "number" ? { responseStatus: r.responseStatus } : {},
|
|
1308
|
+
...r.notFound ? { notFound: true } : {},
|
|
1309
|
+
...r.redirectProps ? { redirectProps: r.redirectProps } : {},
|
|
1310
|
+
...r.locale ? { locale: r.locale } : {},
|
|
1190
1311
|
...r.path ? { path: r.path } : {},
|
|
1191
1312
|
...r.fallback ? { fallback: true } : {}
|
|
1192
1313
|
};
|
|
@@ -1210,4 +1331,4 @@ function writePrerenderIndex(routes, outDir, options) {
|
|
|
1210
1331
|
fs.writeFileSync(path.join(outDir, "vinext-prerender.json"), JSON.stringify(index, null, 2), "utf-8");
|
|
1211
1332
|
}
|
|
1212
1333
|
//#endregion
|
|
1213
|
-
export { buildUrlFromParams, extractRscPayloadFromPrerenderedHtml, layoutOnlyParamSets, prerenderApp, prerenderPages, readPrerenderSecret, resolveParentParams, routeStaticParamSets, validateDiscoveredParams, writePrerenderIndex };
|
|
1334
|
+
export { buildUrlFromParams, extractRscPayloadFromPrerenderedHtml, layoutOnlyParamSets, localizePagesPath, prerenderApp, prerenderPages, readPrerenderSecret, resolveParentParams, routeStaticParamSets, validateDiscoveredParams, writePrerenderIndex };
|
|
@@ -11,7 +11,7 @@ import { rememberCurrentServerEntryImportMtime, startProdServer } from "../serve
|
|
|
11
11
|
import { enterPrerenderPhase } from "./prerender-phase.js";
|
|
12
12
|
import { prerenderApp, prerenderPages, writePrerenderIndex } from "./prerender.js";
|
|
13
13
|
import { injectPregeneratedConcretePaths } from "./inject-pregenerated-paths.js";
|
|
14
|
-
import { resolveBuiltRscEntryPath } from "./server-entry.js";
|
|
14
|
+
import { resolveBuiltPagesEntryPath, resolveBuiltRscEntryPath } from "./server-entry.js";
|
|
15
15
|
import fs from "node:fs";
|
|
16
16
|
//#region src/build/run-prerender.ts
|
|
17
17
|
/**
|
|
@@ -112,10 +112,11 @@ async function runPrerender(options) {
|
|
|
112
112
|
const buildOutDir = path.resolve(root, "dist");
|
|
113
113
|
const configuredRscServerDir = path.resolve(root, options.routeRootConfig?.rscOutDir ?? path.join("dist", "server"));
|
|
114
114
|
const rscBundlePath = options.rscBundlePath ?? resolveBuiltRscEntryPath(configuredRscServerDir);
|
|
115
|
+
const pagesBundlePath = options.pagesBundlePath ?? resolveBuiltPagesEntryPath(path.resolve(root, options.routeRootConfig?.ssrOutDir ?? path.join("dist", "server")));
|
|
115
116
|
const relativeEntryPath = path.relative(configuredRscServerDir, rscBundlePath);
|
|
116
117
|
const serverDir = !relativeEntryPath.startsWith("../") && !path.isAbsolute(relativeEntryPath) ? configuredRscServerDir : path.dirname(rscBundlePath);
|
|
117
118
|
const config = options.nextConfig ? { ...options.nextConfig } : { ...await resolveNextConfig(await loadNextConfig(root, PHASE_PRODUCTION_BUILD), root) };
|
|
118
|
-
const builtBuildId = readBuiltBuildId(manifestDir) ?? readBuiltBuildId(serverDir);
|
|
119
|
+
const builtBuildId = readBuiltBuildId(manifestDir) ?? readBuiltBuildId(appDir ? serverDir : path.dirname(pagesBundlePath));
|
|
119
120
|
if (builtBuildId) config.buildId = builtBuildId;
|
|
120
121
|
const mode = config.output === "export" ? "export" : "default";
|
|
121
122
|
const allRoutes = [];
|
|
@@ -183,7 +184,7 @@ async function runPrerender(options) {
|
|
|
183
184
|
...sharedProdServer ? {
|
|
184
185
|
_prodServer: sharedProdServer,
|
|
185
186
|
_prerenderSecret: sharedPrerenderSecret
|
|
186
|
-
} : { pagesBundlePath
|
|
187
|
+
} : { pagesBundlePath },
|
|
187
188
|
onProgress: ({ total, route }) => {
|
|
188
189
|
if (pagesTotal === 0) {
|
|
189
190
|
pagesTotal = total;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
//#region src/build/server-entry.d.ts
|
|
2
|
+
/** Pages builds emit entry.js in Node or index.js when the host owns the Worker entry. */
|
|
3
|
+
export declare function resolveBuiltPagesEntryPath(serverDir: string): string;
|
|
2
4
|
/** Resolve the built App handler even when a deployment host owns index.js. */
|
|
3
5
|
export declare function resolveBuiltRscEntryPath(serverDir: string): string;
|
|
4
6
|
//#endregion
|
|
@@ -2,6 +2,12 @@ import path from "../deps/.pnpm/pathslash@0.1.0/deps/pathslash/dist/index.js";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
//#region src/build/server-entry.ts
|
|
4
4
|
const RSC_ENTRY_MANIFEST_KEY = "virtual:vinext-rsc-entry";
|
|
5
|
+
/** Pages builds emit entry.js in Node or index.js when the host owns the Worker entry. */
|
|
6
|
+
function resolveBuiltPagesEntryPath(serverDir) {
|
|
7
|
+
const nodeEntryPath = path.join(serverDir, "entry.js");
|
|
8
|
+
const workerEntryPath = path.join(serverDir, "index.js");
|
|
9
|
+
return fs.existsSync(nodeEntryPath) || !fs.existsSync(workerEntryPath) ? nodeEntryPath : workerEntryPath;
|
|
10
|
+
}
|
|
5
11
|
/** Resolve the built App handler even when a deployment host owns index.js. */
|
|
6
12
|
function resolveBuiltRscEntryPath(serverDir) {
|
|
7
13
|
const fallbackPath = path.join(serverDir, "index.js");
|
|
@@ -25,4 +31,4 @@ function resolveBuiltRscEntryPath(serverDir) {
|
|
|
25
31
|
return fs.existsSync(entryPath) ? entryPath : fallbackPath;
|
|
26
32
|
}
|
|
27
33
|
//#endregion
|
|
28
|
-
export { resolveBuiltRscEntryPath };
|
|
34
|
+
export { resolveBuiltPagesEntryPath, resolveBuiltRscEntryPath };
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
* warn when this returns `undefined`.
|
|
15
15
|
*/
|
|
16
16
|
export declare function readPrerenderSecret(serverDir: string): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Read next.config `compress` from `vinext-server.json` in `serverDir`.
|
|
19
|
+
*
|
|
20
|
+
* Like `next start`, compression stays on unless the build recorded an
|
|
21
|
+
* explicit `compress: false`, so builds without the field keep compressing.
|
|
22
|
+
*/
|
|
23
|
+
export declare function readServerCompress(serverDir: string): boolean;
|
|
17
24
|
/**
|
|
18
25
|
* Read every server output root that contains a deployable response-stage
|
|
19
26
|
* graph. Paths are stored relative to the project root so build artifacts stay
|
|
@@ -20,6 +20,16 @@ function readPrerenderSecret(serverDir) {
|
|
|
20
20
|
return readJsonFile(manifestPath)?.prerenderSecret;
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
|
+
* Read next.config `compress` from `vinext-server.json` in `serverDir`.
|
|
24
|
+
*
|
|
25
|
+
* Like `next start`, compression stays on unless the build recorded an
|
|
26
|
+
* explicit `compress: false`, so builds without the field keep compressing.
|
|
27
|
+
*/
|
|
28
|
+
function readServerCompress(serverDir) {
|
|
29
|
+
const manifestPath = path.join(serverDir, "vinext-server.json");
|
|
30
|
+
return readJsonFile(manifestPath)?.compress !== false;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
23
33
|
* Read every server output root that contains a deployable response-stage
|
|
24
34
|
* graph. Paths are stored relative to the project root so build artifacts stay
|
|
25
35
|
* relocatable, then resolved for post-build sidecar updates.
|
|
@@ -31,4 +41,4 @@ function readServerRuntimeOutputDirs(serverDir, root) {
|
|
|
31
41
|
return manifest.runtimeOutputDirs.filter((outputDir) => typeof outputDir === "string").map((outputDir) => path.resolve(root, outputDir));
|
|
32
42
|
}
|
|
33
43
|
//#endregion
|
|
34
|
-
export { readPrerenderSecret, readServerRuntimeOutputDirs };
|
|
44
|
+
export { readPrerenderSecret, readServerCompress, readServerRuntimeOutputDirs };
|
|
@@ -74,7 +74,13 @@ export type CacheAdapterBuildOutput = {
|
|
|
74
74
|
export type CacheAdapterDescriptor<O extends Record<string, unknown> = Record<string, unknown>> = {
|
|
75
75
|
/**
|
|
76
76
|
* Module specifier (or absolute path, e.g. from `require.resolve(...)`) whose
|
|
77
|
-
* default export
|
|
77
|
+
* default export creates the adapter from one `{ env, options }` argument:
|
|
78
|
+
* either a factory `({ env, options }) => adapter` or a class
|
|
79
|
+
* `new Adapter({ env, options })`. Class syntax is invoked with `new`; any
|
|
80
|
+
* other function is called. For a constructor that is not class syntax (an
|
|
81
|
+
* ES5-compiled, bound or Proxy-wrapped class), export
|
|
82
|
+
* `(args) => new Adapter(args)`. The result must be the adapter object
|
|
83
|
+
* itself, not a Promise.
|
|
78
84
|
*/
|
|
79
85
|
adapter: string;
|
|
80
86
|
/** JSON-serializable options forwarded to the factory at runtime. */
|
|
@@ -103,7 +103,7 @@ function generateCacheAdaptersModule(cache) {
|
|
|
103
103
|
"export function registerConfiguredCacheAdapters() {}",
|
|
104
104
|
""
|
|
105
105
|
].join("\n");
|
|
106
|
-
const lines = ["// vinext: generated from the `cache` option in your vinext() plugin config."];
|
|
106
|
+
const lines = ["// vinext: generated from the `cache` option in your vinext() plugin config.", `import { instantiateCacheAdapter } from "vinext/shims/cache-adapter-instantiate";`];
|
|
107
107
|
if (data?.adapter) {
|
|
108
108
|
lines.push(`import __vinextDataAdapterFactory from ${JSON.stringify(data.adapter)};`);
|
|
109
109
|
lines.push(`import { registerDataCacheHandler } from "vinext/shims/cache-handler";`);
|
|
@@ -114,11 +114,11 @@ function generateCacheAdaptersModule(cache) {
|
|
|
114
114
|
} else if (dataProvidesBuildIdentity) lines.push(`import { DefaultCdnCacheAdapter } from "vinext/shims/cdn-cache";`, `import { registerCdnCacheAdapter } from "vinext/shims/cdn-cache-state";`);
|
|
115
115
|
lines.push("", "// A factory that throws (e.g. a missing binding on an incompatible runtime)", "// is logged and skipped so the default handler stays in place.", "function __vinextFormatAdapterError(error) {", " if (error instanceof Error && error.message) return error.message;", " try {", " return String(error);", " } catch {", " return '<unknown error>';", " }", "}", "", "let __vinextCacheAdaptersRegistered = false;", "", "export function registerConfiguredCacheAdapters(env) {", " if (typeof process !== 'undefined' && process.env?.__VINEXT_PRERENDER_PATH_DISCOVERY === '1') return;", " if (__vinextCacheAdaptersRegistered) return;", " __vinextCacheAdaptersRegistered = true;");
|
|
116
116
|
if (data?.adapter) {
|
|
117
|
-
lines.push(" try {", ` registerDataCacheHandler(() => __vinextDataAdapterFactory
|
|
117
|
+
lines.push(" try {", ` registerDataCacheHandler(() => instantiateCacheAdapter(__vinextDataAdapterFactory, { env, options: ${inlineOptions(data.adapter, data.options)} }, "data"));`);
|
|
118
118
|
if (dataProvidesBuildIdentity) lines.push(" registerCdnCacheAdapter(() => new DefaultCdnCacheAdapter(", " process.env.__VINEXT_RSC_BUILD_IDENTITY || process.env.__VINEXT_BUILD_ID,", " ));");
|
|
119
119
|
lines.push(" } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured data cache adapter; using the default handler.\\n\" + __vinextFormatAdapterError(error));", " }");
|
|
120
120
|
}
|
|
121
|
-
if (cdn?.adapter) lines.push(" try {", ` registerCdnCacheAdapter(() => __vinextCdnAdapterFactory
|
|
121
|
+
if (cdn?.adapter) lines.push(" try {", ` registerCdnCacheAdapter(() => instantiateCacheAdapter(__vinextCdnAdapterFactory, { env, options: ${inlineOptions(cdn.adapter, cdn.options)} }, "cdn"));`, " } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured CDN cache adapter; using the default adapter.\\n\" + __vinextFormatAdapterError(error));", " }");
|
|
122
122
|
lines.push("}", "");
|
|
123
123
|
return lines.join("\n");
|
|
124
124
|
}
|
|
@@ -57,6 +57,17 @@ export type NavigationRuntimeFunctions = {
|
|
|
57
57
|
preparePrefetchResponse?: (response: Response) => Promise<unknown>;
|
|
58
58
|
claimCurrentHistoryTreeSnapshot?: (historyUpdateMode: NavigationRuntimeHistoryUpdateMode, previousHistoryState: unknown) => void;
|
|
59
59
|
commitAppOwnedHistoryStateWrite?: (historyUpdateMode: NavigationRuntimeHistoryUpdateMode, previousHistoryState: unknown) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Called after a raw (non-app-owned) history.pushState/replaceState with a
|
|
62
|
+
* URL so an App Router navigation that has not committed yet is discarded,
|
|
63
|
+
* matching Next.js' ACTION_RESTORE.
|
|
64
|
+
*/
|
|
65
|
+
discardPendingNavigation?: () => void;
|
|
66
|
+
/**
|
|
67
|
+
* Called before any history.pushState/replaceState so a navigation React is
|
|
68
|
+
* committing writes its URL first, as Next.js does from an insertion effect.
|
|
69
|
+
*/
|
|
70
|
+
flushCommittingNavigationUrl?: () => void;
|
|
60
71
|
};
|
|
61
72
|
export type NavigationRuntimeBootstrap = {
|
|
62
73
|
routeManifest: RouteManifest | null;
|
|
@@ -66,7 +77,6 @@ export type NavigationRuntime = {
|
|
|
66
77
|
bootstrap: NavigationRuntimeBootstrap;
|
|
67
78
|
functions: NavigationRuntimeFunctions;
|
|
68
79
|
};
|
|
69
|
-
export declare const NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION = "vinext.navigationRuntime";
|
|
70
80
|
export declare const NAVIGATION_RUNTIME_KEY: unique symbol;
|
|
71
81
|
export declare function getNavigationRuntime(): NavigationRuntime | null;
|
|
72
82
|
export declare function registerNavigationRuntimeBootstrap(bootstrap: Partial<NavigationRuntimeBootstrap>): NavigationRuntime;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isUnknownRecord } from "../utils/record.js";
|
|
2
|
+
import { NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION } from "./browser-globals.js";
|
|
2
3
|
//#region src/client/navigation-runtime.ts
|
|
3
|
-
const NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION = "vinext.navigationRuntime";
|
|
4
4
|
const NAVIGATION_RUNTIME_KEY = Symbol.for(NAVIGATION_RUNTIME_SYMBOL_DESCRIPTION);
|
|
5
5
|
const ROUTE_MANIFEST_SEGMENT_GRAPH_MAP_KEYS = [
|
|
6
6
|
"boundaries",
|
|
@@ -31,7 +31,7 @@ function readRuntimeWindow() {
|
|
|
31
31
|
}
|
|
32
32
|
function isNavigationRuntimeFunctions(value) {
|
|
33
33
|
if (!isUnknownRecord(value)) return false;
|
|
34
|
-
return isOptionalRuntimeFunction(Reflect.get(value, "clearNavigationCaches")) && isOptionalRuntimeFunction(Reflect.get(value, "commitHashNavigation")) && isOptionalRuntimeFunction(Reflect.get(value, "navigateExternal")) && isOptionalRuntimeFunction(Reflect.get(value, "navigate")) && isOptionalRuntimeFunction(Reflect.get(value, "getPrefetchRouterState")) && isOptionalRuntimeFunction(Reflect.get(value, "notifyLinkNavigationStart")) && isOptionalRuntimeFunction(Reflect.get(value, "pingVisibleLinks")) && isOptionalRuntimeFunction(Reflect.get(value, "preparePrefetchResponse")) && isOptionalRuntimeFunction(Reflect.get(value, "claimCurrentHistoryTreeSnapshot")) && isOptionalRuntimeFunction(Reflect.get(value, "commitAppOwnedHistoryStateWrite"));
|
|
34
|
+
return isOptionalRuntimeFunction(Reflect.get(value, "clearNavigationCaches")) && isOptionalRuntimeFunction(Reflect.get(value, "commitHashNavigation")) && isOptionalRuntimeFunction(Reflect.get(value, "navigateExternal")) && isOptionalRuntimeFunction(Reflect.get(value, "navigate")) && isOptionalRuntimeFunction(Reflect.get(value, "getPrefetchRouterState")) && isOptionalRuntimeFunction(Reflect.get(value, "notifyLinkNavigationStart")) && isOptionalRuntimeFunction(Reflect.get(value, "pingVisibleLinks")) && isOptionalRuntimeFunction(Reflect.get(value, "preparePrefetchResponse")) && isOptionalRuntimeFunction(Reflect.get(value, "claimCurrentHistoryTreeSnapshot")) && isOptionalRuntimeFunction(Reflect.get(value, "commitAppOwnedHistoryStateWrite")) && isOptionalRuntimeFunction(Reflect.get(value, "discardPendingNavigation")) && isOptionalRuntimeFunction(Reflect.get(value, "flushCommittingNavigationUrl"));
|
|
35
35
|
}
|
|
36
36
|
function isNavigationRuntimeRscChunk(value) {
|
|
37
37
|
if (typeof value === "string") return true;
|
|
@@ -169,4 +169,4 @@ function hasAppNavigationRuntimeBootstrap() {
|
|
|
169
169
|
return getNavigationRuntime() !== null;
|
|
170
170
|
}
|
|
171
171
|
//#endregion
|
|
172
|
-
export { NAVIGATION_RUNTIME_KEY,
|
|
172
|
+
export { NAVIGATION_RUNTIME_KEY, ensureNavigationRuntimeRscBootstrap, getNavigationRuntime, hasAppNavigationRuntime, hasAppNavigationRuntimeBootstrap, registerNavigationRuntimeBootstrap, registerNavigationRuntimeFunctions };
|
|
@@ -307,6 +307,7 @@ function applyMiddlewareRequestHeaders(middlewareHeaders, request) {
|
|
|
307
307
|
method: request.method,
|
|
308
308
|
headers: nextHeaders,
|
|
309
309
|
body: request.body,
|
|
310
|
+
signal: request.signal,
|
|
310
311
|
duplex: request.body ? "half" : void 0
|
|
311
312
|
});
|
|
312
313
|
return {
|
|
@@ -859,9 +860,10 @@ async function proxyExternalRequest(request, externalUrl) {
|
|
|
859
860
|
try {
|
|
860
861
|
upstreamResponse = await fetch(targetUrl.href, {
|
|
861
862
|
...init,
|
|
862
|
-
signal: controller.signal
|
|
863
|
+
signal: AbortSignal.any([request.signal, controller.signal])
|
|
863
864
|
});
|
|
864
865
|
} catch (e) {
|
|
866
|
+
if (request.signal.aborted && !controller.signal.aborted) return new Response(null, { status: 499 });
|
|
865
867
|
if (e instanceof Error && e.name === "AbortError") {
|
|
866
868
|
console.error("[vinext] External rewrite proxy timeout:", targetUrl.href);
|
|
867
869
|
return new Response("Gateway Timeout", { status: 504 });
|