vinext 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -30
- package/dist/build/css-url-assets.d.ts +3 -1
- package/dist/build/css-url-assets.js +18 -1
- package/dist/build/inject-pregenerated-paths.d.ts +7 -0
- package/dist/build/inject-pregenerated-paths.js +21 -0
- package/dist/build/layout-classification.js +1 -1
- package/dist/build/nitro-route-rules.js +1 -1
- package/dist/build/pages-client-assets-module.d.ts +11 -0
- package/dist/build/pages-client-assets-module.js +27 -0
- package/dist/build/prerender-server-entry.d.ts +1 -0
- package/dist/build/prerender-server-entry.js +49 -0
- package/dist/build/prerender-server-pool.d.ts +44 -0
- package/dist/build/prerender-server-pool.js +194 -0
- package/dist/build/prerender.d.ts +2 -1
- package/dist/build/prerender.js +98 -27
- package/dist/build/report.d.ts +13 -2
- package/dist/build/report.js +99 -2
- package/dist/build/run-prerender.d.ts +7 -0
- package/dist/build/run-prerender.js +12 -2
- package/dist/build/standalone.js +2 -0
- package/dist/cache/cache-adapters-virtual.js +3 -3
- package/dist/check.d.ts +4 -6
- package/dist/check.js +48 -11
- package/dist/cli-args.d.ts +1 -2
- package/dist/cli-args.js +1 -1
- package/dist/cli-dev-config.d.ts +12 -0
- package/dist/cli-dev-config.js +23 -0
- package/dist/cli.js +112 -96
- package/dist/{server → client}/dev-error-overlay-store.d.ts +1 -1
- package/dist/{server → client}/dev-error-overlay-store.js +1 -1
- package/dist/{server → client}/dev-error-overlay.d.ts +1 -1
- package/dist/{server → client}/dev-error-overlay.js +2 -2
- package/dist/client/navigation-runtime.d.ts +2 -0
- package/dist/client/navigation-runtime.js +3 -1
- package/dist/client/vinext-next-data.d.ts +4 -1
- package/dist/client/window-next.d.ts +2 -1
- package/dist/cloudflare/index.d.ts +2 -2
- package/dist/cloudflare/index.js +2 -2
- package/dist/config/config-matchers.js +45 -19
- package/dist/config/next-config.d.ts +41 -9
- package/dist/config/next-config.js +60 -3
- package/dist/config/prerender.d.ts +34 -0
- package/dist/config/prerender.js +55 -0
- package/dist/entries/app-browser-entry.js +5 -1
- package/dist/entries/app-rsc-entry.d.ts +5 -3
- package/dist/entries/app-rsc-entry.js +44 -10
- package/dist/entries/app-rsc-manifest.js +2 -0
- package/dist/entries/pages-client-entry.d.ts +3 -0
- package/dist/entries/pages-client-entry.js +28 -3
- package/dist/entries/pages-server-entry.js +23 -6
- package/dist/image/image-adapters-virtual.d.ts +59 -0
- package/dist/image/image-adapters-virtual.js +59 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.js +482 -120
- package/dist/init-cloudflare.d.ts +43 -0
- package/dist/init-cloudflare.js +839 -0
- package/dist/init-platform.d.ts +40 -0
- package/dist/init-platform.js +195 -0
- package/dist/init.d.ts +16 -38
- package/dist/init.js +209 -99
- package/dist/node_modules/.pnpm/am-i-vibing@0.5.0/node_modules/am-i-vibing/dist/detector-1yx2Hoe0.js +294 -0
- package/dist/node_modules/.pnpm/process-ancestry@0.1.0/node_modules/process-ancestry/dist/index.js +94 -0
- package/dist/{cloudflare → packages/cloudflare}/src/cache/cdn-adapter.runtime.js +1 -1
- package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.d.ts +2 -2
- package/dist/{cloudflare → packages/cloudflare}/src/cache/kv-data-adapter.runtime.js +9 -2
- package/dist/packages/cloudflare/src/deploy-config.js +150 -0
- package/dist/packages/cloudflare/src/deploy-help.js +55 -0
- package/dist/packages/cloudflare/src/deploy.js +272 -0
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.d.ts +4 -41
- package/dist/{cloudflare → packages/cloudflare/src}/tpr.js +44 -20
- package/dist/plugins/ast-scope.d.ts +16 -0
- package/dist/plugins/ast-scope.js +62 -0
- package/dist/plugins/ast-utils.d.ts +27 -1
- package/dist/plugins/ast-utils.js +32 -1
- package/dist/plugins/css-module-imports.d.ts +14 -0
- package/dist/plugins/css-module-imports.js +59 -0
- package/dist/plugins/extensionless-dynamic-import.js +2 -2
- package/dist/plugins/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.d.ts +11 -0
- package/dist/plugins/ignore-dynamic-requests.js +530 -0
- package/dist/plugins/og-assets.js +2 -1
- package/dist/plugins/optimize-imports.js +1 -1
- package/dist/plugins/rsc-reference-validation-normalizer.d.ts +12 -0
- package/dist/plugins/rsc-reference-validation-normalizer.js +48 -0
- package/dist/plugins/sass.d.ts +17 -1
- package/dist/plugins/sass.js +74 -1
- package/dist/plugins/styled-jsx.d.ts +16 -0
- package/dist/plugins/styled-jsx.js +149 -0
- package/dist/plugins/typeof-window.d.ts +1 -1
- package/dist/plugins/typeof-window.js +28 -56
- package/dist/routing/app-route-graph.d.ts +23 -2
- package/dist/routing/app-route-graph.js +138 -38
- package/dist/routing/file-matcher.d.ts +11 -1
- package/dist/routing/file-matcher.js +18 -3
- package/dist/routing/pages-router.js +2 -2
- package/dist/server/api-handler.js +9 -14
- package/dist/server/app-browser-action-result.d.ts +4 -1
- package/dist/server/app-browser-action-result.js +8 -1
- package/dist/server/app-browser-entry.js +198 -57
- package/dist/server/app-browser-interception-context.d.ts +1 -0
- package/dist/server/app-browser-interception-context.js +4 -2
- package/dist/server/app-browser-navigation-controller.d.ts +2 -0
- package/dist/server/app-browser-navigation-controller.js +60 -31
- package/dist/server/app-browser-server-action-client.d.ts +1 -1
- package/dist/server/app-browser-server-action-client.js +8 -7
- package/dist/server/app-browser-state.d.ts +12 -1
- package/dist/server/app-browser-state.js +25 -8
- package/dist/server/app-browser-visible-commit.d.ts +6 -1
- package/dist/server/app-browser-visible-commit.js +42 -24
- package/dist/server/app-elements-wire.d.ts +9 -2
- package/dist/server/app-elements-wire.js +8 -1
- package/dist/server/app-elements.d.ts +2 -2
- package/dist/server/app-elements.js +4 -3
- package/dist/server/app-fallback-renderer.d.ts +2 -1
- package/dist/server/app-fallback-renderer.js +10 -6
- package/dist/server/app-hydration-cache-publication.d.ts +11 -0
- package/dist/server/app-hydration-cache-publication.js +43 -0
- package/dist/server/app-middleware.d.ts +4 -3
- package/dist/server/app-middleware.js +8 -3
- package/dist/server/app-optimistic-routing.js +11 -4
- package/dist/server/app-page-boundary.js +2 -1
- package/dist/server/app-page-cache-finalizer.d.ts +1 -0
- package/dist/server/app-page-cache-finalizer.js +5 -4
- package/dist/server/app-page-cache-render.d.ts +1 -0
- package/dist/server/app-page-cache-render.js +8 -4
- package/dist/server/app-page-cache.d.ts +1 -0
- package/dist/server/app-page-cache.js +27 -7
- package/dist/server/app-page-dispatch.d.ts +1 -0
- package/dist/server/app-page-dispatch.js +26 -8
- package/dist/server/app-page-element-builder.d.ts +2 -1
- package/dist/server/app-page-element-builder.js +59 -4
- package/dist/server/app-page-execution.js +2 -1
- package/dist/server/app-page-probe.js +5 -0
- package/dist/server/app-page-render-identity.d.ts +2 -0
- package/dist/server/app-page-render-identity.js +3 -2
- package/dist/server/app-page-render.d.ts +2 -0
- package/dist/server/app-page-render.js +85 -16
- package/dist/server/app-page-request.d.ts +14 -0
- package/dist/server/app-page-request.js +69 -4
- package/dist/server/app-page-response.d.ts +7 -0
- package/dist/server/app-page-response.js +16 -4
- package/dist/server/app-page-route-wiring.d.ts +8 -1
- package/dist/server/app-page-route-wiring.js +32 -18
- package/dist/server/app-page-segment-state.d.ts +2 -1
- package/dist/server/app-page-segment-state.js +3 -1
- package/dist/server/app-page-stream.d.ts +7 -1
- package/dist/server/app-page-stream.js +3 -1
- package/dist/server/app-route-handler-execution.js +5 -1
- package/dist/server/app-route-handler-response.js +1 -0
- package/dist/server/app-route-handler-runtime.js +1 -1
- package/dist/server/app-route-tree-prefetch.d.ts +43 -0
- package/dist/server/app-route-tree-prefetch.js +187 -0
- package/dist/server/app-router-entry.js +9 -2
- package/dist/server/app-rsc-cache-busting.d.ts +2 -1
- package/dist/server/app-rsc-cache-busting.js +9 -4
- package/dist/server/app-rsc-handler.d.ts +7 -0
- package/dist/server/app-rsc-handler.js +148 -39
- package/dist/server/app-rsc-render-mode.d.ts +3 -2
- package/dist/server/app-rsc-render-mode.js +4 -1
- package/dist/server/app-rsc-request-normalization.d.ts +6 -6
- package/dist/server/app-rsc-request-normalization.js +10 -8
- package/dist/server/app-segment-config.d.ts +11 -0
- package/dist/server/app-segment-config.js +62 -6
- package/dist/server/app-server-action-execution.d.ts +1 -0
- package/dist/server/app-server-action-execution.js +61 -30
- package/dist/server/app-ssr-entry.d.ts +3 -0
- package/dist/server/app-ssr-entry.js +13 -5
- package/dist/server/app-ssr-stream.d.ts +7 -3
- package/dist/server/app-ssr-stream.js +10 -6
- package/dist/server/app-visited-response-cache.d.ts +6 -0
- package/dist/server/app-visited-response-cache.js +3 -1
- package/dist/server/cache-control.d.ts +3 -1
- package/dist/server/cache-control.js +13 -1
- package/dist/server/client-trace-metadata.js +26 -0
- package/dist/server/default-global-not-found-module.d.ts +14 -0
- package/dist/server/default-global-not-found-module.js +14 -0
- package/dist/server/dev-route-files.js +4 -0
- package/dist/server/dev-server.d.ts +11 -1
- package/dist/server/dev-server.js +94 -35
- package/dist/server/dev-stack-sourcemap.d.ts +1 -1
- package/dist/server/dev-stack-sourcemap.js +1 -1
- package/dist/server/fetch-handler.d.ts +2 -0
- package/dist/server/fetch-handler.js +18 -0
- package/dist/server/headers.d.ts +7 -15
- package/dist/server/headers.js +11 -18
- package/dist/server/image-optimization.d.ts +51 -1
- package/dist/server/image-optimization.js +52 -2
- package/dist/server/implicit-tags.js +1 -1
- package/dist/server/isr-cache.d.ts +3 -2
- package/dist/server/isr-cache.js +9 -5
- package/dist/server/metadata-routes.d.ts +3 -1
- package/dist/server/metadata-routes.js +12 -2
- package/dist/server/middleware-runtime.js +6 -1
- package/dist/server/navigation-planner.d.ts +1 -0
- package/dist/server/navigation-planner.js +14 -3
- package/dist/server/pages-api-route.js +2 -2
- package/dist/server/pages-asset-tags.d.ts +4 -6
- package/dist/server/pages-asset-tags.js +12 -12
- package/dist/server/pages-client-assets.d.ts +12 -0
- package/dist/server/pages-client-assets.js +10 -0
- package/dist/server/pages-data-route.d.ts +4 -2
- package/dist/server/pages-data-route.js +18 -4
- package/dist/server/pages-dev-module-url.d.ts +2 -1
- package/dist/server/pages-dev-module-url.js +6 -3
- package/dist/server/pages-node-compat.d.ts +19 -1
- package/dist/server/pages-node-compat.js +81 -4
- package/dist/server/pages-page-data.d.ts +33 -1
- package/dist/server/pages-page-data.js +62 -33
- package/dist/server/pages-page-handler.d.ts +2 -1
- package/dist/server/pages-page-handler.js +38 -19
- package/dist/server/pages-page-response.d.ts +8 -0
- package/dist/server/pages-page-response.js +7 -3
- package/dist/server/pages-request-pipeline.d.ts +9 -5
- package/dist/server/pages-request-pipeline.js +55 -7
- package/dist/server/pages-router-entry.d.ts +30 -0
- package/dist/server/pages-router-entry.js +108 -0
- package/dist/server/prerender-manifest.d.ts +3 -1
- package/dist/server/prerender-route-params.js +1 -1
- package/dist/server/prod-server.d.ts +5 -3
- package/dist/server/prod-server.js +68 -39
- package/dist/server/request-pipeline.js +2 -1
- package/dist/server/seed-cache.js +4 -4
- package/dist/shims/app-router-scroll-state.d.ts +1 -0
- package/dist/shims/app-router-scroll-state.js +1 -0
- package/dist/shims/app-router-scroll.js +2 -1
- package/dist/shims/cache-handler.js +8 -1
- package/dist/shims/cache.js +22 -15
- package/dist/shims/cdn-cache.js +1 -1
- package/dist/shims/dynamic-preload-chunks.js +2 -1
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +77 -52
- package/dist/shims/form.d.ts +4 -2
- package/dist/shims/form.js +37 -43
- package/dist/shims/headers.d.ts +7 -1
- package/dist/shims/headers.js +17 -3
- package/dist/shims/image.js +75 -14
- package/dist/shims/internal/app-prefetch-fetch-queue.d.ts +10 -0
- package/dist/shims/internal/app-prefetch-fetch-queue.js +61 -0
- package/dist/shims/internal/app-route-detection.d.ts +2 -17
- package/dist/shims/internal/app-route-detection.js +4 -17
- package/dist/shims/internal/hybrid-client-route-owner-direct.d.ts +23 -0
- package/dist/shims/internal/hybrid-client-route-owner-direct.js +51 -0
- package/dist/shims/internal/hybrid-client-route-owner.d.ts +3 -15
- package/dist/shims/internal/hybrid-client-route-owner.js +40 -58
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +10 -5
- package/dist/shims/internal/pages-data-fetch-dedup.js +84 -14
- package/dist/shims/internal/pages-data-target.d.ts +18 -12
- package/dist/shims/internal/pages-data-target.js +97 -13
- package/dist/shims/internal/pages-router-components.d.ts +7 -0
- package/dist/shims/internal/pages-router-components.js +13 -0
- package/dist/shims/layout-segment-context.d.ts +4 -1
- package/dist/shims/layout-segment-context.js +18 -4
- package/dist/shims/link.d.ts +1 -1
- package/dist/shims/link.js +224 -58
- package/dist/shims/navigation.d.ts +19 -3
- package/dist/shims/navigation.js +245 -47
- package/dist/shims/request-context.js +18 -0
- package/dist/shims/root-params.d.ts +15 -1
- package/dist/shims/root-params.js +21 -1
- package/dist/shims/router.d.ts +5 -7
- package/dist/shims/router.js +387 -102
- package/dist/shims/server.js +3 -2
- package/dist/shims/slot.js +3 -6
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -1
- package/dist/utils/client-runtime-metadata.d.ts +2 -18
- package/dist/utils/client-runtime-metadata.js +31 -22
- package/dist/utils/dev-stack-sourcemap-endpoint.d.ts +4 -0
- package/dist/{server → utils}/dev-stack-sourcemap-endpoint.js +1 -1
- package/dist/utils/domain-locale.d.ts +6 -3
- package/dist/{server → utils}/middleware-request-headers.d.ts +1 -1
- package/dist/{server → utils}/middleware-request-headers.js +3 -3
- package/dist/utils/project.d.ts +48 -2
- package/dist/utils/project.js +225 -4
- package/dist/utils/protocol-headers.d.ts +23 -0
- package/dist/utils/protocol-headers.js +23 -0
- package/dist/utils/react-version.d.ts +4 -0
- package/dist/utils/react-version.js +44 -0
- package/dist/utils/vite-version.d.ts +2 -0
- package/dist/utils/vite-version.js +11 -1
- package/package.json +47 -2
- package/dist/deploy.d.ts +0 -197
- package/dist/deploy.js +0 -1040
- package/dist/server/dev-stack-sourcemap-endpoint.d.ts +0 -4
- /package/dist/{cloudflare → packages/cloudflare}/src/utils/cache-control-metadata.js +0 -0
package/dist/build/prerender.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { createValidFileMatcher, findFileWithExtensions } from "../routing/file-matcher.js";
|
|
2
|
-
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../
|
|
3
|
-
import {
|
|
2
|
+
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER, VINEXT_PRERENDER_SPECULATIVE_HEADER } from "../utils/protocol-headers.js";
|
|
3
|
+
import { VINEXT_PRERENDER_CACHE_LIFE_HEADER } from "../server/headers.js";
|
|
4
|
+
import { classifyAppRoute, classifyPagesRoute, getAppRouteRenderEntryPath } from "./report.js";
|
|
4
5
|
import { NoOpCacheHandler, getCacheHandler, setCacheHandler } from "../shims/cache-handler.js";
|
|
5
6
|
import { headersContextFromRequest, runWithHeadersContext } from "../shims/headers.js";
|
|
6
7
|
import { _consumeRequestScopedCacheLife } from "../shims/cache-request-state.js";
|
|
7
|
-
import {
|
|
8
|
+
import { normalizeStaticPathsEntry } from "../routing/route-pattern.js";
|
|
8
9
|
import { BLOCKED_PAGES } from "../shims/constants.js";
|
|
10
|
+
import { buildPregeneratedConcretePathTable } from "../server/prerender-manifest.js";
|
|
9
11
|
import { concatUint8Arrays, decodeRscEmbeddedChunk } from "../server/app-rsc-embedded-chunks.js";
|
|
10
12
|
import { navigationRuntimeRscBootstrapExpression } from "../server/app-ssr-stream.js";
|
|
11
|
-
import { createAppPprFallbackShells, markAppPprDynamicFallbackShellHtml } from "../server/app-ppr-fallback-shell.js";
|
|
12
13
|
import { encodePrerenderRouteParams, serializePrerenderRouteParamsHeader } from "../server/prerender-route-params.js";
|
|
13
14
|
import { readPrerenderSecret } from "./server-manifest.js";
|
|
15
|
+
import { createAppPprFallbackShells, markAppPprDynamicFallbackShellHtml } from "../server/app-ppr-fallback-shell.js";
|
|
14
16
|
import { getOutputPath, getRscOutputPath } from "../utils/prerender-output-paths.js";
|
|
15
17
|
import { startProdServer } from "../server/prod-server.js";
|
|
18
|
+
import { prerenderPoolAvailable, resolvePrerenderPoolSize, startPrerenderServerPool } from "./prerender-server-pool.js";
|
|
16
19
|
import fs from "node:fs";
|
|
17
20
|
import path from "node:path";
|
|
18
21
|
import os from "node:os";
|
|
@@ -41,6 +44,14 @@ function isExperimentalPprFallbackShellGenerationEnabled(env = process.env) {
|
|
|
41
44
|
function getErrorMessageWithStack(err) {
|
|
42
45
|
return err.stack || err.message;
|
|
43
46
|
}
|
|
47
|
+
async function startOptionalPrerenderServerPool(outDir, poolSize) {
|
|
48
|
+
try {
|
|
49
|
+
return await startPrerenderServerPool(outDir, poolSize);
|
|
50
|
+
} catch (e) {
|
|
51
|
+
console.warn(`[vinext] prerender render pool failed to start; falling back to single-process render: ${e instanceof Error ? e.message : String(e)}`);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
44
55
|
var PrerenderUserFunctionError = class extends Error {};
|
|
45
56
|
function parsePrerenderEndpointError(text) {
|
|
46
57
|
try {
|
|
@@ -80,7 +91,7 @@ function extractRscPayloadFromPrerenderedHtml(html) {
|
|
|
80
91
|
let match;
|
|
81
92
|
while ((match = scriptPattern.exec(html)) !== null) {
|
|
82
93
|
const script = (match[1] ?? "").trim().replace(/;$/, "");
|
|
83
|
-
if (script === RSC_RUNTIME_DONE_SCRIPT || script === RSC_LEGACY_DONE_SCRIPT) {
|
|
94
|
+
if (script === RSC_RUNTIME_DONE_SCRIPT || script === RSC_LEGACY_DONE_SCRIPT || script.endsWith(`;${RSC_RUNTIME_DONE_SCRIPT}`)) {
|
|
84
95
|
sawDone = true;
|
|
85
96
|
continue;
|
|
86
97
|
}
|
|
@@ -256,11 +267,12 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
256
267
|
const previousPrerenderFlag = process.env.VINEXT_PRERENDER;
|
|
257
268
|
process.env.VINEXT_PRERENDER = "1";
|
|
258
269
|
let ownedProdServerHandle = null;
|
|
270
|
+
let renderPool = null;
|
|
259
271
|
try {
|
|
260
272
|
let prerenderSecret = options._prerenderSecret;
|
|
261
273
|
if (!prerenderSecret && pagesBundlePath) prerenderSecret = readPrerenderSecret(path.dirname(pagesBundlePath));
|
|
262
274
|
if (!prerenderSecret) console.warn("[vinext] Warning: prerender secret not found. /__vinext/prerender/* endpoints will return 403 and dynamic routes will produce no paths. Run `vinext build` to regenerate the secret.");
|
|
263
|
-
const
|
|
275
|
+
const prodServer = options._prodServer ? options._prodServer : await (async () => {
|
|
264
276
|
const srv = await startProdServer({
|
|
265
277
|
port: 0,
|
|
266
278
|
host: "127.0.0.1",
|
|
@@ -270,12 +282,18 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
270
282
|
});
|
|
271
283
|
ownedProdServerHandle = srv;
|
|
272
284
|
return srv;
|
|
273
|
-
})()
|
|
285
|
+
})();
|
|
286
|
+
const baseUrl = `http://127.0.0.1:${prodServer.port}`;
|
|
274
287
|
const secretHeaders = prerenderSecret ? { [VINEXT_PRERENDER_SECRET_HEADER]: prerenderSecret } : {};
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
288
|
+
let renderPorts = [prodServer.port];
|
|
289
|
+
let renderRoundRobin = 0;
|
|
290
|
+
const renderPage = (urlPath) => {
|
|
291
|
+
const port = renderPorts[renderRoundRobin++ % renderPorts.length];
|
|
292
|
+
return fetch(`http://127.0.0.1:${port}${urlPath}`, {
|
|
293
|
+
headers: secretHeaders,
|
|
294
|
+
redirect: "manual"
|
|
295
|
+
});
|
|
296
|
+
};
|
|
279
297
|
const bundlePageRoutes = routes.map((r) => ({
|
|
280
298
|
pattern: r.pattern,
|
|
281
299
|
isDynamic: r.isDynamic ?? false,
|
|
@@ -396,6 +414,13 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
396
414
|
revalidate
|
|
397
415
|
});
|
|
398
416
|
}
|
|
417
|
+
if (!options._prodServer && pagesBundlePath && prerenderPoolAvailable()) {
|
|
418
|
+
const poolSize = resolvePrerenderPoolSize(pagesToRender.length, concurrency);
|
|
419
|
+
if (poolSize > 1) {
|
|
420
|
+
renderPool = await startOptionalPrerenderServerPool(path.dirname(path.dirname(pagesBundlePath)), poolSize);
|
|
421
|
+
if (renderPool) renderPorts = renderPool.ports;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
399
424
|
let completed = 0;
|
|
400
425
|
const pageResults = await runWithConcurrency(pagesToRender, concurrency, async ({ route, urlPath, revalidate }) => {
|
|
401
426
|
let result;
|
|
@@ -426,6 +451,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
426
451
|
...urlPath !== route.pattern ? { path: urlPath } : {}
|
|
427
452
|
};
|
|
428
453
|
} catch (e) {
|
|
454
|
+
renderPool?.recordRenderError(e);
|
|
429
455
|
const err = e;
|
|
430
456
|
result = {
|
|
431
457
|
route: route.pattern,
|
|
@@ -442,6 +468,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
442
468
|
return result;
|
|
443
469
|
});
|
|
444
470
|
results.push(...pageResults);
|
|
471
|
+
renderPool?.assertHealthy();
|
|
445
472
|
const hasCustom404 = findFileWithExtensions(path.join(pagesDir, "404"), fileMatcher);
|
|
446
473
|
const hasErrorPage = findFileWithExtensions(path.join(pagesDir, "_error"), fileMatcher);
|
|
447
474
|
if (hasCustom404 || hasErrorPage) try {
|
|
@@ -459,13 +486,17 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
459
486
|
router: "pages"
|
|
460
487
|
});
|
|
461
488
|
}
|
|
462
|
-
} catch {
|
|
489
|
+
} catch (e) {
|
|
490
|
+
renderPool?.recordRenderError(e);
|
|
491
|
+
}
|
|
492
|
+
renderPool?.assertHealthy();
|
|
463
493
|
if (!skipManifest) writePrerenderIndex(results, manifestDir, {
|
|
464
494
|
buildId: config.buildId,
|
|
465
495
|
trailingSlash: config.trailingSlash
|
|
466
496
|
});
|
|
467
497
|
return { routes: results };
|
|
468
498
|
} finally {
|
|
499
|
+
if (renderPool) await renderPool.close();
|
|
469
500
|
setCacheHandler(previousHandler);
|
|
470
501
|
if (previousPrerenderFlag === void 0) delete process.env.VINEXT_PRERENDER;
|
|
471
502
|
else process.env.VINEXT_PRERENDER = previousPrerenderFlag;
|
|
@@ -504,10 +535,13 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
504
535
|
let rscHandler;
|
|
505
536
|
let staticParamsMap = {};
|
|
506
537
|
let ownedProdServerHandle = null;
|
|
538
|
+
let renderPool = null;
|
|
539
|
+
let renderPorts = [];
|
|
540
|
+
let renderRoundRobin = 0;
|
|
507
541
|
try {
|
|
508
542
|
const prerenderSecret = readPrerenderSecret(serverDir);
|
|
509
543
|
if (!prerenderSecret) console.warn("[vinext] Warning: prerender secret not found. /__vinext/prerender/* endpoints will return 403 and generateStaticParams will not be called. Run `vinext build` to regenerate the secret.");
|
|
510
|
-
const
|
|
544
|
+
const prodServer = options._prodServer ? options._prodServer : await (async () => {
|
|
511
545
|
const srv = await startProdServer({
|
|
512
546
|
port: 0,
|
|
513
547
|
host: "127.0.0.1",
|
|
@@ -517,11 +551,13 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
517
551
|
});
|
|
518
552
|
ownedProdServerHandle = srv;
|
|
519
553
|
return srv;
|
|
520
|
-
})()
|
|
554
|
+
})();
|
|
555
|
+
const baseUrl = `http://127.0.0.1:${prodServer.port}`;
|
|
556
|
+
renderPorts = [prodServer.port];
|
|
521
557
|
const secretHeaders = prerenderSecret ? { [VINEXT_PRERENDER_SECRET_HEADER]: prerenderSecret } : {};
|
|
522
558
|
rscHandler = (req) => {
|
|
523
559
|
const parsed = new URL(req.url);
|
|
524
|
-
const url =
|
|
560
|
+
const url = `http://127.0.0.1:${renderPorts[renderRoundRobin++ % renderPorts.length]}${parsed.pathname}${parsed.search}`;
|
|
525
561
|
return fetch(url, {
|
|
526
562
|
method: req.method,
|
|
527
563
|
headers: {
|
|
@@ -717,25 +753,32 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
717
753
|
const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParams);
|
|
718
754
|
const htmlHeaders = new Headers();
|
|
719
755
|
if (prerenderRouteParamsHeader !== null) htmlHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
756
|
+
if (isSpeculative) htmlHeaders.set(VINEXT_PRERENDER_SPECULATIVE_HEADER, "1");
|
|
720
757
|
const htmlRequest = new Request(`http://localhost${urlPath}`, { headers: htmlHeaders });
|
|
721
758
|
const htmlRender = await runWithHeadersContext(headersContextFromRequest(htmlRequest), async () => {
|
|
722
759
|
const response = await rscHandler(htmlRequest);
|
|
723
760
|
const cacheControl = response.headers.get("cache-control") ?? "";
|
|
724
|
-
|
|
761
|
+
const linkHeader = response.headers.get("link");
|
|
762
|
+
const responseCacheLife = readPrerenderCacheLifeHeader(response.headers);
|
|
763
|
+
if (!response.ok || cacheControl.includes("no-store")) {
|
|
725
764
|
await response.body?.cancel();
|
|
726
765
|
return {
|
|
727
766
|
cacheControl,
|
|
767
|
+
linkHeader,
|
|
728
768
|
html: null,
|
|
729
769
|
ok: response.ok,
|
|
730
770
|
requestCacheLife: null,
|
|
731
771
|
status: response.status
|
|
732
772
|
};
|
|
733
773
|
}
|
|
774
|
+
const html = await response.text();
|
|
775
|
+
const processCacheLife = _consumeRequestScopedCacheLife();
|
|
734
776
|
return {
|
|
735
777
|
cacheControl,
|
|
736
|
-
|
|
778
|
+
linkHeader,
|
|
779
|
+
html,
|
|
737
780
|
ok: true,
|
|
738
|
-
requestCacheLife:
|
|
781
|
+
requestCacheLife: responseCacheLife ?? processCacheLife,
|
|
739
782
|
status: response.status
|
|
740
783
|
};
|
|
741
784
|
});
|
|
@@ -752,13 +795,11 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
752
795
|
error: `RSC handler returned ${htmlRender.status}`
|
|
753
796
|
};
|
|
754
797
|
}
|
|
755
|
-
if (
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
};
|
|
761
|
-
}
|
|
798
|
+
if (htmlCacheControl.includes("no-store")) return {
|
|
799
|
+
route: routePattern,
|
|
800
|
+
status: "skipped",
|
|
801
|
+
reason: "dynamic"
|
|
802
|
+
};
|
|
762
803
|
if (htmlRender.html === null) return {
|
|
763
804
|
route: routePattern,
|
|
764
805
|
status: "error",
|
|
@@ -772,6 +813,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
772
813
|
RSC: "1"
|
|
773
814
|
});
|
|
774
815
|
if (prerenderRouteParamsHeader !== null) rscHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
816
|
+
if (isSpeculative) rscHeaders.set(VINEXT_PRERENDER_SPECULATIVE_HEADER, "1");
|
|
775
817
|
const rscRequest = new Request(`http://localhost${urlPath}`, { headers: rscHeaders });
|
|
776
818
|
const rscRes = await runWithHeadersContext(headersContextFromRequest(rscRequest), () => rscHandler(rscRequest));
|
|
777
819
|
if (!rscRes.ok) {
|
|
@@ -800,10 +842,12 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
800
842
|
revalidate: renderedRevalidate,
|
|
801
843
|
...typeof renderedRevalidate === "number" ? { expire: renderedCacheControl.expire } : {},
|
|
802
844
|
router: "app",
|
|
845
|
+
...htmlRender.linkHeader ? { headers: { link: htmlRender.linkHeader } } : {},
|
|
803
846
|
...urlPath !== routePattern ? { path: urlPath } : {},
|
|
804
847
|
...isFallback ? { fallback: true } : {}
|
|
805
848
|
};
|
|
806
849
|
} catch (e) {
|
|
850
|
+
renderPool?.recordRenderError(e);
|
|
807
851
|
if (isSpeculative) return {
|
|
808
852
|
route: routePattern,
|
|
809
853
|
status: "skipped",
|
|
@@ -818,6 +862,13 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
818
862
|
};
|
|
819
863
|
}
|
|
820
864
|
}
|
|
865
|
+
if (!options._prodServer && prerenderPoolAvailable()) {
|
|
866
|
+
const poolSize = resolvePrerenderPoolSize(urlsToRender.length, concurrency);
|
|
867
|
+
if (poolSize > 1) {
|
|
868
|
+
renderPool = await startOptionalPrerenderServerPool(path.dirname(serverDir), poolSize);
|
|
869
|
+
if (renderPool) renderPorts = renderPool.ports;
|
|
870
|
+
}
|
|
871
|
+
}
|
|
821
872
|
let completedApp = 0;
|
|
822
873
|
const appResults = await runWithConcurrency(urlsToRender, concurrency, async (urlToRender) => {
|
|
823
874
|
const result = await renderUrl(urlToRender);
|
|
@@ -830,6 +881,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
830
881
|
return result;
|
|
831
882
|
});
|
|
832
883
|
results.push(...appResults);
|
|
884
|
+
renderPool?.assertHealthy();
|
|
833
885
|
const outputFiles = mode === "export" && metadataRoutes.length > 0 ? emitStaticMetadataFiles(metadataRoutes, outDir) : [];
|
|
834
886
|
try {
|
|
835
887
|
const notFoundRequest = new Request(`http://localhost${NOT_FOUND_SENTINEL_PATH}`);
|
|
@@ -847,7 +899,10 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
847
899
|
router: "app"
|
|
848
900
|
});
|
|
849
901
|
}
|
|
850
|
-
} catch {
|
|
902
|
+
} catch (e) {
|
|
903
|
+
renderPool?.recordRenderError(e);
|
|
904
|
+
}
|
|
905
|
+
renderPool?.assertHealthy();
|
|
851
906
|
if (!skipManifest) writePrerenderIndex(results, manifestDir, {
|
|
852
907
|
buildId: config.buildId,
|
|
853
908
|
trailingSlash: config.trailingSlash
|
|
@@ -857,6 +912,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
857
912
|
...outputFiles.length > 0 ? { outputFiles } : {}
|
|
858
913
|
};
|
|
859
914
|
} finally {
|
|
915
|
+
if (renderPool) await renderPool.close();
|
|
860
916
|
setCacheHandler(previousHandler);
|
|
861
917
|
if (previousPrerenderFlag === void 0) delete process.env.VINEXT_PRERENDER;
|
|
862
918
|
else process.env.VINEXT_PRERENDER = previousPrerenderFlag;
|
|
@@ -876,6 +932,19 @@ function resolveRenderedCacheControl(requestCacheLife, cacheControl, fallbackExp
|
|
|
876
932
|
...revalidate === void 0 ? {} : { revalidate }
|
|
877
933
|
};
|
|
878
934
|
}
|
|
935
|
+
function readPrerenderCacheLifeHeader(headers) {
|
|
936
|
+
const value = headers.get(VINEXT_PRERENDER_CACHE_LIFE_HEADER);
|
|
937
|
+
if (!value) return null;
|
|
938
|
+
try {
|
|
939
|
+
const parsed = JSON.parse(value);
|
|
940
|
+
const cacheLife = {};
|
|
941
|
+
if (typeof parsed.revalidate === "number" && Number.isFinite(parsed.revalidate)) cacheLife.revalidate = parsed.revalidate;
|
|
942
|
+
if (typeof parsed.expire === "number" && Number.isFinite(parsed.expire)) cacheLife.expire = parsed.expire;
|
|
943
|
+
return cacheLife.revalidate === void 0 && cacheLife.expire === void 0 ? null : cacheLife;
|
|
944
|
+
} catch {
|
|
945
|
+
return null;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
879
948
|
function resolveRenderedExpireSeconds(options) {
|
|
880
949
|
const { fallbackExpireSeconds, sMaxage, staleWhileRevalidate } = options;
|
|
881
950
|
if (sMaxage === void 0 || staleWhileRevalidate === void 0) return fallbackExpireSeconds;
|
|
@@ -907,6 +976,7 @@ function writePrerenderIndex(routes, outDir, options) {
|
|
|
907
976
|
revalidate: r.revalidate,
|
|
908
977
|
...typeof r.revalidate === "number" ? { expire: r.expire } : {},
|
|
909
978
|
router: r.router,
|
|
979
|
+
...r.headers ? { headers: r.headers } : {},
|
|
910
980
|
...r.path ? { path: r.path } : {},
|
|
911
981
|
...r.fallback ? { fallback: true } : {}
|
|
912
982
|
};
|
|
@@ -924,7 +994,8 @@ function writePrerenderIndex(routes, outDir, options) {
|
|
|
924
994
|
const index = {
|
|
925
995
|
...buildId ? { buildId } : {},
|
|
926
996
|
...typeof trailingSlash === "boolean" ? { trailingSlash } : {},
|
|
927
|
-
routes: indexRoutes
|
|
997
|
+
routes: indexRoutes,
|
|
998
|
+
pregeneratedConcretePaths: buildPregeneratedConcretePathTable({ routes: indexRoutes })
|
|
928
999
|
};
|
|
929
1000
|
fs.writeFileSync(path.join(outDir, "vinext-prerender.json"), JSON.stringify(index, null, 2), "utf-8");
|
|
930
1001
|
}
|
package/dist/build/report.d.ts
CHANGED
|
@@ -17,6 +17,13 @@ type RouteRow = {
|
|
|
17
17
|
prerendered?: boolean;
|
|
18
18
|
};
|
|
19
19
|
type AppRouteRenderEntry = Pick<AppRoute, "pagePath" | "routePath" | "parallelSlots">;
|
|
20
|
+
type StaticMiddlewareMatcherObject = {
|
|
21
|
+
source: string;
|
|
22
|
+
locale?: false;
|
|
23
|
+
has?: Array<Record<string, string>>;
|
|
24
|
+
missing?: Array<Record<string, string>>;
|
|
25
|
+
};
|
|
26
|
+
type StaticMiddlewareMatcher = string | Array<string | StaticMiddlewareMatcherObject>;
|
|
20
27
|
declare function getAppRouteRenderEntryPath(route: AppRouteRenderEntry): string | null;
|
|
21
28
|
/**
|
|
22
29
|
* Returns true if the source code contains an export declaration with the given name.
|
|
@@ -28,12 +35,15 @@ declare function getAppRouteRenderEntryPath(route: AppRouteRenderEntry): string
|
|
|
28
35
|
* export { foo }
|
|
29
36
|
*/
|
|
30
37
|
declare function hasNamedExport(code: string, name: string): boolean;
|
|
38
|
+
/** Returns true when Next.js' analyzer recognizes the requested export name. */
|
|
39
|
+
declare function hasExportedName(code: string, name: string): boolean;
|
|
31
40
|
/**
|
|
32
41
|
* Extracts the string value of `export const <name> = "value"`.
|
|
33
42
|
* Handles TypeScript annotations/assertions and no-substitution template literals.
|
|
34
43
|
* Returns null if the export is absent or not a string literal.
|
|
35
44
|
*/
|
|
36
45
|
declare function extractExportConstString(code: string, name: string): string | null;
|
|
46
|
+
declare function extractMiddlewareMatcherConfig(filePath: string): StaticMiddlewareMatcher | undefined;
|
|
37
47
|
/**
|
|
38
48
|
* Extracts the numeric value of `export const <name> = <number|false>`.
|
|
39
49
|
* Supports integers, decimals, negative values, `Infinity`, and `false`.
|
|
@@ -121,7 +131,8 @@ declare function formatBuildReport(rows: RouteRow[], routerLabel?: string): stri
|
|
|
121
131
|
* Scans the project at `root`, classifies all routes, and prints the
|
|
122
132
|
* Next.js-style build report to stdout.
|
|
123
133
|
*
|
|
124
|
-
*
|
|
134
|
+
* `root` must be forward-slash — it is passed to `findDir`. The caller (the
|
|
135
|
+
* `vinext build` entry in cli.ts) normalizes it.
|
|
125
136
|
*/
|
|
126
137
|
declare function printBuildReport(options: {
|
|
127
138
|
root: string;
|
|
@@ -129,4 +140,4 @@ declare function printBuildReport(options: {
|
|
|
129
140
|
prerenderResult?: PrerenderResult;
|
|
130
141
|
}): Promise<void>;
|
|
131
142
|
//#endregion
|
|
132
|
-
export { RouteRow, RouteType, buildReportRows, classifyAppRoute, classifyLayoutSegmentConfig, classifyPagesRoute, extractExportConstNumber, extractExportConstString, extractGetStaticPropsRevalidate, formatBuildReport, getAppRouteRenderEntryPath, hasNamedExport, printBuildReport };
|
|
143
|
+
export { RouteRow, RouteType, StaticMiddlewareMatcher, buildReportRows, classifyAppRoute, classifyLayoutSegmentConfig, classifyPagesRoute, extractExportConstNumber, extractExportConstString, extractGetStaticPropsRevalidate, extractMiddlewareMatcherConfig, formatBuildReport, getAppRouteRenderEntryPath, hasExportedName, hasNamedExport, printBuildReport };
|
package/dist/build/report.js
CHANGED
|
@@ -22,6 +22,7 @@ import { parseSync } from "vite";
|
|
|
22
22
|
* `export const revalidate` are classified as "unknown" rather than "static"
|
|
23
23
|
* to avoid false confidence.
|
|
24
24
|
*/
|
|
25
|
+
const UNSUPPORTED_STATIC_VALUE = Symbol("unsupported static value");
|
|
25
26
|
function getAppRouteRenderEntryPath(route) {
|
|
26
27
|
if (route.pagePath) return route.pagePath;
|
|
27
28
|
if (route.routePath) return null;
|
|
@@ -72,6 +73,21 @@ function hasNamedExport(code, name) {
|
|
|
72
73
|
if (!program) return false;
|
|
73
74
|
return hasNamedExportInProgram(program, name);
|
|
74
75
|
}
|
|
76
|
+
/** Returns true when Next.js' analyzer recognizes the requested export name. */
|
|
77
|
+
function hasExportedName(code, name) {
|
|
78
|
+
const program = parseRouteModule(code);
|
|
79
|
+
if (!program) return false;
|
|
80
|
+
for (const node of program.body) {
|
|
81
|
+
if (node.type !== "ExportNamedDeclaration") continue;
|
|
82
|
+
if (node.exportKind === "type") continue;
|
|
83
|
+
if (declarationHasBindingName(node.declaration, name)) return true;
|
|
84
|
+
for (const specifier of node.specifiers) {
|
|
85
|
+
if (specifier.exportKind === "type") continue;
|
|
86
|
+
if (moduleExportNameValue(specifier.local) === name) return true;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
75
91
|
function hasNamedExportInProgram(program, name) {
|
|
76
92
|
for (const node of program.body) {
|
|
77
93
|
if (node.type !== "ExportNamedDeclaration") continue;
|
|
@@ -117,6 +133,86 @@ function extractStringFromConstInitializer(initializer) {
|
|
|
117
133
|
if (expression.type === "TemplateLiteral" && expression.expressions.length === 0) return expression.quasis[0]?.value.cooked ?? expression.quasis[0]?.value.raw ?? null;
|
|
118
134
|
return null;
|
|
119
135
|
}
|
|
136
|
+
function extractMiddlewareMatcherConfig(filePath) {
|
|
137
|
+
let code;
|
|
138
|
+
try {
|
|
139
|
+
code = fs.readFileSync(filePath, "utf8");
|
|
140
|
+
} catch {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const initializer = findExportedConstInitializer(code, "config");
|
|
144
|
+
if (!initializer) return void 0;
|
|
145
|
+
const config = unwrapStaticExpression(initializer);
|
|
146
|
+
if (config.type !== "ObjectExpression") return void 0;
|
|
147
|
+
const matcherExpression = objectPropertyValue(config, "matcher");
|
|
148
|
+
if (!matcherExpression) return void 0;
|
|
149
|
+
const value = extractStaticJsonValue(matcherExpression);
|
|
150
|
+
return isStaticMiddlewareMatcher(value) ? value : void 0;
|
|
151
|
+
}
|
|
152
|
+
function objectPropertyValue(object, key) {
|
|
153
|
+
for (const property of object.properties) {
|
|
154
|
+
if (property.type !== "Property" || property.computed) continue;
|
|
155
|
+
if (propertyKeyName(property.key) !== key) continue;
|
|
156
|
+
return property.value;
|
|
157
|
+
}
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
function propertyKeyName(key) {
|
|
161
|
+
if (key.type === "Identifier") return key.name;
|
|
162
|
+
if (key.type === "Literal" && typeof key.value === "string") return key.value;
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
function extractStaticJsonValue(expression) {
|
|
166
|
+
const value = unwrapStaticExpression(expression);
|
|
167
|
+
if (value.type === "Literal") {
|
|
168
|
+
if (typeof value.value === "string" || typeof value.value === "number" || typeof value.value === "boolean" || value.value === null) return value.value;
|
|
169
|
+
return UNSUPPORTED_STATIC_VALUE;
|
|
170
|
+
}
|
|
171
|
+
if (value.type === "TemplateLiteral" && value.expressions.length === 0) return value.quasis[0]?.value.cooked ?? value.quasis[0]?.value.raw ?? "";
|
|
172
|
+
if (value.type === "ArrayExpression") {
|
|
173
|
+
const items = [];
|
|
174
|
+
for (const element of value.elements) {
|
|
175
|
+
if (!element || element.type === "SpreadElement") return UNSUPPORTED_STATIC_VALUE;
|
|
176
|
+
const item = extractStaticJsonValue(element);
|
|
177
|
+
if (item === UNSUPPORTED_STATIC_VALUE) return UNSUPPORTED_STATIC_VALUE;
|
|
178
|
+
items.push(item);
|
|
179
|
+
}
|
|
180
|
+
return items;
|
|
181
|
+
}
|
|
182
|
+
if (value.type === "ObjectExpression") {
|
|
183
|
+
const object = {};
|
|
184
|
+
for (const property of value.properties) {
|
|
185
|
+
if (property.type !== "Property" || property.computed) return UNSUPPORTED_STATIC_VALUE;
|
|
186
|
+
const key = propertyKeyName(property.key);
|
|
187
|
+
if (!key) return UNSUPPORTED_STATIC_VALUE;
|
|
188
|
+
const propertyValue = extractStaticJsonValue(property.value);
|
|
189
|
+
if (propertyValue === UNSUPPORTED_STATIC_VALUE) return UNSUPPORTED_STATIC_VALUE;
|
|
190
|
+
object[key] = propertyValue;
|
|
191
|
+
}
|
|
192
|
+
return object;
|
|
193
|
+
}
|
|
194
|
+
return UNSUPPORTED_STATIC_VALUE;
|
|
195
|
+
}
|
|
196
|
+
function isStaticMiddlewareMatcher(value) {
|
|
197
|
+
if (typeof value === "string") return true;
|
|
198
|
+
if (!Array.isArray(value)) return false;
|
|
199
|
+
return value.every((item) => typeof item === "string" || isStaticMiddlewareMatcherObject(item));
|
|
200
|
+
}
|
|
201
|
+
function isStaticMiddlewareMatcherObject(value) {
|
|
202
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
203
|
+
const record = value;
|
|
204
|
+
if (typeof record.source !== "string") return false;
|
|
205
|
+
if (record.locale !== void 0 && record.locale !== false) return false;
|
|
206
|
+
return isStaticMatcherConditions(record.has) && isStaticMatcherConditions(record.missing);
|
|
207
|
+
}
|
|
208
|
+
function isStaticMatcherConditions(value) {
|
|
209
|
+
if (value === void 0) return true;
|
|
210
|
+
if (!Array.isArray(value)) return false;
|
|
211
|
+
return value.every((item) => {
|
|
212
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return false;
|
|
213
|
+
return Object.values(item).every((entry) => typeof entry === "string");
|
|
214
|
+
});
|
|
215
|
+
}
|
|
120
216
|
/**
|
|
121
217
|
* Extracts the numeric value of `export const <name> = <number|false>`.
|
|
122
218
|
* Supports integers, decimals, negative values, `Infinity`, and `false`.
|
|
@@ -474,7 +570,8 @@ function formatBuildReport(rows, routerLabel = "app") {
|
|
|
474
570
|
* Scans the project at `root`, classifies all routes, and prints the
|
|
475
571
|
* Next.js-style build report to stdout.
|
|
476
572
|
*
|
|
477
|
-
*
|
|
573
|
+
* `root` must be forward-slash — it is passed to `findDir`. The caller (the
|
|
574
|
+
* `vinext build` entry in cli.ts) normalizes it.
|
|
478
575
|
*/
|
|
479
576
|
async function printBuildReport(options) {
|
|
480
577
|
const { root } = options;
|
|
@@ -501,4 +598,4 @@ async function printBuildReport(options) {
|
|
|
501
598
|
}
|
|
502
599
|
}
|
|
503
600
|
//#endregion
|
|
504
|
-
export { buildReportRows, classifyAppRoute, classifyLayoutSegmentConfig, classifyPagesRoute, extractExportConstNumber, extractExportConstString, extractGetStaticPropsRevalidate, formatBuildReport, getAppRouteRenderEntryPath, hasNamedExport, printBuildReport };
|
|
601
|
+
export { buildReportRows, classifyAppRoute, classifyLayoutSegmentConfig, classifyPagesRoute, extractExportConstNumber, extractExportConstString, extractGetStaticPropsRevalidate, extractMiddlewareMatcherConfig, formatBuildReport, getAppRouteRenderEntryPath, hasExportedName, hasNamedExport, printBuildReport };
|
|
@@ -56,6 +56,13 @@ type RunPrerenderOptions = {
|
|
|
56
56
|
* `output: 'export'`. Exported for direct unit testing. Refs cloudflare/vinext#1982
|
|
57
57
|
*/
|
|
58
58
|
declare function assertNoFatalPrerenderRoutes(routes: readonly PrerenderRouteResult[]): void;
|
|
59
|
+
/**
|
|
60
|
+
* Statically generate routes and return the prerender result.
|
|
61
|
+
*
|
|
62
|
+
* `options.root` must be forward-slash — it is passed to `findDir` and flows
|
|
63
|
+
* into the route model. The caller (the `vinext build` entry in cli.ts)
|
|
64
|
+
* normalizes it.
|
|
65
|
+
*/
|
|
59
66
|
declare function runPrerender(options: RunPrerenderOptions): Promise<PrerenderResult | null>;
|
|
60
67
|
//#endregion
|
|
61
68
|
export { assertNoFatalPrerenderRoutes, runPrerender };
|
|
@@ -4,14 +4,15 @@ import { appRouter } from "../routing/app-router.js";
|
|
|
4
4
|
import { scanMetadataFiles } from "../server/metadata-routes.js";
|
|
5
5
|
import { loadNextConfig, resolveNextConfig } from "../config/next-config.js";
|
|
6
6
|
import { readPrerenderSecret } from "./server-manifest.js";
|
|
7
|
-
import { startProdServer } from "../server/prod-server.js";
|
|
7
|
+
import { rememberCurrentServerEntryImportMtime, startProdServer } from "../server/prod-server.js";
|
|
8
8
|
import { prerenderApp, prerenderPages, writePrerenderIndex } from "./prerender.js";
|
|
9
|
+
import { injectPregeneratedConcretePaths } from "./inject-pregenerated-paths.js";
|
|
9
10
|
import fs from "node:fs";
|
|
10
11
|
import path from "node:path";
|
|
11
12
|
//#region src/build/run-prerender.ts
|
|
12
13
|
/**
|
|
13
14
|
* Shared prerender runner used by both `vinext build` (cli.ts) and
|
|
14
|
-
* `vinext deploy --prerender-all` (deploy.ts).
|
|
15
|
+
* `vinext-cloudflare deploy --prerender-all` (deploy.ts).
|
|
15
16
|
*
|
|
16
17
|
* `runPrerender` handles route scanning, dynamic imports, progress reporting,
|
|
17
18
|
* and result summarisation.
|
|
@@ -95,6 +96,13 @@ function assertNoFatalPrerenderRoutes(routes) {
|
|
|
95
96
|
const fatalList = fatalRoutes.map((r) => ` ${r.route}: ${r.error}`).join("\n");
|
|
96
97
|
throw new Error(`Prerender failed: ${fatalRoutes.length} route${fatalRoutes.length !== 1 ? "s" : ""} errored during static generation.\n${fatalList}`);
|
|
97
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Statically generate routes and return the prerender result.
|
|
101
|
+
*
|
|
102
|
+
* `options.root` must be forward-slash — it is passed to `findDir` and flows
|
|
103
|
+
* into the route model. The caller (the `vinext build` entry in cli.ts)
|
|
104
|
+
* normalizes it.
|
|
105
|
+
*/
|
|
98
106
|
async function runPrerender(options) {
|
|
99
107
|
const { root } = options;
|
|
100
108
|
const appDir = findDir(root, "app", "src/app");
|
|
@@ -215,6 +223,8 @@ async function runPrerender(options) {
|
|
|
215
223
|
const errorRoutes = allRoutes.filter((r) => r.status === "error").map((r) => ` ${r.route}: ${r.error}`).join("\n");
|
|
216
224
|
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.`);
|
|
217
225
|
}
|
|
226
|
+
injectPregeneratedConcretePaths(root);
|
|
227
|
+
if (fs.existsSync(rscBundlePath)) rememberCurrentServerEntryImportMtime(rscBundlePath);
|
|
218
228
|
return {
|
|
219
229
|
routes: allRoutes,
|
|
220
230
|
...allOutputFiles.length > 0 ? { outputFiles: allOutputFiles } : {}
|
package/dist/build/standalone.js
CHANGED
|
@@ -167,6 +167,8 @@ function emitStandaloneOutput(options) {
|
|
|
167
167
|
dereference: true,
|
|
168
168
|
filter: (src) => !path.relative(serverDir, src).split(path.sep).includes("node_modules")
|
|
169
169
|
});
|
|
170
|
+
const clientAssetsSidecar = path.join(outDir, "vinext-client-assets.js");
|
|
171
|
+
if (fs.existsSync(clientAssetsSidecar)) fs.copyFileSync(clientAssetsSidecar, path.join(standaloneDistDir, "vinext-client-assets.js"));
|
|
170
172
|
const publicDir = path.join(root, "public");
|
|
171
173
|
if (fs.existsSync(publicDir)) fs.cpSync(publicDir, path.join(standaloneDir, "public"), {
|
|
172
174
|
recursive: true,
|
|
@@ -35,9 +35,9 @@ function generateCacheAdaptersModule(cache) {
|
|
|
35
35
|
lines.push(`import __vinextCdnAdapterFactory from ${JSON.stringify(cdn.adapter)};`);
|
|
36
36
|
lines.push(`import { setCdnCacheAdapter } from "vinext/shims/cdn-cache";`);
|
|
37
37
|
}
|
|
38
|
-
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.", "let __vinextCacheAdaptersRegistered = false;", "", "export function registerConfiguredCacheAdapters(env) {", " if (__vinextCacheAdaptersRegistered) return;", " __vinextCacheAdaptersRegistered = true;");
|
|
39
|
-
if (data?.adapter) lines.push(" try {", ` setDataCacheHandler(__vinextDataAdapterFactory({ env, options: ${inlineOptions(data.adapter, data.options)} }));`, " } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured data cache adapter; using the default handler
|
|
40
|
-
if (cdn?.adapter) lines.push(" try {", ` setCdnCacheAdapter(__vinextCdnAdapterFactory({ env, options: ${inlineOptions(cdn.adapter, cdn.options)} }));`, " } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured CDN cache adapter; using the default adapter
|
|
38
|
+
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 (__vinextCacheAdaptersRegistered) return;", " __vinextCacheAdaptersRegistered = true;");
|
|
39
|
+
if (data?.adapter) lines.push(" try {", ` setDataCacheHandler(__vinextDataAdapterFactory({ env, options: ${inlineOptions(data.adapter, data.options)} }));`, " } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured data cache adapter; using the default handler.\\n\" + __vinextFormatAdapterError(error));", " }");
|
|
40
|
+
if (cdn?.adapter) lines.push(" try {", ` setCdnCacheAdapter(__vinextCdnAdapterFactory({ env, options: ${inlineOptions(cdn.adapter, cdn.options)} }));`, " } catch (error) {", " console.warn(\"[vinext] failed to initialize the configured CDN cache adapter; using the default adapter.\\n\" + __vinextFormatAdapterError(error));", " }");
|
|
41
41
|
lines.push("}", "");
|
|
42
42
|
return lines.join("\n");
|
|
43
43
|
}
|
package/dist/check.d.ts
CHANGED
|
@@ -60,9 +60,8 @@ declare function hasFreeCjsGlobal(content: string): boolean;
|
|
|
60
60
|
/**
|
|
61
61
|
* Scan source files for `import ... from 'next/...'` statements.
|
|
62
62
|
*
|
|
63
|
-
* `root` must be forward-slash: it is passed to `findSourceFiles
|
|
64
|
-
* requires it
|
|
65
|
-
* a canonical relative path when both operands are forward-slash.
|
|
63
|
+
* `root` must be forward-slash: it is passed to `findSourceFiles`, which
|
|
64
|
+
* requires it.
|
|
66
65
|
*/
|
|
67
66
|
declare function scanImports(root: string): CheckItem[];
|
|
68
67
|
/**
|
|
@@ -82,9 +81,8 @@ declare function checkLibraries(root: string): CheckItem[];
|
|
|
82
81
|
/**
|
|
83
82
|
* Check file conventions (pages, app directory, middleware, etc.)
|
|
84
83
|
*
|
|
85
|
-
* `root` must be forward-slash — joined with `path.posix.join
|
|
86
|
-
* `findDir
|
|
87
|
-
* `runCheck`, which normalizes it.
|
|
84
|
+
* `root` must be forward-slash — joined with `path.posix.join` and passed to
|
|
85
|
+
* `findDir`. Only called from `runCheck`, which normalizes it.
|
|
88
86
|
*/
|
|
89
87
|
declare function checkConventions(root: string): CheckItem[];
|
|
90
88
|
/**
|