vinext 0.2.0 → 1.0.0-beta.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 +50 -29
- package/dist/build/client-build-config.d.ts +13 -92
- package/dist/build/client-build-config.js +17 -95
- 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 +3 -0
- package/dist/build/inject-pregenerated-paths.js +4 -1
- package/dist/build/prerender-paths.d.ts +23 -0
- package/dist/build/prerender-paths.js +296 -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 +12 -1
- package/dist/build/prerender.js +87 -23
- package/dist/build/run-prerender.js +2 -1
- package/dist/cache/cache-adapters-virtual.d.ts +7 -1
- package/dist/cache/cache-adapters-virtual.js +26 -2
- package/dist/check.d.ts +4 -6
- package/dist/check.js +13 -9
- package/dist/cli.js +34 -54
- package/dist/client/vinext-next-data.d.ts +4 -1
- package/dist/config/config-matchers.js +33 -11
- package/dist/config/next-config.d.ts +36 -6
- package/dist/config/next-config.js +17 -4
- package/dist/config/prerender.d.ts +11 -1
- package/dist/config/prerender.js +19 -1
- package/dist/config/tsconfig-paths.js +5 -1
- package/dist/entries/app-browser-entry.js +5 -1
- package/dist/entries/app-rsc-entry.d.ts +3 -2
- package/dist/entries/app-rsc-entry.js +4 -0
- package/dist/entries/pages-client-entry.js +14 -3
- package/dist/entries/pages-server-entry.js +18 -4
- package/dist/image/image-adapters-virtual.js +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +549 -152
- package/dist/init-cloudflare.js +12 -3
- package/dist/init-platform.d.ts +10 -1
- package/dist/init-platform.js +78 -12
- package/dist/init.d.ts +11 -3
- package/dist/init.js +129 -31
- package/dist/plugins/fonts.js +1 -1
- package/dist/plugins/ignore-dynamic-requests.js +1 -1
- 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/routing/app-route-graph.js +22 -16
- package/dist/routing/file-matcher.d.ts +8 -1
- package/dist/routing/file-matcher.js +15 -3
- package/dist/server/app-browser-entry.js +44 -14
- package/dist/server/app-browser-navigation-controller.js +5 -2
- package/dist/server/app-browser-server-action-client.js +5 -3
- package/dist/server/app-browser-state.d.ts +1 -0
- package/dist/server/app-browser-state.js +1 -1
- package/dist/server/app-layout-param-observation.d.ts +1 -1
- 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 +3 -3
- package/dist/server/app-page-cache-render.d.ts +1 -1
- package/dist/server/app-page-cache.js +23 -6
- package/dist/server/app-page-dispatch.d.ts +2 -1
- package/dist/server/app-page-dispatch.js +27 -10
- package/dist/server/app-page-element-builder.js +1 -0
- package/dist/server/app-page-execution.js +2 -1
- package/dist/server/app-page-render-identity.d.ts +1 -0
- package/dist/server/app-page-render-identity.js +2 -1
- package/dist/server/app-page-render.d.ts +3 -1
- package/dist/server/app-page-render.js +67 -16
- 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.js +3 -3
- package/dist/server/app-page-stream.d.ts +2 -1
- package/dist/server/app-page-stream.js +1 -1
- package/dist/server/app-route-handler-execution.d.ts +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 +1 -1
- package/dist/server/app-rsc-cache-busting.d.ts +2 -1
- package/dist/server/app-rsc-cache-busting.js +9 -5
- package/dist/server/app-rsc-handler.d.ts +6 -0
- package/dist/server/app-rsc-handler.js +88 -10
- package/dist/server/app-rsc-render-mode.d.ts +3 -5
- package/dist/server/app-rsc-render-mode.js +5 -12
- package/dist/server/app-rsc-request-normalization.d.ts +3 -4
- package/dist/server/app-rsc-request-normalization.js +4 -5
- package/dist/server/app-server-action-execution.js +6 -5
- package/dist/server/app-ssr-entry.js +1 -1
- package/dist/server/cache-control.d.ts +3 -1
- package/dist/server/cache-control.js +13 -1
- package/dist/server/dev-module-runner.js +1 -1
- package/dist/server/dev-origin-check.d.ts +2 -2
- package/dist/server/dev-origin-check.js +2 -2
- package/dist/server/dev-server.d.ts +11 -1
- package/dist/server/dev-server.js +82 -24
- package/dist/server/headers.d.ts +6 -2
- package/dist/server/headers.js +11 -5
- package/dist/server/image-optimization.d.ts +12 -1
- package/dist/server/image-optimization.js +13 -1
- package/dist/server/isr-cache.d.ts +13 -4
- package/dist/server/isr-cache.js +8 -4
- 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 +12 -1
- package/dist/server/pages-node-compat.js +50 -1
- package/dist/server/pages-page-data.d.ts +9 -0
- package/dist/server/pages-page-data.js +18 -10
- package/dist/server/pages-page-handler.js +19 -7
- package/dist/server/pages-page-response.d.ts +1 -0
- package/dist/server/pages-page-response.js +5 -4
- package/dist/server/pages-request-pipeline.d.ts +8 -6
- package/dist/server/pages-request-pipeline.js +31 -7
- package/dist/server/pages-router-entry.js +1 -1
- package/dist/server/prerender-manifest.d.ts +15 -1
- package/dist/server/prerender-manifest.js +29 -1
- package/dist/server/prod-server.d.ts +10 -7
- package/dist/server/prod-server.js +43 -28
- package/dist/server/request-pipeline.js +1 -1
- package/dist/server/static-file-cache.js +1 -1
- package/dist/shims/cache-handler.js +8 -1
- package/dist/shims/cache.d.ts +1 -1
- package/dist/shims/cache.js +3 -0
- package/dist/shims/cdn-cache.d.ts +2 -7
- package/dist/shims/cdn-cache.js +2 -14
- package/dist/shims/fetch-cache.d.ts +3 -1
- package/dist/shims/fetch-cache.js +77 -52
- 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/hybrid-client-route-owner.d.ts +2 -1
- package/dist/shims/internal/hybrid-client-route-owner.js +34 -1
- package/dist/shims/internal/pages-data-fetch-dedup.d.ts +2 -1
- package/dist/shims/internal/pages-data-fetch-dedup.js +13 -2
- package/dist/shims/internal/pages-data-target.d.ts +8 -3
- package/dist/shims/internal/pages-data-target.js +9 -4
- package/dist/shims/link.d.ts +1 -1
- package/dist/shims/link.js +179 -42
- package/dist/shims/navigation.d.ts +15 -3
- package/dist/shims/navigation.js +202 -39
- package/dist/shims/request-context.js +18 -0
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/router.js +31 -15
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/dist/shims/unified-request-context.js +1 -0
- package/dist/typegen.js +1 -1
- package/dist/utils/middleware-request-headers.js +1 -1
- package/dist/utils/project.d.ts +1 -1
- package/dist/utils/protocol-headers.d.ts +7 -1
- package/dist/utils/protocol-headers.js +7 -1
- package/dist/utils/vite-version.d.ts +4 -12
- package/dist/utils/vite-version.js +39 -21
- package/package.json +31 -13
- package/dist/cloudflare/index.d.ts +0 -3
- package/dist/cloudflare/index.js +0 -3
- package/dist/packages/cloudflare/src/cache/cdn-adapter.runtime.js +0 -102
- package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.d.ts +0 -126
- package/dist/packages/cloudflare/src/cache/kv-data-adapter.runtime.js +0 -435
- package/dist/packages/cloudflare/src/deploy-config.js +0 -150
- package/dist/packages/cloudflare/src/deploy-help.js +0 -55
- package/dist/packages/cloudflare/src/deploy.js +0 -276
- package/dist/packages/cloudflare/src/tpr.d.ts +0 -45
- package/dist/packages/cloudflare/src/tpr.js +0 -561
- package/dist/packages/cloudflare/src/utils/cache-control-metadata.js +0 -20
package/dist/build/prerender.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createValidFileMatcher, findFileWithExtensions } from "../routing/file-matcher.js";
|
|
2
|
-
import { VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, VINEXT_PRERENDER_SECRET_HEADER } from "../utils/protocol-headers.js";
|
|
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";
|
|
3
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";
|
|
@@ -14,6 +15,7 @@ import { readPrerenderSecret } from "./server-manifest.js";
|
|
|
14
15
|
import { createAppPprFallbackShells, markAppPprDynamicFallbackShellHtml } from "../server/app-ppr-fallback-shell.js";
|
|
15
16
|
import { getOutputPath, getRscOutputPath } from "../utils/prerender-output-paths.js";
|
|
16
17
|
import { startProdServer } from "../server/prod-server.js";
|
|
18
|
+
import { prerenderPoolAvailable, resolvePrerenderPoolSize, startPrerenderServerPool } from "./prerender-server-pool.js";
|
|
17
19
|
import fs from "node:fs";
|
|
18
20
|
import path from "node:path";
|
|
19
21
|
import os from "node:os";
|
|
@@ -42,6 +44,14 @@ function isExperimentalPprFallbackShellGenerationEnabled(env = process.env) {
|
|
|
42
44
|
function getErrorMessageWithStack(err) {
|
|
43
45
|
return err.stack || err.message;
|
|
44
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
|
+
}
|
|
45
55
|
var PrerenderUserFunctionError = class extends Error {};
|
|
46
56
|
function parsePrerenderEndpointError(text) {
|
|
47
57
|
try {
|
|
@@ -257,11 +267,12 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
257
267
|
const previousPrerenderFlag = process.env.VINEXT_PRERENDER;
|
|
258
268
|
process.env.VINEXT_PRERENDER = "1";
|
|
259
269
|
let ownedProdServerHandle = null;
|
|
270
|
+
let renderPool = null;
|
|
260
271
|
try {
|
|
261
272
|
let prerenderSecret = options._prerenderSecret;
|
|
262
273
|
if (!prerenderSecret && pagesBundlePath) prerenderSecret = readPrerenderSecret(path.dirname(pagesBundlePath));
|
|
263
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.");
|
|
264
|
-
const
|
|
275
|
+
const prodServer = options._prodServer ? options._prodServer : await (async () => {
|
|
265
276
|
const srv = await startProdServer({
|
|
266
277
|
port: 0,
|
|
267
278
|
host: "127.0.0.1",
|
|
@@ -271,12 +282,18 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
271
282
|
});
|
|
272
283
|
ownedProdServerHandle = srv;
|
|
273
284
|
return srv;
|
|
274
|
-
})()
|
|
285
|
+
})();
|
|
286
|
+
const baseUrl = `http://127.0.0.1:${prodServer.port}`;
|
|
275
287
|
const secretHeaders = prerenderSecret ? { [VINEXT_PRERENDER_SECRET_HEADER]: prerenderSecret } : {};
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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
|
+
};
|
|
280
297
|
const bundlePageRoutes = routes.map((r) => ({
|
|
281
298
|
pattern: r.pattern,
|
|
282
299
|
isDynamic: r.isDynamic ?? false,
|
|
@@ -397,6 +414,13 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
397
414
|
revalidate
|
|
398
415
|
});
|
|
399
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
|
+
}
|
|
400
424
|
let completed = 0;
|
|
401
425
|
const pageResults = await runWithConcurrency(pagesToRender, concurrency, async ({ route, urlPath, revalidate }) => {
|
|
402
426
|
let result;
|
|
@@ -427,6 +451,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
427
451
|
...urlPath !== route.pattern ? { path: urlPath } : {}
|
|
428
452
|
};
|
|
429
453
|
} catch (e) {
|
|
454
|
+
renderPool?.recordRenderError(e);
|
|
430
455
|
const err = e;
|
|
431
456
|
result = {
|
|
432
457
|
route: route.pattern,
|
|
@@ -443,6 +468,7 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
443
468
|
return result;
|
|
444
469
|
});
|
|
445
470
|
results.push(...pageResults);
|
|
471
|
+
renderPool?.assertHealthy();
|
|
446
472
|
const hasCustom404 = findFileWithExtensions(path.join(pagesDir, "404"), fileMatcher);
|
|
447
473
|
const hasErrorPage = findFileWithExtensions(path.join(pagesDir, "_error"), fileMatcher);
|
|
448
474
|
if (hasCustom404 || hasErrorPage) try {
|
|
@@ -460,13 +486,17 @@ async function prerenderPages({ routes, apiRoutes, pagesDir, outDir, config, mod
|
|
|
460
486
|
router: "pages"
|
|
461
487
|
});
|
|
462
488
|
}
|
|
463
|
-
} catch {
|
|
489
|
+
} catch (e) {
|
|
490
|
+
renderPool?.recordRenderError(e);
|
|
491
|
+
}
|
|
492
|
+
renderPool?.assertHealthy();
|
|
464
493
|
if (!skipManifest) writePrerenderIndex(results, manifestDir, {
|
|
465
494
|
buildId: config.buildId,
|
|
466
495
|
trailingSlash: config.trailingSlash
|
|
467
496
|
});
|
|
468
497
|
return { routes: results };
|
|
469
498
|
} finally {
|
|
499
|
+
if (renderPool) await renderPool.close();
|
|
470
500
|
setCacheHandler(previousHandler);
|
|
471
501
|
if (previousPrerenderFlag === void 0) delete process.env.VINEXT_PRERENDER;
|
|
472
502
|
else process.env.VINEXT_PRERENDER = previousPrerenderFlag;
|
|
@@ -505,10 +535,13 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
505
535
|
let rscHandler;
|
|
506
536
|
let staticParamsMap = {};
|
|
507
537
|
let ownedProdServerHandle = null;
|
|
538
|
+
let renderPool = null;
|
|
539
|
+
let renderPorts = [];
|
|
540
|
+
let renderRoundRobin = 0;
|
|
508
541
|
try {
|
|
509
542
|
const prerenderSecret = readPrerenderSecret(serverDir);
|
|
510
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.");
|
|
511
|
-
const
|
|
544
|
+
const prodServer = options._prodServer ? options._prodServer : await (async () => {
|
|
512
545
|
const srv = await startProdServer({
|
|
513
546
|
port: 0,
|
|
514
547
|
host: "127.0.0.1",
|
|
@@ -518,11 +551,13 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
518
551
|
});
|
|
519
552
|
ownedProdServerHandle = srv;
|
|
520
553
|
return srv;
|
|
521
|
-
})()
|
|
554
|
+
})();
|
|
555
|
+
const baseUrl = `http://127.0.0.1:${prodServer.port}`;
|
|
556
|
+
renderPorts = [prodServer.port];
|
|
522
557
|
const secretHeaders = prerenderSecret ? { [VINEXT_PRERENDER_SECRET_HEADER]: prerenderSecret } : {};
|
|
523
558
|
rscHandler = (req) => {
|
|
524
559
|
const parsed = new URL(req.url);
|
|
525
|
-
const url =
|
|
560
|
+
const url = `http://127.0.0.1:${renderPorts[renderRoundRobin++ % renderPorts.length]}${parsed.pathname}${parsed.search}`;
|
|
526
561
|
return fetch(url, {
|
|
527
562
|
method: req.method,
|
|
528
563
|
headers: {
|
|
@@ -718,12 +753,14 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
718
753
|
const prerenderRouteParamsHeader = serializePrerenderRouteParamsHeader(prerenderRouteParams);
|
|
719
754
|
const htmlHeaders = new Headers();
|
|
720
755
|
if (prerenderRouteParamsHeader !== null) htmlHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
756
|
+
if (isSpeculative) htmlHeaders.set(VINEXT_PRERENDER_SPECULATIVE_HEADER, "1");
|
|
721
757
|
const htmlRequest = new Request(`http://localhost${urlPath}`, { headers: htmlHeaders });
|
|
722
758
|
const htmlRender = await runWithHeadersContext(headersContextFromRequest(htmlRequest), async () => {
|
|
723
759
|
const response = await rscHandler(htmlRequest);
|
|
724
760
|
const cacheControl = response.headers.get("cache-control") ?? "";
|
|
725
761
|
const linkHeader = response.headers.get("link");
|
|
726
|
-
|
|
762
|
+
const responseCacheLife = readPrerenderCacheLifeHeader(response.headers);
|
|
763
|
+
if (!response.ok || cacheControl.includes("no-store")) {
|
|
727
764
|
await response.body?.cancel();
|
|
728
765
|
return {
|
|
729
766
|
cacheControl,
|
|
@@ -734,12 +771,14 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
734
771
|
status: response.status
|
|
735
772
|
};
|
|
736
773
|
}
|
|
774
|
+
const html = await response.text();
|
|
775
|
+
const processCacheLife = _consumeRequestScopedCacheLife();
|
|
737
776
|
return {
|
|
738
777
|
cacheControl,
|
|
739
778
|
linkHeader,
|
|
740
|
-
html
|
|
779
|
+
html,
|
|
741
780
|
ok: true,
|
|
742
|
-
requestCacheLife:
|
|
781
|
+
requestCacheLife: responseCacheLife ?? processCacheLife,
|
|
743
782
|
status: response.status
|
|
744
783
|
};
|
|
745
784
|
});
|
|
@@ -756,13 +795,11 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
756
795
|
error: `RSC handler returned ${htmlRender.status}`
|
|
757
796
|
};
|
|
758
797
|
}
|
|
759
|
-
if (
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
};
|
|
765
|
-
}
|
|
798
|
+
if (htmlCacheControl.includes("no-store")) return {
|
|
799
|
+
route: routePattern,
|
|
800
|
+
status: "skipped",
|
|
801
|
+
reason: "dynamic"
|
|
802
|
+
};
|
|
766
803
|
if (htmlRender.html === null) return {
|
|
767
804
|
route: routePattern,
|
|
768
805
|
status: "error",
|
|
@@ -776,6 +813,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
776
813
|
RSC: "1"
|
|
777
814
|
});
|
|
778
815
|
if (prerenderRouteParamsHeader !== null) rscHeaders.set(VINEXT_PRERENDER_ROUTE_PARAMS_HEADER, prerenderRouteParamsHeader);
|
|
816
|
+
if (isSpeculative) rscHeaders.set(VINEXT_PRERENDER_SPECULATIVE_HEADER, "1");
|
|
779
817
|
const rscRequest = new Request(`http://localhost${urlPath}`, { headers: rscHeaders });
|
|
780
818
|
const rscRes = await runWithHeadersContext(headersContextFromRequest(rscRequest), () => rscHandler(rscRequest));
|
|
781
819
|
if (!rscRes.ok) {
|
|
@@ -809,6 +847,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
809
847
|
...isFallback ? { fallback: true } : {}
|
|
810
848
|
};
|
|
811
849
|
} catch (e) {
|
|
850
|
+
renderPool?.recordRenderError(e);
|
|
812
851
|
if (isSpeculative) return {
|
|
813
852
|
route: routePattern,
|
|
814
853
|
status: "skipped",
|
|
@@ -823,6 +862,13 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
823
862
|
};
|
|
824
863
|
}
|
|
825
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
|
+
}
|
|
826
872
|
let completedApp = 0;
|
|
827
873
|
const appResults = await runWithConcurrency(urlsToRender, concurrency, async (urlToRender) => {
|
|
828
874
|
const result = await renderUrl(urlToRender);
|
|
@@ -835,6 +881,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
835
881
|
return result;
|
|
836
882
|
});
|
|
837
883
|
results.push(...appResults);
|
|
884
|
+
renderPool?.assertHealthy();
|
|
838
885
|
const outputFiles = mode === "export" && metadataRoutes.length > 0 ? emitStaticMetadataFiles(metadataRoutes, outDir) : [];
|
|
839
886
|
try {
|
|
840
887
|
const notFoundRequest = new Request(`http://localhost${NOT_FOUND_SENTINEL_PATH}`);
|
|
@@ -852,7 +899,10 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
852
899
|
router: "app"
|
|
853
900
|
});
|
|
854
901
|
}
|
|
855
|
-
} catch {
|
|
902
|
+
} catch (e) {
|
|
903
|
+
renderPool?.recordRenderError(e);
|
|
904
|
+
}
|
|
905
|
+
renderPool?.assertHealthy();
|
|
856
906
|
if (!skipManifest) writePrerenderIndex(results, manifestDir, {
|
|
857
907
|
buildId: config.buildId,
|
|
858
908
|
trailingSlash: config.trailingSlash
|
|
@@ -862,6 +912,7 @@ async function prerenderApp({ routes, metadataRoutes = [], outDir, config, mode,
|
|
|
862
912
|
...outputFiles.length > 0 ? { outputFiles } : {}
|
|
863
913
|
};
|
|
864
914
|
} finally {
|
|
915
|
+
if (renderPool) await renderPool.close();
|
|
865
916
|
setCacheHandler(previousHandler);
|
|
866
917
|
if (previousPrerenderFlag === void 0) delete process.env.VINEXT_PRERENDER;
|
|
867
918
|
else process.env.VINEXT_PRERENDER = previousPrerenderFlag;
|
|
@@ -881,6 +932,19 @@ function resolveRenderedCacheControl(requestCacheLife, cacheControl, fallbackExp
|
|
|
881
932
|
...revalidate === void 0 ? {} : { revalidate }
|
|
882
933
|
};
|
|
883
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
|
+
}
|
|
884
948
|
function resolveRenderedExpireSeconds(options) {
|
|
885
949
|
const { fallbackExpireSeconds, sMaxage, staleWhileRevalidate } = options;
|
|
886
950
|
if (sMaxage === void 0 || staleWhileRevalidate === void 0) return fallbackExpireSeconds;
|
|
@@ -936,4 +1000,4 @@ function writePrerenderIndex(routes, outDir, options) {
|
|
|
936
1000
|
fs.writeFileSync(path.join(outDir, "vinext-prerender.json"), JSON.stringify(index, null, 2), "utf-8");
|
|
937
1001
|
}
|
|
938
1002
|
//#endregion
|
|
939
|
-
export { extractRscPayloadFromPrerenderedHtml, prerenderApp, prerenderPages, readPrerenderSecret, resolveParentParams, writePrerenderIndex };
|
|
1003
|
+
export { buildUrlFromParams, extractRscPayloadFromPrerenderedHtml, prerenderApp, prerenderPages, readPrerenderSecret, resolveParentParams, writePrerenderIndex };
|
|
@@ -4,7 +4,7 @@ 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
9
|
import { injectPregeneratedConcretePaths } from "./inject-pregenerated-paths.js";
|
|
10
10
|
import fs from "node:fs";
|
|
@@ -224,6 +224,7 @@ async function runPrerender(options) {
|
|
|
224
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.`);
|
|
225
225
|
}
|
|
226
226
|
injectPregeneratedConcretePaths(root);
|
|
227
|
+
if (fs.existsSync(rscBundlePath)) rememberCurrentServerEntryImportMtime(rscBundlePath);
|
|
227
228
|
return {
|
|
228
229
|
routes: allRoutes,
|
|
229
230
|
...allOutputFiles.length > 0 ? { outputFiles: allOutputFiles } : {}
|
|
@@ -41,10 +41,16 @@ type VinextCacheConfig = {
|
|
|
41
41
|
};
|
|
42
42
|
/** Public virtual module id imported by the server entries. */
|
|
43
43
|
declare const VIRTUAL_CACHE_ADAPTERS = "virtual:vinext-cache-adapters";
|
|
44
|
+
declare const VINEXT_CACHE_CONFIG_PLUGIN_PROPERTY = "__vinextCacheConfig";
|
|
45
|
+
type ViteConfigLoader = {
|
|
46
|
+
loadConfigFromFile: typeof import("vite").loadConfigFromFile;
|
|
47
|
+
};
|
|
48
|
+
declare function findVinextCacheConfigInPlugins(plugins: import("vite").PluginOption[] | undefined): VinextCacheConfig | null;
|
|
49
|
+
declare function loadVinextCacheConfigFromViteConfig(vite: ViteConfigLoader, root: string): Promise<VinextCacheConfig | null>;
|
|
44
50
|
/**
|
|
45
51
|
* Generate the source of the `virtual:vinext-cache-adapters` module for the
|
|
46
52
|
* given config. Always exports `registerConfiguredCacheAdapters(env)`.
|
|
47
53
|
*/
|
|
48
54
|
declare function generateCacheAdaptersModule(cache?: VinextCacheConfig): string;
|
|
49
55
|
//#endregion
|
|
50
|
-
export { VIRTUAL_CACHE_ADAPTERS, VinextCacheConfig, generateCacheAdaptersModule };
|
|
56
|
+
export { VINEXT_CACHE_CONFIG_PLUGIN_PROPERTY, VIRTUAL_CACHE_ADAPTERS, VinextCacheConfig, findVinextCacheConfigInPlugins, generateCacheAdaptersModule, loadVinextCacheConfigFromViteConfig };
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
//#region src/cache/cache-adapters-virtual.ts
|
|
2
2
|
/** Public virtual module id imported by the server entries. */
|
|
3
3
|
const VIRTUAL_CACHE_ADAPTERS = "virtual:vinext-cache-adapters";
|
|
4
|
+
const VINEXT_CACHE_CONFIG_PLUGIN_PROPERTY = "__vinextCacheConfig";
|
|
5
|
+
function flattenPluginOptions(value, target) {
|
|
6
|
+
if (Array.isArray(value)) {
|
|
7
|
+
for (const item of value) flattenPluginOptions(item, target);
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (value) target.push(value);
|
|
11
|
+
}
|
|
12
|
+
function findVinextCacheConfigInPlugins(plugins) {
|
|
13
|
+
const flattened = [];
|
|
14
|
+
flattenPluginOptions(plugins, flattened);
|
|
15
|
+
for (const plugin of flattened) {
|
|
16
|
+
if (!plugin || typeof plugin !== "object") continue;
|
|
17
|
+
const cacheConfig = plugin[VINEXT_CACHE_CONFIG_PLUGIN_PROPERTY];
|
|
18
|
+
if (cacheConfig) return cacheConfig;
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
async function loadVinextCacheConfigFromViteConfig(vite, root) {
|
|
23
|
+
return findVinextCacheConfigInPlugins((await vite.loadConfigFromFile({
|
|
24
|
+
command: "build",
|
|
25
|
+
mode: "production"
|
|
26
|
+
}, void 0, root))?.config.plugins);
|
|
27
|
+
}
|
|
4
28
|
/**
|
|
5
29
|
* Serialize descriptor options into a JS expression for inlining. Plain JSON is
|
|
6
30
|
* a valid JS literal; `undefined` when there are no options. Throws a clear
|
|
@@ -35,11 +59,11 @@ function generateCacheAdaptersModule(cache) {
|
|
|
35
59
|
lines.push(`import __vinextCdnAdapterFactory from ${JSON.stringify(cdn.adapter)};`);
|
|
36
60
|
lines.push(`import { setCdnCacheAdapter } from "vinext/shims/cdn-cache";`);
|
|
37
61
|
}
|
|
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;");
|
|
62
|
+
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;");
|
|
39
63
|
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
64
|
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
65
|
lines.push("}", "");
|
|
42
66
|
return lines.join("\n");
|
|
43
67
|
}
|
|
44
68
|
//#endregion
|
|
45
|
-
export { VIRTUAL_CACHE_ADAPTERS, generateCacheAdaptersModule };
|
|
69
|
+
export { VINEXT_CACHE_CONFIG_PLUGIN_PROPERTY, VIRTUAL_CACHE_ADAPTERS, findVinextCacheConfigInPlugins, generateCacheAdaptersModule, loadVinextCacheConfigFromViteConfig };
|
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
|
/**
|
package/dist/check.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { detectPackageManager, findDir } from "./utils/project.js";
|
|
2
|
+
import { normalizePathSeparators } from "./utils/path.js";
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
import path from "node:path";
|
|
4
5
|
import { parseAst } from "vite";
|
|
@@ -214,6 +215,10 @@ const CONFIG_SUPPORT = {
|
|
|
214
215
|
status: "supported",
|
|
215
216
|
detail: "sourcemap-resolved stack traces during prerender"
|
|
216
217
|
},
|
|
218
|
+
cacheComponents: {
|
|
219
|
+
status: "partial",
|
|
220
|
+
detail: "experimental support; behavior is incomplete"
|
|
221
|
+
},
|
|
217
222
|
"experimental.ppr": {
|
|
218
223
|
status: "unsupported",
|
|
219
224
|
detail: "partial prerendering not yet implemented"
|
|
@@ -300,7 +305,7 @@ const CONFIG_SUPPORT = {
|
|
|
300
305
|
},
|
|
301
306
|
reactStrictMode: {
|
|
302
307
|
status: "partial",
|
|
303
|
-
detail: "
|
|
308
|
+
detail: "enforced for the Pages Router (client root wrapped in <React.StrictMode> when true); App Router is not yet wrapped (Next.js defaults App Router strict mode on)"
|
|
304
309
|
},
|
|
305
310
|
poweredByHeader: {
|
|
306
311
|
status: "supported",
|
|
@@ -588,9 +593,8 @@ function hasFreeCjsGlobal(content) {
|
|
|
588
593
|
/**
|
|
589
594
|
* Scan source files for `import ... from 'next/...'` statements.
|
|
590
595
|
*
|
|
591
|
-
* `root` must be forward-slash: it is passed to `findSourceFiles
|
|
592
|
-
* requires it
|
|
593
|
-
* a canonical relative path when both operands are forward-slash.
|
|
596
|
+
* `root` must be forward-slash: it is passed to `findSourceFiles`, which
|
|
597
|
+
* requires it.
|
|
594
598
|
*/
|
|
595
599
|
function scanImports(root) {
|
|
596
600
|
const files = findSourceFiles(root);
|
|
@@ -608,7 +612,7 @@ function scanImports(root) {
|
|
|
608
612
|
if (mod.startsWith("next/") || mod === "next" || mod === "server-only" || mod === "client-only") {
|
|
609
613
|
const normalized = mod === "next" ? "next" : mod;
|
|
610
614
|
if (!importUsage.has(normalized)) importUsage.set(normalized, []);
|
|
611
|
-
const relFile = path.
|
|
615
|
+
const relFile = normalizePathSeparators(path.relative(root, file));
|
|
612
616
|
const usedInFiles = importUsage.get(normalized) ?? [];
|
|
613
617
|
if (!usedInFiles.includes(relFile)) usedInFiles.push(relFile);
|
|
614
618
|
}
|
|
@@ -775,6 +779,7 @@ function analyzeConfig(root) {
|
|
|
775
779
|
"output",
|
|
776
780
|
"transpilePackages",
|
|
777
781
|
"webpack",
|
|
782
|
+
"cacheComponents",
|
|
778
783
|
"reactStrictMode",
|
|
779
784
|
"poweredByHeader",
|
|
780
785
|
"skipMiddlewareUrlNormalize",
|
|
@@ -830,9 +835,8 @@ function checkLibraries(root) {
|
|
|
830
835
|
/**
|
|
831
836
|
* Check file conventions (pages, app directory, middleware, etc.)
|
|
832
837
|
*
|
|
833
|
-
* `root` must be forward-slash — joined with `path.posix.join
|
|
834
|
-
* `findDir
|
|
835
|
-
* `runCheck`, which normalizes it.
|
|
838
|
+
* `root` must be forward-slash — joined with `path.posix.join` and passed to
|
|
839
|
+
* `findDir`. Only called from `runCheck`, which normalizes it.
|
|
836
840
|
*/
|
|
837
841
|
function checkConventions(root) {
|
|
838
842
|
const items = [];
|
|
@@ -931,7 +935,7 @@ function checkConventions(root) {
|
|
|
931
935
|
const cjsGlobalFiles = [];
|
|
932
936
|
for (const file of allSourceFiles) {
|
|
933
937
|
const content = fs.readFileSync(file, "utf-8");
|
|
934
|
-
const rel = path.
|
|
938
|
+
const rel = normalizePathSeparators(path.relative(root, file));
|
|
935
939
|
if (viewTransitionRegex.test(content)) viewTransitionFiles.push(rel);
|
|
936
940
|
if (hasFreeCjsGlobal(content)) cjsGlobalFiles.push(rel);
|
|
937
941
|
}
|
package/dist/cli.js
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { detectPackageManager, ensureViteConfigCompatibility, hasAppDir, hasViteConfig } from "./utils/project.js";
|
|
3
|
+
import { normalizePathSeparators } from "./utils/path.js";
|
|
3
4
|
import { formatReport, runCheck } from "./check.js";
|
|
4
5
|
import { parseArgs } from "./cli-args.js";
|
|
5
6
|
import { createDevServerConfigPlugin, normalizeDevServerHostname } from "./cli-dev-config.js";
|
|
6
|
-
import { normalizePathSeparators } from "./utils/path.js";
|
|
7
7
|
import { PHASE_PRODUCTION_BUILD } from "./shims/constants.js";
|
|
8
8
|
import { createRscCompatibilityId, loadNextConfig, resolveNextConfig } from "./config/next-config.js";
|
|
9
9
|
import { generateRouteTypes } from "./typegen.js";
|
|
10
10
|
import { clearPagesClientAssetsBuildMetadata } from "./build/pages-client-assets-module.js";
|
|
11
|
-
import { findVinextPrerenderConfigInPlugins, formatVinextPrerenderLabel, resolveVinextPrerenderDecision } from "./config/prerender.js";
|
|
11
|
+
import { findVinextPrerenderConfigInPlugins, findVinextRouteRootConfigInPlugins, formatVinextPrerenderLabel, resolveVinextPrerenderDecision } from "./config/prerender.js";
|
|
12
12
|
import vinext from "./index.js";
|
|
13
13
|
import { runPrerender } from "./build/run-prerender.js";
|
|
14
|
-
import {
|
|
15
|
-
import { deploy, parseDeployArgs } from "./packages/cloudflare/src/deploy.js";
|
|
16
|
-
import { printDeployHelp } from "./packages/cloudflare/src/deploy-help.js";
|
|
14
|
+
import { emitPrerenderPathManifest } from "./build/prerender-paths.js";
|
|
17
15
|
import { getReactUpgradeDeps } from "./utils/react-version.js";
|
|
18
16
|
import { init } from "./init.js";
|
|
19
|
-
import {
|
|
17
|
+
import { resolveInitOptions } from "./init-platform.js";
|
|
18
|
+
import { loadDotenv } from "./config/dotenv.js";
|
|
20
19
|
import { resolveVinextPackageRoot } from "./utils/vinext-root.js";
|
|
21
20
|
import { emitStandaloneOutput } from "./build/standalone.js";
|
|
22
21
|
import { cleanBuildOutput } from "./build/clean-output.js";
|
|
@@ -34,7 +33,6 @@ import { execFileSync } from "node:child_process";
|
|
|
34
33
|
* vinext dev Start development server (Vite)
|
|
35
34
|
* vinext build Build for production
|
|
36
35
|
* vinext start Start production server
|
|
37
|
-
* vinext deploy Deprecated Cloudflare deploy shim
|
|
38
36
|
* vinext typegen Generate App Router route helper types
|
|
39
37
|
* vinext lint Run linter (delegates to eslint/oxlint)
|
|
40
38
|
*
|
|
@@ -128,7 +126,10 @@ function hasPagesDir() {
|
|
|
128
126
|
return fs.existsSync(path.join(process.cwd(), "pages")) || fs.existsSync(path.join(process.cwd(), "src", "pages"));
|
|
129
127
|
}
|
|
130
128
|
async function loadBuildViteConfigMetadata(vite, root) {
|
|
131
|
-
if (!hasViteConfig(root)) return {
|
|
129
|
+
if (!hasViteConfig(root)) return {
|
|
130
|
+
prerenderConfig: null,
|
|
131
|
+
routeRootConfig: null
|
|
132
|
+
};
|
|
132
133
|
const loaded = await vite.loadConfigFromFile({
|
|
133
134
|
command: "build",
|
|
134
135
|
mode: "production"
|
|
@@ -136,7 +137,8 @@ async function loadBuildViteConfigMetadata(vite, root) {
|
|
|
136
137
|
const emptyOutDir = loaded?.config.build?.emptyOutDir;
|
|
137
138
|
return {
|
|
138
139
|
emptyOutDir: typeof emptyOutDir === "boolean" ? emptyOutDir : void 0,
|
|
139
|
-
prerenderConfig: findVinextPrerenderConfigInPlugins(loaded?.config.plugins)
|
|
140
|
+
prerenderConfig: findVinextPrerenderConfigInPlugins(loaded?.config.plugins),
|
|
141
|
+
routeRootConfig: findVinextRouteRootConfigInPlugins(loaded?.config.plugins)
|
|
140
142
|
};
|
|
141
143
|
}
|
|
142
144
|
/**
|
|
@@ -277,8 +279,7 @@ async function buildApp() {
|
|
|
277
279
|
});
|
|
278
280
|
applyViteConfigCompatibility(process.cwd());
|
|
279
281
|
const vite = await loadVite();
|
|
280
|
-
const
|
|
281
|
-
const withBuildBundlerOptions = (bundlerOptions) => viteMajorVersion >= 8 ? { rolldownOptions: bundlerOptions } : { rollupOptions: bundlerOptions };
|
|
282
|
+
const withBuildBundlerOptions = (bundlerOptions) => ({ rolldownOptions: bundlerOptions });
|
|
282
283
|
console.log(`\n vinext build (Vite ${getViteVersion()})\n`);
|
|
283
284
|
const root = process.cwd();
|
|
284
285
|
const isApp = hasAppDir(normalizePathSeparators(root));
|
|
@@ -330,7 +331,7 @@ async function buildApp() {
|
|
|
330
331
|
mode: "production",
|
|
331
332
|
isSsrBuild: true
|
|
332
333
|
}, void 0, root);
|
|
333
|
-
if (loaded?.config.plugins) userTransformPlugins = loaded.config.plugins.flat(Infinity).filter((p) => !!p && typeof p.name === "string" && !p.name.startsWith("vinext:") && !p.name.startsWith("vite:react") && !p.name.startsWith("rsc:") && p.name !== "vite-rsc-load-module-dev-proxy" &&
|
|
334
|
+
if (loaded?.config.plugins) userTransformPlugins = loaded.config.plugins.flat(Infinity).filter((p) => !!p && typeof p.name === "string" && !p.name.startsWith("vinext:") && !p.name.startsWith("vite:react") && !p.name.startsWith("rsc:") && p.name !== "vite-rsc-load-module-dev-proxy" && !p.name.startsWith("vite-plugin-cloudflare"));
|
|
334
335
|
}
|
|
335
336
|
await vite.build({
|
|
336
337
|
root,
|
|
@@ -383,6 +384,11 @@ async function buildApp() {
|
|
|
383
384
|
root: normalizePathSeparators(process.cwd()),
|
|
384
385
|
concurrency: parsed.prerenderConcurrency
|
|
385
386
|
});
|
|
387
|
+
await emitPrerenderPathManifest({
|
|
388
|
+
root: normalizePathSeparators(process.cwd()),
|
|
389
|
+
nextConfigOverride: resolvedNextConfig,
|
|
390
|
+
routeRootConfig: buildConfigMetadata.routeRootConfig
|
|
391
|
+
});
|
|
386
392
|
}
|
|
387
393
|
process.stdout.write("\x1B[0m");
|
|
388
394
|
const { printBuildReport } = await import("./build/report.js");
|
|
@@ -452,33 +458,9 @@ async function lint() {
|
|
|
452
458
|
process.exit(1);
|
|
453
459
|
}
|
|
454
460
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
printDeployDeprecationWarning();
|
|
459
|
-
printDeployHelp();
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
printDeployDeprecationWarning();
|
|
463
|
-
await loadVite();
|
|
464
|
-
console.log(`\n vinext deploy (Vite ${getViteVersion()})\n`);
|
|
465
|
-
await deploy({
|
|
466
|
-
root: process.cwd(),
|
|
467
|
-
preview: parsed.preview,
|
|
468
|
-
env: parsed.env,
|
|
469
|
-
skipBuild: parsed.skipBuild,
|
|
470
|
-
dryRun: parsed.dryRun,
|
|
471
|
-
name: parsed.name,
|
|
472
|
-
prerenderAll: parsed.prerenderAll,
|
|
473
|
-
prerenderConcurrency: parsed.prerenderConcurrency,
|
|
474
|
-
experimentalTPR: parsed.experimentalTPR,
|
|
475
|
-
tprCoverage: parsed.tprCoverage,
|
|
476
|
-
tprLimit: parsed.tprLimit,
|
|
477
|
-
tprWindow: parsed.tprWindow
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
function printDeployDeprecationWarning() {
|
|
481
|
-
console.log(" ⚠️ Warning: `vinext deploy` has moved to the `@vinext/cloudflare` package.\n Please switch to `npx @vinext/cloudflare deploy` or `vp exec vinext-cloudflare deploy`; this compatibility command will be removed in a future release.\n");
|
|
461
|
+
function failRemovedDeployCommand() {
|
|
462
|
+
console.error("\n Error: `vinext deploy` has moved to the `@vinext/cloudflare` package.\n\n Run `npx @vinext/cloudflare deploy` or `vp exec vinext-cloudflare deploy` instead.\n");
|
|
463
|
+
process.exit(1);
|
|
482
464
|
}
|
|
483
465
|
async function check() {
|
|
484
466
|
if (parseArgs(rawArgs).help) return printHelp("check");
|
|
@@ -508,17 +490,13 @@ async function initCommand() {
|
|
|
508
490
|
const port = parsed.port ?? 3001;
|
|
509
491
|
const skipCheck = rawArgs.includes("--skip-check");
|
|
510
492
|
const force = rawArgs.includes("--force");
|
|
511
|
-
const
|
|
512
|
-
const platformOptions = await INIT_PLATFORMS[platform].options(rawArgs);
|
|
513
|
-
const prerender = await resolveInitPrerender(rawArgs);
|
|
493
|
+
const initOptions = await resolveInitOptions(rawArgs);
|
|
514
494
|
await init({
|
|
515
495
|
root: process.cwd(),
|
|
516
496
|
port,
|
|
517
497
|
skipCheck,
|
|
518
498
|
force,
|
|
519
|
-
|
|
520
|
-
prerender,
|
|
521
|
-
cloudflare: platform === "cloudflare" ? platformOptions : void 0
|
|
499
|
+
...initOptions
|
|
522
500
|
});
|
|
523
501
|
}
|
|
524
502
|
function printHelp(cmd) {
|
|
@@ -574,11 +552,7 @@ function printHelp(cmd) {
|
|
|
574
552
|
`);
|
|
575
553
|
return;
|
|
576
554
|
}
|
|
577
|
-
if (cmd === "deploy")
|
|
578
|
-
printDeployDeprecationWarning();
|
|
579
|
-
printDeployHelp();
|
|
580
|
-
return;
|
|
581
|
-
}
|
|
555
|
+
if (cmd === "deploy") failRemovedDeployCommand();
|
|
582
556
|
if (cmd === "check") {
|
|
583
557
|
console.log(`
|
|
584
558
|
vinext check - Scan Next.js app for compatibility
|
|
@@ -611,6 +585,11 @@ function printHelp(cmd) {
|
|
|
611
585
|
--platform <target> Deployment target: cloudflare or node
|
|
612
586
|
--prerender Configure vinext build to pre-render all static routes
|
|
613
587
|
(default: prompt, with No selected by default)
|
|
588
|
+
--experimental-warm-cdn-cache
|
|
589
|
+
Add experimental CDN pre-warming to the Cloudflare deploy script
|
|
590
|
+
(Workers Cache CDN only, default: prompt with No)
|
|
591
|
+
--cdn-cache <type> Cloudflare CDN cache: workers-cache or data-cache
|
|
592
|
+
(default: workers-cache)
|
|
614
593
|
--data-cache <type> Cloudflare data cache: kv or none (default: kv)
|
|
615
594
|
--image-optimization <type>
|
|
616
595
|
Cloudflare image optimization: cloudflare-images or none
|
|
@@ -619,11 +598,15 @@ function printHelp(cmd) {
|
|
|
619
598
|
Examples:
|
|
620
599
|
vinext init Prompt for a deployment platform
|
|
621
600
|
vinext init --platform=cloudflare Configure Cloudflare Workers (default)
|
|
601
|
+
vinext init --platform=cloudflare --cdn-cache=data-cache
|
|
602
|
+
Fall through CDN caching to the data cache
|
|
622
603
|
vinext init --platform=cloudflare --data-cache=kv
|
|
623
604
|
Configure the default Cloudflare cache handlers
|
|
624
605
|
vinext init --platform=cloudflare --image-optimization=none
|
|
625
606
|
Do not configure Cloudflare Images
|
|
626
607
|
vinext init --prerender Add prerender: { routes: "*" } to vite.config.ts
|
|
608
|
+
vinext init --experimental-warm-cdn-cache
|
|
609
|
+
Add experimental CDN pre-warming to deploy:vinext
|
|
627
610
|
vinext init --platform=node Configure a Node deployment
|
|
628
611
|
vinext init -p 4000 Use port 4000 for dev:vinext
|
|
629
612
|
vinext init --force Overwrite existing vite.config.ts
|
|
@@ -722,10 +705,7 @@ switch (command) {
|
|
|
722
705
|
});
|
|
723
706
|
break;
|
|
724
707
|
case "deploy":
|
|
725
|
-
|
|
726
|
-
console.error(e);
|
|
727
|
-
process.exit(1);
|
|
728
|
-
});
|
|
708
|
+
failRemovedDeployCommand();
|
|
729
709
|
break;
|
|
730
710
|
case "init":
|
|
731
711
|
initCommand().catch((e) => {
|