vinext 0.0.26 → 0.0.27
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 +89 -85
- package/dist/build/static-export.d.ts.map +1 -1
- package/dist/build/static-export.js +3 -8
- package/dist/build/static-export.js.map +1 -1
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +152 -48
- package/dist/check.js.map +1 -1
- package/dist/cli.js +10 -11
- package/dist/cli.js.map +1 -1
- package/dist/cloudflare/kv-cache-handler.d.ts +32 -1
- package/dist/cloudflare/kv-cache-handler.d.ts.map +1 -1
- package/dist/cloudflare/kv-cache-handler.js +47 -21
- package/dist/cloudflare/kv-cache-handler.js.map +1 -1
- package/dist/cloudflare/tpr.d.ts.map +1 -1
- package/dist/cloudflare/tpr.js +15 -4
- package/dist/cloudflare/tpr.js.map +1 -1
- package/dist/config/config-matchers.d.ts +27 -0
- package/dist/config/config-matchers.d.ts.map +1 -1
- package/dist/config/config-matchers.js +306 -60
- package/dist/config/config-matchers.js.map +1 -1
- package/dist/config/dotenv.d.ts.map +1 -1
- package/dist/config/dotenv.js +1 -6
- package/dist/config/dotenv.js.map +1 -1
- package/dist/config/next-config.d.ts +7 -0
- package/dist/config/next-config.d.ts.map +1 -1
- package/dist/config/next-config.js +44 -19
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +36 -19
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-rsc-entry.d.ts.map +1 -1
- package/dist/entries/app-rsc-entry.js +89 -38
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/pages-client-entry.d.ts.map +1 -1
- package/dist/entries/pages-client-entry.js +5 -3
- package/dist/entries/pages-client-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.d.ts.map +1 -1
- package/dist/entries/pages-server-entry.js +32 -10
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +204 -118
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +6 -5
- package/dist/init.js.map +1 -1
- package/dist/routing/app-router.d.ts +2 -0
- package/dist/routing/app-router.d.ts.map +1 -1
- package/dist/routing/app-router.js +10 -18
- package/dist/routing/app-router.js.map +1 -1
- package/dist/routing/file-matcher.d.ts.map +1 -1
- package/dist/routing/file-matcher.js.map +1 -1
- package/dist/routing/pages-router.d.ts +2 -0
- package/dist/routing/pages-router.d.ts.map +1 -1
- package/dist/routing/pages-router.js +8 -5
- package/dist/routing/pages-router.js.map +1 -1
- package/dist/routing/utils.d.ts.map +1 -1
- package/dist/routing/utils.js.map +1 -1
- package/dist/server/api-handler.d.ts.map +1 -1
- package/dist/server/api-handler.js +7 -2
- package/dist/server/api-handler.js.map +1 -1
- package/dist/server/app-router-entry.d.ts +3 -2
- package/dist/server/app-router-entry.d.ts.map +1 -1
- package/dist/server/app-router-entry.js +8 -4
- package/dist/server/app-router-entry.js.map +1 -1
- package/dist/server/dev-module-runner.d.ts.map +1 -1
- package/dist/server/dev-module-runner.js +1 -1
- package/dist/server/dev-module-runner.js.map +1 -1
- package/dist/server/dev-origin-check.d.ts.map +1 -1
- package/dist/server/dev-origin-check.js.map +1 -1
- package/dist/server/dev-server.d.ts.map +1 -1
- package/dist/server/dev-server.js +30 -18
- package/dist/server/dev-server.js.map +1 -1
- package/dist/server/image-optimization.d.ts.map +1 -1
- package/dist/server/image-optimization.js.map +1 -1
- package/dist/server/instrumentation.js +1 -1
- package/dist/server/instrumentation.js.map +1 -1
- package/dist/server/isr-cache.d.ts +13 -1
- package/dist/server/isr-cache.d.ts.map +1 -1
- package/dist/server/isr-cache.js +10 -1
- package/dist/server/isr-cache.js.map +1 -1
- package/dist/server/metadata-routes.d.ts.map +1 -1
- package/dist/server/metadata-routes.js +6 -18
- package/dist/server/metadata-routes.js.map +1 -1
- package/dist/server/middleware-codegen.d.ts.map +1 -1
- package/dist/server/middleware-codegen.js +12 -10
- package/dist/server/middleware-codegen.js.map +1 -1
- package/dist/server/middleware-request-headers.d.ts +9 -0
- package/dist/server/middleware-request-headers.d.ts.map +1 -0
- package/dist/server/middleware-request-headers.js +77 -0
- package/dist/server/middleware-request-headers.js.map +1 -0
- package/dist/server/middleware.d.ts.map +1 -1
- package/dist/server/middleware.js +38 -19
- package/dist/server/middleware.js.map +1 -1
- package/dist/server/normalize-path.js.map +1 -1
- package/dist/server/prod-server.d.ts +1 -1
- package/dist/server/prod-server.d.ts.map +1 -1
- package/dist/server/prod-server.js +53 -38
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/request-pipeline.d.ts +2 -1
- package/dist/server/request-pipeline.d.ts.map +1 -1
- package/dist/server/request-pipeline.js +5 -7
- package/dist/server/request-pipeline.js.map +1 -1
- package/dist/shims/cache-runtime.d.ts.map +1 -1
- package/dist/shims/cache-runtime.js +21 -16
- package/dist/shims/cache-runtime.js.map +1 -1
- package/dist/shims/cache.d.ts.map +1 -1
- package/dist/shims/cache.js +18 -17
- package/dist/shims/cache.js.map +1 -1
- package/dist/shims/constants.d.ts.map +1 -1
- package/dist/shims/constants.js +1 -6
- package/dist/shims/constants.js.map +1 -1
- package/dist/shims/dynamic.d.ts.map +1 -1
- package/dist/shims/dynamic.js +1 -1
- package/dist/shims/dynamic.js.map +1 -1
- package/dist/shims/error-boundary.d.ts.map +1 -1
- package/dist/shims/error-boundary.js +2 -3
- package/dist/shims/error-boundary.js.map +1 -1
- package/dist/shims/error.d.ts.map +1 -1
- package/dist/shims/error.js +1 -3
- package/dist/shims/error.js.map +1 -1
- package/dist/shims/fetch-cache.d.ts.map +1 -1
- package/dist/shims/fetch-cache.js +53 -29
- package/dist/shims/fetch-cache.js.map +1 -1
- package/dist/shims/font-google-base.d.ts.map +1 -1
- package/dist/shims/font-google-base.js +16 -4
- package/dist/shims/font-google-base.js.map +1 -1
- package/dist/shims/font-google.d.ts +1 -1
- package/dist/shims/font-google.d.ts.map +1 -1
- package/dist/shims/font-google.generated.d.ts.map +1 -1
- package/dist/shims/font-google.generated.js +412 -206
- package/dist/shims/font-google.generated.js.map +1 -1
- package/dist/shims/font-google.js +1 -1
- package/dist/shims/font-google.js.map +1 -1
- package/dist/shims/font-local.d.ts.map +1 -1
- package/dist/shims/font-local.js +13 -3
- package/dist/shims/font-local.js.map +1 -1
- package/dist/shims/form.d.ts.map +1 -1
- package/dist/shims/form.js +2 -2
- package/dist/shims/form.js.map +1 -1
- package/dist/shims/head.d.ts.map +1 -1
- package/dist/shims/head.js +10 -8
- package/dist/shims/head.js.map +1 -1
- package/dist/shims/headers.d.ts +23 -5
- package/dist/shims/headers.d.ts.map +1 -1
- package/dist/shims/headers.js +97 -37
- package/dist/shims/headers.js.map +1 -1
- package/dist/shims/image.d.ts.map +1 -1
- package/dist/shims/image.js +35 -8
- package/dist/shims/image.js.map +1 -1
- package/dist/shims/legacy-image.d.ts.map +1 -1
- package/dist/shims/legacy-image.js +1 -1
- package/dist/shims/legacy-image.js.map +1 -1
- package/dist/shims/link.d.ts.map +1 -1
- package/dist/shims/link.js +29 -15
- package/dist/shims/link.js.map +1 -1
- package/dist/shims/metadata.d.ts +12 -2
- package/dist/shims/metadata.d.ts.map +1 -1
- package/dist/shims/metadata.js +10 -8
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/navigation-state.d.ts.map +1 -1
- package/dist/shims/navigation-state.js +3 -2
- package/dist/shims/navigation-state.js.map +1 -1
- package/dist/shims/navigation.d.ts.map +1 -1
- package/dist/shims/navigation.js +26 -19
- package/dist/shims/navigation.js.map +1 -1
- package/dist/shims/request-context.d.ts +50 -0
- package/dist/shims/request-context.d.ts.map +1 -0
- package/dist/shims/request-context.js +59 -0
- package/dist/shims/request-context.js.map +1 -0
- package/dist/shims/router-state.d.ts.map +1 -1
- package/dist/shims/router-state.js +2 -1
- package/dist/shims/router-state.js.map +1 -1
- package/dist/shims/router.d.ts.map +1 -1
- package/dist/shims/router.js +18 -25
- package/dist/shims/router.js.map +1 -1
- package/dist/shims/script.d.ts.map +1 -1
- package/dist/shims/script.js.map +1 -1
- package/dist/shims/server.d.ts +13 -0
- package/dist/shims/server.d.ts.map +1 -1
- package/dist/shims/server.js +100 -34
- package/dist/shims/server.js.map +1 -1
- package/dist/shims/url-utils.d.ts.map +1 -1
- package/dist/shims/url-utils.js +1 -3
- package/dist/shims/url-utils.js.map +1 -1
- package/dist/utils/base-path.d.ts +17 -0
- package/dist/utils/base-path.d.ts.map +1 -0
- package/dist/utils/base-path.js +25 -0
- package/dist/utils/base-path.js.map +1 -0
- package/dist/utils/project.d.ts.map +1 -1
- package/dist/utils/project.js +2 -4
- package/dist/utils/project.js.map +1 -1
- package/dist/utils/query.d.ts.map +1 -1
- package/dist/utils/query.js +3 -1
- package/dist/utils/query.js.map +1 -1
- package/package.json +47 -33
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { loadEnv, parseAst } from "vite";
|
|
2
|
-
import { pagesRouter, apiRouter, invalidateRouteCache, matchRoute } from "./routing/pages-router.js";
|
|
2
|
+
import { pagesRouter, apiRouter, invalidateRouteCache, matchRoute, } from "./routing/pages-router.js";
|
|
3
3
|
import { generateServerEntry as _generateServerEntry } from "./entries/pages-server-entry.js";
|
|
4
4
|
import { generateClientEntry as _generateClientEntry } from "./entries/pages-client-entry.js";
|
|
5
5
|
import { appRouter, invalidateAppRouteCache } from "./routing/app-router.js";
|
|
@@ -19,7 +19,9 @@ import { PHASE_PRODUCTION_BUILD, PHASE_DEVELOPMENT_SERVER } from "./shims/consta
|
|
|
19
19
|
import { validateDevRequest } from "./server/dev-origin-check.js";
|
|
20
20
|
import { isExternalUrl, proxyExternalRequest, matchHeaders, matchRedirect, matchRewrite, requestContextFromRequest, sanitizeDestination, } from "./config/config-matchers.js";
|
|
21
21
|
import { scanMetadataFiles } from "./server/metadata-routes.js";
|
|
22
|
+
import { buildRequestHeadersFromMiddlewareResponse } from "./server/middleware-request-headers.js";
|
|
22
23
|
import { detectPackageManager } from "./utils/project.js";
|
|
24
|
+
import { hasBasePath } from "./utils/base-path.js";
|
|
23
25
|
import { asyncHooksStubPlugin } from "./plugins/async-hooks-stub.js";
|
|
24
26
|
import { hasWranglerConfig, formatMissingCloudflarePluginError } from "./deploy.js";
|
|
25
27
|
import tsconfigPaths from "vite-tsconfig-paths";
|
|
@@ -66,7 +68,11 @@ async function fetchAndCacheFont(cssUrl, family, cacheDir) {
|
|
|
66
68
|
while ((urlMatch = urlRe.exec(css)) !== null) {
|
|
67
69
|
const fontUrl = urlMatch[1];
|
|
68
70
|
if (!urls.has(fontUrl)) {
|
|
69
|
-
const ext = fontUrl.includes(".woff2")
|
|
71
|
+
const ext = fontUrl.includes(".woff2")
|
|
72
|
+
? ".woff2"
|
|
73
|
+
: fontUrl.includes(".woff")
|
|
74
|
+
? ".woff"
|
|
75
|
+
: ".ttf";
|
|
70
76
|
const fileHash = createHash("md5").update(fontUrl).digest("hex").slice(0, 8);
|
|
71
77
|
urls.set(fontUrl, `${family.toLowerCase().replace(/\s+/g, "-")}-${fileHash}${ext}`);
|
|
72
78
|
}
|
|
@@ -133,7 +139,9 @@ function extractStaticValue(node) {
|
|
|
133
139
|
return node.value;
|
|
134
140
|
case "UnaryExpression":
|
|
135
141
|
// Handle negative numbers: -1, -3.14
|
|
136
|
-
if (node.operator === "-" &&
|
|
142
|
+
if (node.operator === "-" &&
|
|
143
|
+
node.argument?.type === "Literal" &&
|
|
144
|
+
typeof node.argument.value === "number") {
|
|
137
145
|
return -node.argument.value;
|
|
138
146
|
}
|
|
139
147
|
return undefined;
|
|
@@ -244,7 +252,9 @@ async function resolvePostcssStringPlugins(projectRoot) {
|
|
|
244
252
|
// Load the config file
|
|
245
253
|
let config;
|
|
246
254
|
try {
|
|
247
|
-
if (configPath.endsWith(".json") ||
|
|
255
|
+
if (configPath.endsWith(".json") ||
|
|
256
|
+
configPath.endsWith(".yaml") ||
|
|
257
|
+
configPath.endsWith(".yml")) {
|
|
248
258
|
// JSON/YAML configs use object form — postcss-load-config handles these fine
|
|
249
259
|
return undefined;
|
|
250
260
|
}
|
|
@@ -267,8 +277,7 @@ async function resolvePostcssStringPlugins(projectRoot) {
|
|
|
267
277
|
// (either bare strings or tuple form ["plugin-name", { options }])
|
|
268
278
|
if (!config || !Array.isArray(config.plugins))
|
|
269
279
|
return undefined;
|
|
270
|
-
const hasStringPlugins = config.plugins.some((p) => typeof p === "string" ||
|
|
271
|
-
(Array.isArray(p) && typeof p[0] === "string"));
|
|
280
|
+
const hasStringPlugins = config.plugins.some((p) => typeof p === "string" || (Array.isArray(p) && typeof p[0] === "string"));
|
|
272
281
|
if (!hasStringPlugins)
|
|
273
282
|
return undefined;
|
|
274
283
|
// Resolve string plugin names to actual plugin functions
|
|
@@ -366,9 +375,7 @@ function clientManualChunks(id) {
|
|
|
366
375
|
const pkg = getPackageName(id);
|
|
367
376
|
if (!pkg)
|
|
368
377
|
return undefined;
|
|
369
|
-
if (pkg === "react" ||
|
|
370
|
-
pkg === "react-dom" ||
|
|
371
|
-
pkg === "scheduler") {
|
|
378
|
+
if (pkg === "react" || pkg === "react-dom" || pkg === "scheduler") {
|
|
372
379
|
return "framework";
|
|
373
380
|
}
|
|
374
381
|
// Let Rollup handle all other vendor code via its default
|
|
@@ -566,11 +573,12 @@ export default function vinext(options = {}) {
|
|
|
566
573
|
if (earlyAppDirExists && autoRsc) {
|
|
567
574
|
if (!resolvedRscPath) {
|
|
568
575
|
throw new Error("vinext: App Router detected but @vitejs/plugin-rsc is not installed.\n" +
|
|
569
|
-
"Run: " +
|
|
576
|
+
"Run: " +
|
|
577
|
+
detectPackageManager(process.cwd()) +
|
|
578
|
+
" @vitejs/plugin-rsc");
|
|
570
579
|
}
|
|
571
580
|
const rscImport = import(pathToFileURL(resolvedRscPath).href);
|
|
572
|
-
rscPluginPromise = rscImport
|
|
573
|
-
.then((mod) => {
|
|
581
|
+
rscPluginPromise = rscImport.then((mod) => {
|
|
574
582
|
const rsc = mod.default;
|
|
575
583
|
return rsc({
|
|
576
584
|
entries: {
|
|
@@ -585,9 +593,7 @@ export default function vinext(options = {}) {
|
|
|
585
593
|
// Shared state for the MDX proxy plugin. Populated during config() if MDX
|
|
586
594
|
// files are detected and @mdx-js/rollup is installed.
|
|
587
595
|
let mdxDelegate = null;
|
|
588
|
-
const reactPlugin = options.react === false
|
|
589
|
-
? false
|
|
590
|
-
: react(options.react === true ? undefined : options.react);
|
|
596
|
+
const reactPlugin = options.react === false ? false : react(options.react === true ? undefined : options.react);
|
|
591
597
|
const plugins = [
|
|
592
598
|
// Resolve tsconfig paths/baseUrl aliases so real-world Next.js repos
|
|
593
599
|
// that use @/*, #/*, or baseUrl imports work out of the box.
|
|
@@ -689,7 +695,9 @@ export default function vinext(options = {}) {
|
|
|
689
695
|
// server-side validation. Matches Next.js behavior: only configured
|
|
690
696
|
// sizes are accepted by the image optimization endpoint.
|
|
691
697
|
{
|
|
692
|
-
const deviceSizes = nextConfig.images?.deviceSizes ?? [
|
|
698
|
+
const deviceSizes = nextConfig.images?.deviceSizes ?? [
|
|
699
|
+
640, 750, 828, 1080, 1200, 1920, 2048, 3840,
|
|
700
|
+
];
|
|
693
701
|
const imageSizes = nextConfig.images?.imageSizes ?? [16, 32, 48, 64, 96, 128, 256, 384];
|
|
694
702
|
defines["process.env.__VINEXT_IMAGE_DEVICE_SIZES"] = JSON.stringify(JSON.stringify(deviceSizes));
|
|
695
703
|
defines["process.env.__VINEXT_IMAGE_SIZES"] = JSON.stringify(JSON.stringify(imageSizes));
|
|
@@ -701,6 +709,9 @@ export default function vinext(options = {}) {
|
|
|
701
709
|
// __prerender_bypass cookie is consistent across all server
|
|
702
710
|
// instances (e.g. multiple Cloudflare Workers isolates).
|
|
703
711
|
defines["process.env.__VINEXT_DRAFT_SECRET"] = JSON.stringify(crypto.randomUUID());
|
|
712
|
+
// Build ID — resolved from next.config generateBuildId() or random UUID.
|
|
713
|
+
// Exposed so server entries and the next/server shim can inject it.
|
|
714
|
+
defines["process.env.__VINEXT_BUILD_ID"] = JSON.stringify(nextConfig.buildId);
|
|
704
715
|
// Build the shim alias map — used by both resolve.alias and resolveId
|
|
705
716
|
// (resolveId handles .js extension variants for libraries like nuqs)
|
|
706
717
|
nextShimMap = {
|
|
@@ -770,8 +781,14 @@ export default function vinext(options = {}) {
|
|
|
770
781
|
}
|
|
771
782
|
}
|
|
772
783
|
flattenPlugins(config.plugins ?? []);
|
|
773
|
-
hasCloudflarePlugin = pluginsFlat.some((p) => p &&
|
|
774
|
-
|
|
784
|
+
hasCloudflarePlugin = pluginsFlat.some((p) => p &&
|
|
785
|
+
typeof p === "object" &&
|
|
786
|
+
typeof p.name === "string" &&
|
|
787
|
+
(p.name === "vite-plugin-cloudflare" || p.name.startsWith("vite-plugin-cloudflare:")));
|
|
788
|
+
hasNitroPlugin = pluginsFlat.some((p) => p &&
|
|
789
|
+
typeof p === "object" &&
|
|
790
|
+
typeof p.name === "string" &&
|
|
791
|
+
(p.name === "nitro" || p.name.startsWith("nitro:")));
|
|
775
792
|
// Resolve PostCSS string plugin names that Vite can't handle.
|
|
776
793
|
// Next.js projects commonly use array-form plugins like
|
|
777
794
|
// `plugins: ["@tailwindcss/postcss"]` which postcss-load-config
|
|
@@ -785,9 +802,12 @@ export default function vinext(options = {}) {
|
|
|
785
802
|
}
|
|
786
803
|
// Auto-inject @mdx-js/rollup when MDX files exist and no MDX plugin is
|
|
787
804
|
// already configured. Applies remark/rehype plugins from next.config.
|
|
788
|
-
const hasMdxPlugin = pluginsFlat.some((p) => p &&
|
|
805
|
+
const hasMdxPlugin = pluginsFlat.some((p) => p &&
|
|
806
|
+
typeof p === "object" &&
|
|
807
|
+
typeof p.name === "string" &&
|
|
789
808
|
(p.name === "@mdx-js/rollup" || p.name === "mdx"));
|
|
790
|
-
if (!hasMdxPlugin &&
|
|
809
|
+
if (!hasMdxPlugin &&
|
|
810
|
+
hasMdxFiles(root, hasAppDir ? appDir : null, hasPagesDir ? pagesDir : null)) {
|
|
791
811
|
try {
|
|
792
812
|
const mdxRollup = await import("@mdx-js/rollup");
|
|
793
813
|
const mdxFactory = mdxRollup.default ?? mdxRollup;
|
|
@@ -811,7 +831,9 @@ export default function vinext(options = {}) {
|
|
|
811
831
|
catch {
|
|
812
832
|
// @mdx-js/rollup not installed — warn but don't fail
|
|
813
833
|
console.warn("[vinext] MDX files detected but @mdx-js/rollup is not installed. " +
|
|
814
|
-
"Install it with: " +
|
|
834
|
+
"Install it with: " +
|
|
835
|
+
detectPackageManager(process.cwd()) +
|
|
836
|
+
" @mdx-js/rollup");
|
|
815
837
|
}
|
|
816
838
|
}
|
|
817
839
|
// Detect if this is a standalone SSR build (set by `vite build --ssr`
|
|
@@ -893,12 +915,14 @@ export default function vinext(options = {}) {
|
|
|
893
915
|
// Skip when targeting bundled runtimes (Cloudflare/Nitro bundle everything).
|
|
894
916
|
// This also resolves extensionless-import issues in packages like
|
|
895
917
|
// `validator` (see #189) by routing them through Vite's resolver.
|
|
896
|
-
...(hasCloudflarePlugin || hasNitroPlugin
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
918
|
+
...(hasCloudflarePlugin || hasNitroPlugin
|
|
919
|
+
? {}
|
|
920
|
+
: {
|
|
921
|
+
ssr: {
|
|
922
|
+
external: ["react", "react-dom", "react-dom/server"],
|
|
923
|
+
noExternal: true,
|
|
924
|
+
},
|
|
925
|
+
}),
|
|
902
926
|
resolve: {
|
|
903
927
|
alias: nextShimMap,
|
|
904
928
|
// Dedupe React packages to prevent dual-instance errors.
|
|
@@ -906,12 +930,7 @@ export default function vinext(options = {}) {
|
|
|
906
930
|
// brings its own React copy, multiple React instances can load,
|
|
907
931
|
// causing cryptic "Invalid hook call" errors. This is a no-op
|
|
908
932
|
// when only one copy exists.
|
|
909
|
-
dedupe: [
|
|
910
|
-
"react",
|
|
911
|
-
"react-dom",
|
|
912
|
-
"react/jsx-runtime",
|
|
913
|
-
"react/jsx-dev-runtime",
|
|
914
|
-
],
|
|
933
|
+
dedupe: ["react", "react-dom", "react/jsx-runtime", "react/jsx-dev-runtime"],
|
|
915
934
|
},
|
|
916
935
|
// Exclude vinext from dependency optimization so esbuild doesn't
|
|
917
936
|
// scan dist files containing virtual module imports (virtual:vinext-*)
|
|
@@ -954,34 +973,31 @@ export default function vinext(options = {}) {
|
|
|
954
973
|
// "Invalid hook call" from duplicate React instances).
|
|
955
974
|
// The entries must be relative to the project root.
|
|
956
975
|
const relAppDir = path.relative(root, appDir);
|
|
957
|
-
const appEntries = [
|
|
958
|
-
`${relAppDir}/**/*.{tsx,ts,jsx,js}`,
|
|
959
|
-
];
|
|
976
|
+
const appEntries = [`${relAppDir}/**/*.{tsx,ts,jsx,js}`];
|
|
960
977
|
viteConfig.environments = {
|
|
961
978
|
rsc: {
|
|
962
|
-
...(hasCloudflarePlugin || hasNitroPlugin
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
},
|
|
984
|
-
}),
|
|
979
|
+
...(hasCloudflarePlugin || hasNitroPlugin
|
|
980
|
+
? {}
|
|
981
|
+
: {
|
|
982
|
+
resolve: {
|
|
983
|
+
// Externalize native/heavy packages so the RSC environment
|
|
984
|
+
// loads them natively via Node rather than through Vite's
|
|
985
|
+
// ESM module evaluator (which can't handle native addons).
|
|
986
|
+
// Note: Do NOT externalize react/react-dom here — they must
|
|
987
|
+
// be bundled with the "react-server" condition for RSC.
|
|
988
|
+
// Skip when targeting bundled runtimes (Cloudflare/Nitro).
|
|
989
|
+
external: userSsrExternal === true
|
|
990
|
+
? true
|
|
991
|
+
: ["satori", "@resvg/resvg-js", "yoga-wasm-web", ...userSsrExternal],
|
|
992
|
+
// Force all node_modules through Vite's transform pipeline
|
|
993
|
+
// so non-JS imports (CSS, images) don't hit Node's native
|
|
994
|
+
// ESM loader. Matches Next.js behavior of bundling everything.
|
|
995
|
+
// Packages in `external` above take precedence per Vite rules.
|
|
996
|
+
// When user sets `ssr.external: true`, skip noExternal since
|
|
997
|
+
// everything is already externalized.
|
|
998
|
+
...(userSsrExternal === true ? {} : { noExternal: true }),
|
|
999
|
+
},
|
|
1000
|
+
}),
|
|
985
1001
|
optimizeDeps: {
|
|
986
1002
|
exclude: ["vinext", "@vercel/og"],
|
|
987
1003
|
entries: appEntries,
|
|
@@ -994,17 +1010,19 @@ export default function vinext(options = {}) {
|
|
|
994
1010
|
},
|
|
995
1011
|
},
|
|
996
1012
|
ssr: {
|
|
997
|
-
...(hasCloudflarePlugin || hasNitroPlugin
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1013
|
+
...(hasCloudflarePlugin || hasNitroPlugin
|
|
1014
|
+
? {}
|
|
1015
|
+
: {
|
|
1016
|
+
resolve: {
|
|
1017
|
+
external: userSsrExternal === true ? true : [...userSsrExternal],
|
|
1018
|
+
// Force all node_modules through Vite's transform pipeline
|
|
1019
|
+
// so non-JS imports (CSS, images) don't hit Node's native
|
|
1020
|
+
// ESM loader. Matches Next.js behavior of bundling everything.
|
|
1021
|
+
// When user sets `ssr.external: true`, skip noExternal since
|
|
1022
|
+
// everything is already externalized.
|
|
1023
|
+
...(userSsrExternal === true ? {} : { noExternal: true }),
|
|
1024
|
+
},
|
|
1025
|
+
}),
|
|
1008
1026
|
optimizeDeps: {
|
|
1009
1027
|
exclude: ["vinext", "@vercel/og"],
|
|
1010
1028
|
entries: appEntries,
|
|
@@ -1137,10 +1155,12 @@ export default function vinext(options = {}) {
|
|
|
1137
1155
|
return RESOLVED_SERVER_ENTRY;
|
|
1138
1156
|
if (cleanId === VIRTUAL_CLIENT_ENTRY)
|
|
1139
1157
|
return RESOLVED_CLIENT_ENTRY;
|
|
1140
|
-
if (cleanId.endsWith("/" + VIRTUAL_SERVER_ENTRY) ||
|
|
1158
|
+
if (cleanId.endsWith("/" + VIRTUAL_SERVER_ENTRY) ||
|
|
1159
|
+
cleanId.endsWith("\\" + VIRTUAL_SERVER_ENTRY)) {
|
|
1141
1160
|
return RESOLVED_SERVER_ENTRY;
|
|
1142
1161
|
}
|
|
1143
|
-
if (cleanId.endsWith("/" + VIRTUAL_CLIENT_ENTRY) ||
|
|
1162
|
+
if (cleanId.endsWith("/" + VIRTUAL_CLIENT_ENTRY) ||
|
|
1163
|
+
cleanId.endsWith("\\" + VIRTUAL_CLIENT_ENTRY)) {
|
|
1144
1164
|
return RESOLVED_CLIENT_ENTRY;
|
|
1145
1165
|
}
|
|
1146
1166
|
// App Router virtual modules
|
|
@@ -1150,13 +1170,16 @@ export default function vinext(options = {}) {
|
|
|
1150
1170
|
return RESOLVED_APP_SSR_ENTRY;
|
|
1151
1171
|
if (cleanId === VIRTUAL_APP_BROWSER_ENTRY)
|
|
1152
1172
|
return RESOLVED_APP_BROWSER_ENTRY;
|
|
1153
|
-
if (cleanId.endsWith("/" + VIRTUAL_RSC_ENTRY) ||
|
|
1173
|
+
if (cleanId.endsWith("/" + VIRTUAL_RSC_ENTRY) ||
|
|
1174
|
+
cleanId.endsWith("\\" + VIRTUAL_RSC_ENTRY)) {
|
|
1154
1175
|
return RESOLVED_RSC_ENTRY;
|
|
1155
1176
|
}
|
|
1156
|
-
if (cleanId.endsWith("/" + VIRTUAL_APP_SSR_ENTRY) ||
|
|
1177
|
+
if (cleanId.endsWith("/" + VIRTUAL_APP_SSR_ENTRY) ||
|
|
1178
|
+
cleanId.endsWith("\\" + VIRTUAL_APP_SSR_ENTRY)) {
|
|
1157
1179
|
return RESOLVED_APP_SSR_ENTRY;
|
|
1158
1180
|
}
|
|
1159
|
-
if (cleanId.endsWith("/" + VIRTUAL_APP_BROWSER_ENTRY) ||
|
|
1181
|
+
if (cleanId.endsWith("/" + VIRTUAL_APP_BROWSER_ENTRY) ||
|
|
1182
|
+
cleanId.endsWith("\\" + VIRTUAL_APP_BROWSER_ENTRY)) {
|
|
1160
1183
|
return RESOLVED_APP_BROWSER_ENTRY;
|
|
1161
1184
|
}
|
|
1162
1185
|
},
|
|
@@ -1448,9 +1471,14 @@ export default function vinext(options = {}) {
|
|
|
1448
1471
|
// loads the module. The gap between them is exactly the Vite
|
|
1449
1472
|
// compile/transform cost.
|
|
1450
1473
|
function _parseTiming(raw) {
|
|
1451
|
-
const [handlerStart, inHandlerCompileMs, renderMs] = String(raw)
|
|
1452
|
-
|
|
1453
|
-
|
|
1474
|
+
const [handlerStart, inHandlerCompileMs, renderMs] = String(raw)
|
|
1475
|
+
.split(",")
|
|
1476
|
+
.map((v) => Number(v));
|
|
1477
|
+
if (!Number.isNaN(handlerStart) &&
|
|
1478
|
+
!Number.isNaN(inHandlerCompileMs) &&
|
|
1479
|
+
inHandlerCompileMs !== -1) {
|
|
1480
|
+
_compileMs =
|
|
1481
|
+
Math.max(0, Math.round(handlerStart - _reqStart)) + inHandlerCompileMs;
|
|
1454
1482
|
}
|
|
1455
1483
|
if (!Number.isNaN(renderMs) && renderMs !== -1) {
|
|
1456
1484
|
_renderMs = renderMs;
|
|
@@ -1496,7 +1524,9 @@ export default function vinext(options = {}) {
|
|
|
1496
1524
|
// matching what Next.js shows for soft navigations.
|
|
1497
1525
|
const resolvedRenderMs = _renderMs !== undefined
|
|
1498
1526
|
? _renderMs
|
|
1499
|
-
:
|
|
1527
|
+
: _compileMs !== undefined
|
|
1528
|
+
? Math.max(0, Math.round(totalMs - _compileMs))
|
|
1529
|
+
: undefined;
|
|
1500
1530
|
logRequest({
|
|
1501
1531
|
method: req.method ?? "GET",
|
|
1502
1532
|
url: logUrl,
|
|
@@ -1633,7 +1663,10 @@ export default function vinext(options = {}) {
|
|
|
1633
1663
|
}
|
|
1634
1664
|
// Normalize trailing slash based on next.config.js trailingSlash setting.
|
|
1635
1665
|
// Redirect to the canonical form if needed.
|
|
1636
|
-
if (nextConfig &&
|
|
1666
|
+
if (nextConfig &&
|
|
1667
|
+
pathname !== "/" &&
|
|
1668
|
+
pathname !== "/api" &&
|
|
1669
|
+
!pathname.startsWith("/api/")) {
|
|
1637
1670
|
const hasTrailing = pathname.endsWith("/");
|
|
1638
1671
|
if (nextConfig.trailingSlash && !hasTrailing) {
|
|
1639
1672
|
// trailingSlash: true — redirect /about → /about/
|
|
@@ -1652,12 +1685,24 @@ export default function vinext(options = {}) {
|
|
|
1652
1685
|
return;
|
|
1653
1686
|
}
|
|
1654
1687
|
}
|
|
1688
|
+
const applyRequestHeadersToNodeRequest = (nextRequestHeaders) => {
|
|
1689
|
+
for (const key of Object.keys(req.headers)) {
|
|
1690
|
+
delete req.headers[key];
|
|
1691
|
+
}
|
|
1692
|
+
for (const [key, value] of nextRequestHeaders) {
|
|
1693
|
+
req.headers[key] = value;
|
|
1694
|
+
}
|
|
1695
|
+
};
|
|
1696
|
+
let middlewareRequestHeaders = null;
|
|
1655
1697
|
// Run middleware.ts if present
|
|
1656
1698
|
if (middlewarePath) {
|
|
1657
1699
|
// Only trust X-Forwarded-Proto when behind a trusted proxy
|
|
1658
|
-
const devTrustProxy = process.env.VINEXT_TRUST_PROXY === "1" ||
|
|
1700
|
+
const devTrustProxy = process.env.VINEXT_TRUST_PROXY === "1" ||
|
|
1701
|
+
(process.env.VINEXT_TRUSTED_HOSTS ?? "").split(",").some((h) => h.trim());
|
|
1659
1702
|
const rawProto = devTrustProxy
|
|
1660
|
-
? String(req.headers["x-forwarded-proto"] || "")
|
|
1703
|
+
? String(req.headers["x-forwarded-proto"] || "")
|
|
1704
|
+
.split(",")[0]
|
|
1705
|
+
.trim()
|
|
1661
1706
|
: "";
|
|
1662
1707
|
const mwProto = rawProto === "https" || rawProto === "http" ? rawProto : "http";
|
|
1663
1708
|
const origin = `${mwProto}://${req.headers.host || "localhost"}`;
|
|
@@ -1670,7 +1715,9 @@ export default function vinext(options = {}) {
|
|
|
1670
1715
|
const result = await runMiddleware(getPagesRunner(), middlewarePath, middlewareRequest);
|
|
1671
1716
|
if (!result.continue) {
|
|
1672
1717
|
if (result.redirectUrl) {
|
|
1673
|
-
const redirectHeaders = {
|
|
1718
|
+
const redirectHeaders = {
|
|
1719
|
+
Location: result.redirectUrl,
|
|
1720
|
+
};
|
|
1674
1721
|
if (result.responseHeaders) {
|
|
1675
1722
|
for (const [key, value] of result.responseHeaders) {
|
|
1676
1723
|
const existing = redirectHeaders[key];
|
|
@@ -1704,13 +1751,21 @@ export default function vinext(options = {}) {
|
|
|
1704
1751
|
// config has/missing conditions and downstream handlers
|
|
1705
1752
|
// see middleware-modified cookies and headers.
|
|
1706
1753
|
if (result.responseHeaders) {
|
|
1707
|
-
const
|
|
1708
|
-
for (const [key, value] of
|
|
1709
|
-
if (
|
|
1710
|
-
|
|
1711
|
-
|
|
1754
|
+
const currentRequestHeaders = new Headers();
|
|
1755
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
1756
|
+
if (Array.isArray(value)) {
|
|
1757
|
+
currentRequestHeaders.set(key, value.join(", "));
|
|
1758
|
+
}
|
|
1759
|
+
else if (value !== undefined) {
|
|
1760
|
+
currentRequestHeaders.set(key, value);
|
|
1712
1761
|
}
|
|
1713
|
-
|
|
1762
|
+
}
|
|
1763
|
+
middlewareRequestHeaders = buildRequestHeadersFromMiddlewareResponse(currentRequestHeaders, result.responseHeaders);
|
|
1764
|
+
if (middlewareRequestHeaders && !hasAppDir) {
|
|
1765
|
+
applyRequestHeadersToNodeRequest(middlewareRequestHeaders);
|
|
1766
|
+
}
|
|
1767
|
+
for (const [key, value] of result.responseHeaders) {
|
|
1768
|
+
if (!key.startsWith("x-middleware-")) {
|
|
1714
1769
|
res.appendHeader(key, value);
|
|
1715
1770
|
}
|
|
1716
1771
|
}
|
|
@@ -1758,9 +1813,10 @@ export default function vinext(options = {}) {
|
|
|
1758
1813
|
// Convert Node.js IncomingMessage headers to a Web Request for
|
|
1759
1814
|
// requestContextFromRequest(), which uses the standard Web API.
|
|
1760
1815
|
const reqUrl = new URL(url, `http://${req.headers.host || "localhost"}`);
|
|
1761
|
-
const reqCtxHeaders =
|
|
1762
|
-
.
|
|
1763
|
-
|
|
1816
|
+
const reqCtxHeaders = middlewareRequestHeaders ??
|
|
1817
|
+
new Headers(Object.fromEntries(Object.entries(req.headers)
|
|
1818
|
+
.filter(([, v]) => v !== undefined)
|
|
1819
|
+
.map(([k, v]) => [k, Array.isArray(v) ? v.join(", ") : String(v)])));
|
|
1764
1820
|
const reqCtx = requestContextFromRequest(new Request(reqUrl, { headers: reqCtxHeaders }));
|
|
1765
1821
|
// Apply custom headers from next.config.js
|
|
1766
1822
|
if (nextConfig?.headers.length) {
|
|
@@ -1768,7 +1824,7 @@ export default function vinext(options = {}) {
|
|
|
1768
1824
|
}
|
|
1769
1825
|
// Apply redirects from next.config.js
|
|
1770
1826
|
if (nextConfig?.redirects.length) {
|
|
1771
|
-
const redirected = applyRedirects(pathname, res, nextConfig.redirects, reqCtx);
|
|
1827
|
+
const redirected = applyRedirects(pathname, res, nextConfig.redirects, reqCtx, nextConfig.basePath ?? "");
|
|
1772
1828
|
if (redirected)
|
|
1773
1829
|
return;
|
|
1774
1830
|
}
|
|
@@ -1776,8 +1832,7 @@ export default function vinext(options = {}) {
|
|
|
1776
1832
|
let resolvedUrl = url;
|
|
1777
1833
|
if (nextConfig?.rewrites.beforeFiles.length) {
|
|
1778
1834
|
resolvedUrl =
|
|
1779
|
-
applyRewrites(pathname, nextConfig.rewrites.beforeFiles, reqCtx) ??
|
|
1780
|
-
url;
|
|
1835
|
+
applyRewrites(pathname, nextConfig.rewrites.beforeFiles, reqCtx) ?? url;
|
|
1781
1836
|
}
|
|
1782
1837
|
// External rewrite from beforeFiles — proxy to external URL
|
|
1783
1838
|
if (isExternalUrl(resolvedUrl)) {
|
|
@@ -1786,9 +1841,12 @@ export default function vinext(options = {}) {
|
|
|
1786
1841
|
}
|
|
1787
1842
|
// Handle API routes first (pages/api/*)
|
|
1788
1843
|
const resolvedPathname = resolvedUrl.split("?")[0];
|
|
1789
|
-
if (resolvedPathname.startsWith("/api/") ||
|
|
1790
|
-
resolvedPathname === "/api") {
|
|
1844
|
+
if (resolvedPathname.startsWith("/api/") || resolvedPathname === "/api") {
|
|
1791
1845
|
const apiRoutes = await apiRouter(pagesDir, nextConfig?.pageExtensions, fileMatcher);
|
|
1846
|
+
const apiMatch = matchRoute(resolvedUrl, apiRoutes);
|
|
1847
|
+
if (apiMatch && middlewareRequestHeaders) {
|
|
1848
|
+
applyRequestHeadersToNodeRequest(middlewareRequestHeaders);
|
|
1849
|
+
}
|
|
1792
1850
|
const handled = await handleApiRoute(server, req, res, resolvedUrl, apiRoutes);
|
|
1793
1851
|
if (handled)
|
|
1794
1852
|
return;
|
|
@@ -1820,6 +1878,9 @@ export default function vinext(options = {}) {
|
|
|
1820
1878
|
// Try rendering the resolved URL
|
|
1821
1879
|
const match = matchRoute(resolvedUrl.split("?")[0], routes);
|
|
1822
1880
|
if (match) {
|
|
1881
|
+
if (middlewareRequestHeaders) {
|
|
1882
|
+
applyRequestHeadersToNodeRequest(middlewareRequestHeaders);
|
|
1883
|
+
}
|
|
1823
1884
|
await handler(req, res, resolvedUrl, mwStatus);
|
|
1824
1885
|
return;
|
|
1825
1886
|
}
|
|
@@ -1832,6 +1893,13 @@ export default function vinext(options = {}) {
|
|
|
1832
1893
|
await proxyExternalRewriteNode(req, res, fallbackRewrite);
|
|
1833
1894
|
return;
|
|
1834
1895
|
}
|
|
1896
|
+
const fallbackMatch = matchRoute(fallbackRewrite.split("?")[0], routes);
|
|
1897
|
+
if (!fallbackMatch && hasAppDir) {
|
|
1898
|
+
return next();
|
|
1899
|
+
}
|
|
1900
|
+
if (middlewareRequestHeaders) {
|
|
1901
|
+
applyRequestHeadersToNodeRequest(middlewareRequestHeaders);
|
|
1902
|
+
}
|
|
1835
1903
|
await handler(req, res, fallbackRewrite, mwStatus);
|
|
1836
1904
|
return;
|
|
1837
1905
|
}
|
|
@@ -2032,7 +2100,10 @@ export default function vinext(options = {}) {
|
|
|
2032
2100
|
const importMatch = code.match(importRe);
|
|
2033
2101
|
if (!importMatch)
|
|
2034
2102
|
return null;
|
|
2035
|
-
const importedNames = new Set(importMatch[1]
|
|
2103
|
+
const importedNames = new Set(importMatch[1]
|
|
2104
|
+
.split(",")
|
|
2105
|
+
.map((s) => s.trim())
|
|
2106
|
+
.filter(Boolean));
|
|
2036
2107
|
const s = new MagicString(code);
|
|
2037
2108
|
let hasChanges = false;
|
|
2038
2109
|
const cacheDir = this._cacheDir;
|
|
@@ -2058,10 +2129,14 @@ export default function vinext(options = {}) {
|
|
|
2058
2129
|
}
|
|
2059
2130
|
// Build the Google Fonts CSS URL
|
|
2060
2131
|
const weights = options.weight
|
|
2061
|
-
? Array.isArray(options.weight)
|
|
2132
|
+
? Array.isArray(options.weight)
|
|
2133
|
+
? options.weight
|
|
2134
|
+
: [options.weight]
|
|
2062
2135
|
: [];
|
|
2063
2136
|
const styles = options.style
|
|
2064
|
-
? Array.isArray(options.style)
|
|
2137
|
+
? Array.isArray(options.style)
|
|
2138
|
+
? options.style
|
|
2139
|
+
: [options.style]
|
|
2065
2140
|
: [];
|
|
2066
2141
|
const display = options.display ?? "swap";
|
|
2067
2142
|
let spec = family.replace(/\s+/g, "+");
|
|
@@ -2217,7 +2292,9 @@ export default function vinext(options = {}) {
|
|
|
2217
2292
|
return null;
|
|
2218
2293
|
if (!resolvedRscTransformsPath) {
|
|
2219
2294
|
throw new Error("vinext: 'use cache' requires @vitejs/plugin-rsc to be installed.\n" +
|
|
2220
|
-
"Run: " +
|
|
2295
|
+
"Run: " +
|
|
2296
|
+
detectPackageManager(process.cwd()) +
|
|
2297
|
+
" @vitejs/plugin-rsc");
|
|
2221
2298
|
}
|
|
2222
2299
|
const { transformWrapExport, transformHoistInlineDirective } = await import(pathToFileURL(resolvedRscTransformsPath).href);
|
|
2223
2300
|
const ast = parseAst(code);
|
|
@@ -2232,7 +2309,9 @@ export default function vinext(options = {}) {
|
|
|
2232
2309
|
// (they're leaf components). Layout/template defaults are excluded
|
|
2233
2310
|
// because they receive {children} from the framework.
|
|
2234
2311
|
const directiveValue = cacheDirective.expression.value;
|
|
2235
|
-
const variant = directiveValue === "use cache"
|
|
2312
|
+
const variant = directiveValue === "use cache"
|
|
2313
|
+
? ""
|
|
2314
|
+
: directiveValue.replace("use cache:", "").replace("use cache: ", "").trim();
|
|
2236
2315
|
// Only skip default export wrapping for layouts and templates —
|
|
2237
2316
|
// they receive {children} from the framework which requires
|
|
2238
2317
|
// temporary reference handling that registerCachedFunction doesn't
|
|
@@ -2284,7 +2363,9 @@ export default function vinext(options = {}) {
|
|
|
2284
2363
|
directive: /^use cache(:\s*\w+)?$/,
|
|
2285
2364
|
runtime: (value, name, meta) => {
|
|
2286
2365
|
const directiveMatch = meta.directiveMatch[0];
|
|
2287
|
-
const variant = directiveMatch === "use cache"
|
|
2366
|
+
const variant = directiveMatch === "use cache"
|
|
2367
|
+
? ""
|
|
2368
|
+
: directiveMatch.replace("use cache:", "").replace("use cache: ", "").trim();
|
|
2288
2369
|
return `(await import(${JSON.stringify(runtimeModuleUrl2)})).registerCachedFunction(${value}, ${JSON.stringify(id + ":" + name)}, ${JSON.stringify(variant)})`;
|
|
2289
2370
|
},
|
|
2290
2371
|
rejectNonAsyncFunction: false,
|
|
@@ -2429,11 +2510,9 @@ export default function vinext(options = {}) {
|
|
|
2429
2510
|
const content = fs.readFileSync(indexPath, "utf-8");
|
|
2430
2511
|
// The font is inlined as base64 by vinext:og-inline-fetch-assets, so only
|
|
2431
2512
|
// the WASM needs to be present as a file alongside the bundle.
|
|
2432
|
-
const ogAssets = [
|
|
2433
|
-
"resvg.wasm",
|
|
2434
|
-
];
|
|
2513
|
+
const ogAssets = ["resvg.wasm"];
|
|
2435
2514
|
// Only copy if the bundle actually references these files
|
|
2436
|
-
const referencedAssets = ogAssets.filter(asset => content.includes(asset));
|
|
2515
|
+
const referencedAssets = ogAssets.filter((asset) => content.includes(asset));
|
|
2437
2516
|
if (referencedAssets.length === 0)
|
|
2438
2517
|
return;
|
|
2439
2518
|
// Find @vercel/og in node_modules
|
|
@@ -2533,7 +2612,9 @@ export default function vinext(options = {}) {
|
|
|
2533
2612
|
if (lazy.length > 0)
|
|
2534
2613
|
lazyChunksData = lazy;
|
|
2535
2614
|
}
|
|
2536
|
-
catch {
|
|
2615
|
+
catch {
|
|
2616
|
+
/* ignore parse errors */
|
|
2617
|
+
}
|
|
2537
2618
|
}
|
|
2538
2619
|
// Read SSR manifest for per-page CSS/JS injection
|
|
2539
2620
|
let ssrManifestData = null;
|
|
@@ -2542,7 +2623,9 @@ export default function vinext(options = {}) {
|
|
|
2542
2623
|
try {
|
|
2543
2624
|
ssrManifestData = JSON.parse(fs.readFileSync(ssrManifestPath, "utf-8"));
|
|
2544
2625
|
}
|
|
2545
|
-
catch {
|
|
2626
|
+
catch {
|
|
2627
|
+
/* ignore parse errors */
|
|
2628
|
+
}
|
|
2546
2629
|
}
|
|
2547
2630
|
if (hasAppDir) {
|
|
2548
2631
|
// App Router: the RSC plugin handles __VINEXT_CLIENT_ENTRY__
|
|
@@ -2589,7 +2672,8 @@ export default function vinext(options = {}) {
|
|
|
2589
2672
|
const assetsDir = path.join(clientDir, "assets");
|
|
2590
2673
|
if (fs.existsSync(assetsDir)) {
|
|
2591
2674
|
const files = fs.readdirSync(assetsDir);
|
|
2592
|
-
const entry = files.find((f) => (f.includes("vinext-client-entry") || f.includes("vinext-app-browser-entry")) &&
|
|
2675
|
+
const entry = files.find((f) => (f.includes("vinext-client-entry") || f.includes("vinext-app-browser-entry")) &&
|
|
2676
|
+
f.endsWith(".js"));
|
|
2593
2677
|
if (entry)
|
|
2594
2678
|
clientEntryFile = "assets/" + entry;
|
|
2595
2679
|
}
|
|
@@ -2722,7 +2806,7 @@ export { matchConfigPattern } from "./config/config-matchers.js";
|
|
|
2722
2806
|
*/
|
|
2723
2807
|
function stripServerExports(code) {
|
|
2724
2808
|
const SERVER_EXPORTS = new Set(["getServerSideProps", "getStaticProps", "getStaticPaths"]);
|
|
2725
|
-
if (![...SERVER_EXPORTS].some(name => code.includes(name)))
|
|
2809
|
+
if (![...SERVER_EXPORTS].some((name) => code.includes(name)))
|
|
2726
2810
|
return null;
|
|
2727
2811
|
let ast;
|
|
2728
2812
|
try {
|
|
@@ -2773,11 +2857,13 @@ function stripServerExports(code) {
|
|
|
2773
2857
|
// Build replacement: keep non-server specifiers, add stubs for stripped ones
|
|
2774
2858
|
const parts = [];
|
|
2775
2859
|
if (kept.length > 0) {
|
|
2776
|
-
const keptStr = kept
|
|
2860
|
+
const keptStr = kept
|
|
2861
|
+
.map((sp) => {
|
|
2777
2862
|
const local = sp.local.name;
|
|
2778
2863
|
const exported = sp.exported?.name ?? sp.exported?.value;
|
|
2779
2864
|
return local === exported ? local : `${local} as ${exported}`;
|
|
2780
|
-
})
|
|
2865
|
+
})
|
|
2866
|
+
.join(", ");
|
|
2781
2867
|
parts.push(`export { ${keptStr} };`);
|
|
2782
2868
|
}
|
|
2783
2869
|
for (const name of stripped) {
|
|
@@ -2796,11 +2882,13 @@ function stripServerExports(code) {
|
|
|
2796
2882
|
* Apply redirect rules from next.config.js.
|
|
2797
2883
|
* Returns true if a redirect was applied.
|
|
2798
2884
|
*/
|
|
2799
|
-
function applyRedirects(pathname, res, redirects, ctx) {
|
|
2885
|
+
function applyRedirects(pathname, res, redirects, ctx, basePath = "") {
|
|
2800
2886
|
const result = matchRedirect(pathname, redirects, ctx);
|
|
2801
2887
|
if (result) {
|
|
2802
2888
|
// Sanitize to prevent open redirect via protocol-relative URLs
|
|
2803
|
-
const dest = sanitizeDestination(result.destination)
|
|
2889
|
+
const dest = sanitizeDestination(basePath && !isExternalUrl(result.destination) && !hasBasePath(result.destination, basePath)
|
|
2890
|
+
? basePath + result.destination
|
|
2891
|
+
: result.destination);
|
|
2804
2892
|
res.writeHead(result.permanent ? 308 : 307, { Location: dest });
|
|
2805
2893
|
res.end();
|
|
2806
2894
|
return true;
|
|
@@ -2838,9 +2926,7 @@ async function proxyExternalRewriteNode(req, res, externalUrl) {
|
|
|
2838
2926
|
proxyResponse.headers.forEach((value, key) => {
|
|
2839
2927
|
const existing = nodeHeaders[key];
|
|
2840
2928
|
if (existing !== undefined) {
|
|
2841
|
-
nodeHeaders[key] = Array.isArray(existing)
|
|
2842
|
-
? [...existing, value]
|
|
2843
|
-
: [existing, value];
|
|
2929
|
+
nodeHeaders[key] = Array.isArray(existing) ? [...existing, value] : [existing, value];
|
|
2844
2930
|
}
|
|
2845
2931
|
else {
|
|
2846
2932
|
nodeHeaders[key] = value;
|