vinext 0.0.32 → 0.0.34
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 +7 -6
- package/dist/config/next-config.d.ts +2 -0
- package/dist/config/next-config.js +4 -0
- package/dist/config/next-config.js.map +1 -1
- package/dist/deploy.js +52 -4
- package/dist/deploy.js.map +1 -1
- package/dist/entries/app-browser-entry.js +3 -330
- package/dist/entries/app-browser-entry.js.map +1 -1
- package/dist/entries/app-rsc-entry.js +444 -1265
- package/dist/entries/app-rsc-entry.js.map +1 -1
- package/dist/entries/app-ssr-entry.js +4 -460
- package/dist/entries/app-ssr-entry.js.map +1 -1
- package/dist/entries/pages-server-entry.js +8 -1
- package/dist/entries/pages-server-entry.js.map +1 -1
- package/dist/entries/runtime-entry-module.d.ts +13 -0
- package/dist/entries/runtime-entry-module.js +27 -0
- package/dist/entries/runtime-entry-module.js.map +1 -0
- package/dist/index.js +302 -23
- package/dist/index.js.map +1 -1
- package/dist/plugins/optimize-imports.d.ts +38 -0
- package/dist/plugins/optimize-imports.js +557 -0
- package/dist/plugins/optimize-imports.js.map +1 -0
- package/dist/server/app-browser-entry.d.ts +1 -0
- package/dist/server/app-browser-entry.js +160 -0
- package/dist/server/app-browser-entry.js.map +1 -0
- package/dist/server/app-browser-stream.d.ts +33 -0
- package/dist/server/app-browser-stream.js +54 -0
- package/dist/server/app-browser-stream.js.map +1 -0
- package/dist/server/app-page-boundary-render.d.ts +63 -0
- package/dist/server/app-page-boundary-render.js +182 -0
- package/dist/server/app-page-boundary-render.js.map +1 -0
- package/dist/server/app-page-boundary.d.ts +57 -0
- package/dist/server/app-page-boundary.js +60 -0
- package/dist/server/app-page-boundary.js.map +1 -0
- package/dist/server/app-page-cache.d.ts +61 -0
- package/dist/server/app-page-cache.js +133 -0
- package/dist/server/app-page-cache.js.map +1 -0
- package/dist/server/app-page-execution.d.ts +46 -0
- package/dist/server/app-page-execution.js +109 -0
- package/dist/server/app-page-execution.js.map +1 -0
- package/dist/server/app-page-probe.d.ts +17 -0
- package/dist/server/app-page-probe.js +35 -0
- package/dist/server/app-page-probe.js.map +1 -0
- package/dist/server/app-page-render.d.ts +59 -0
- package/dist/server/app-page-render.js +174 -0
- package/dist/server/app-page-render.js.map +1 -0
- package/dist/server/app-page-request.d.ts +58 -0
- package/dist/server/app-page-request.js +79 -0
- package/dist/server/app-page-request.js.map +1 -0
- package/dist/server/app-page-response.d.ts +51 -0
- package/dist/server/app-page-response.js +90 -0
- package/dist/server/app-page-response.js.map +1 -0
- package/dist/server/app-page-stream.d.ts +55 -0
- package/dist/server/app-page-stream.js +65 -0
- package/dist/server/app-page-stream.js.map +1 -0
- package/dist/server/app-route-handler-cache.d.ts +42 -0
- package/dist/server/app-route-handler-cache.js +69 -0
- package/dist/server/app-route-handler-cache.js.map +1 -0
- package/dist/server/app-route-handler-execution.d.ts +64 -0
- package/dist/server/app-route-handler-execution.js +100 -0
- package/dist/server/app-route-handler-execution.js.map +1 -0
- package/dist/server/app-route-handler-policy.d.ts +51 -0
- package/dist/server/app-route-handler-policy.js +57 -0
- package/dist/server/app-route-handler-policy.js.map +1 -0
- package/dist/server/app-route-handler-response.d.ts +26 -0
- package/dist/server/app-route-handler-response.js +61 -0
- package/dist/server/app-route-handler-response.js.map +1 -0
- package/dist/server/app-route-handler-runtime.d.ts +27 -0
- package/dist/server/app-route-handler-runtime.js +99 -0
- package/dist/server/app-route-handler-runtime.js.map +1 -0
- package/dist/server/app-ssr-entry.d.ts +19 -0
- package/dist/server/app-ssr-entry.js +105 -0
- package/dist/server/app-ssr-entry.js.map +1 -0
- package/dist/server/app-ssr-stream.d.ts +30 -0
- package/dist/server/app-ssr-stream.js +116 -0
- package/dist/server/app-ssr-stream.js.map +1 -0
- package/dist/server/prod-server.d.ts +13 -1
- package/dist/server/prod-server.js +113 -19
- package/dist/server/prod-server.js.map +1 -1
- package/dist/server/worker-utils.d.ts +0 -6
- package/dist/server/worker-utils.js +41 -5
- package/dist/server/worker-utils.js.map +1 -1
- package/dist/shims/error-boundary.js +1 -1
- package/dist/shims/font-google-base.js +1 -1
- package/dist/shims/font-google-base.js.map +1 -1
- package/dist/shims/font-google.d.ts +2 -3
- package/dist/shims/font-google.js +2 -3
- package/dist/shims/metadata.js +3 -3
- package/dist/shims/metadata.js.map +1 -1
- package/dist/shims/request-state-types.d.ts +2 -2
- package/dist/shims/unified-request-context.d.ts +1 -1
- package/package.json +1 -1
- package/dist/shims/font-google.generated.d.ts +0 -1929
- package/dist/shims/font-google.generated.js +0 -1929
- package/dist/shims/font-google.generated.js.map +0 -1
package/README.md
CHANGED
|
@@ -480,12 +480,13 @@ Every `next/*` import is shimmed to a Vite-compatible implementation.
|
|
|
480
480
|
|
|
481
481
|
### Configuration
|
|
482
482
|
|
|
483
|
-
| Feature | | Notes
|
|
484
|
-
| ------------------------------------------------ | --- |
|
|
485
|
-
| `next.config.js` / `.ts` / `.mjs` | ✅ | Function configs, phase argument
|
|
486
|
-
| `rewrites` / `redirects` / `headers` | ✅ | All phases, param interpolation
|
|
487
|
-
| Environment variables (`.env*`, `NEXT_PUBLIC_*`) | ✅ | Auto-loads Next.js-style dotenv files; only public vars are inlined
|
|
488
|
-
| `images` config | 🟡 | Parsed but not used for optimization
|
|
483
|
+
| Feature | | Notes |
|
|
484
|
+
| ------------------------------------------------ | --- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
485
|
+
| `next.config.js` / `.ts` / `.mjs` | ✅ | Function configs, phase argument |
|
|
486
|
+
| `rewrites` / `redirects` / `headers` | ✅ | All phases, param interpolation |
|
|
487
|
+
| Environment variables (`.env*`, `NEXT_PUBLIC_*`) | ✅ | Auto-loads Next.js-style dotenv files; only public vars are inlined |
|
|
488
|
+
| `images` config | 🟡 | Parsed but not used for optimization |
|
|
489
|
+
| `experimental.optimizePackageImports` | ✅ | Rewrites barrel imports to direct sub-module imports in RSC/SSR environments. A default set (lucide-react, date-fns, radix-ui, antd, MUI, and others) are always optimized. Add package names here to extend the list. |
|
|
489
490
|
|
|
490
491
|
### Environment variable loading (`.env*`)
|
|
491
492
|
|
|
@@ -161,6 +161,8 @@ interface ResolvedNextConfig {
|
|
|
161
161
|
allowedDevOrigins: string[];
|
|
162
162
|
/** Extra allowed origins for server action CSRF validation (from experimental.serverActions.allowedOrigins). */
|
|
163
163
|
serverActionsAllowedOrigins: string[];
|
|
164
|
+
/** Packages whose barrel imports should be optimized (from experimental.optimizePackageImports). */
|
|
165
|
+
optimizePackageImports: string[];
|
|
164
166
|
/** Parsed body size limit for server actions in bytes (from experimental.serverActions.bodySizeLimit). Defaults to 1MB. */
|
|
165
167
|
serverActionsBodySizeLimit: number;
|
|
166
168
|
/**
|
|
@@ -180,6 +180,7 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
180
180
|
aliases: {},
|
|
181
181
|
allowedDevOrigins: [],
|
|
182
182
|
serverActionsAllowedOrigins: [],
|
|
183
|
+
optimizePackageImports: [],
|
|
183
184
|
serverActionsBodySizeLimit: 1 * 1024 * 1024,
|
|
184
185
|
serverExternalPackages: [],
|
|
185
186
|
buildId
|
|
@@ -231,6 +232,8 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
231
232
|
const serverActionsConfig = experimental?.serverActions;
|
|
232
233
|
const serverActionsAllowedOrigins = Array.isArray(serverActionsConfig?.allowedOrigins) ? serverActionsConfig.allowedOrigins : [];
|
|
233
234
|
const serverActionsBodySizeLimit = parseBodySizeLimit(serverActionsConfig?.bodySizeLimit);
|
|
235
|
+
const rawOptimize = experimental?.optimizePackageImports;
|
|
236
|
+
const optimizePackageImports = Array.isArray(rawOptimize) ? rawOptimize.filter((x) => typeof x === "string") : [];
|
|
234
237
|
const legacyServerComponentsExternal = experimental?.serverComponentsExternalPackages;
|
|
235
238
|
const serverExternalPackages = Array.isArray(config.serverExternalPackages) ? config.serverExternalPackages : Array.isArray(legacyServerComponentsExternal) ? legacyServerComponentsExternal : [];
|
|
236
239
|
if (config.webpack !== void 0) if (mdx || Object.keys(webpackProbe.aliases).length > 0) console.warn("[vinext] next.config option \"webpack\" is only partially supported. vinext preserves resolve.alias entries and MDX loader settings, but other webpack customization is ignored");
|
|
@@ -262,6 +265,7 @@ async function resolveNextConfig(config, root = process.cwd()) {
|
|
|
262
265
|
aliases,
|
|
263
266
|
allowedDevOrigins,
|
|
264
267
|
serverActionsAllowedOrigins,
|
|
268
|
+
optimizePackageImports,
|
|
265
269
|
serverActionsBodySizeLimit,
|
|
266
270
|
serverExternalPackages,
|
|
267
271
|
buildId
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next-config.js","names":[],"sources":["../../src/config/next-config.ts"],"sourcesContent":["/**\n * next.config.js / next.config.mjs / next.config.ts parser\n *\n * Loads the Next.js config file (if present) and extracts supported options.\n * Unsupported options are logged as warnings.\n */\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport fs from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport { PHASE_DEVELOPMENT_SERVER } from \"../shims/constants.js\";\nimport { normalizePageExtensions } from \"../routing/file-matcher.js\";\nimport { isExternalUrl } from \"./config-matchers.js\";\n\n/**\n * Parse a body size limit value (string or number) into bytes.\n * Accepts Next.js-style strings like \"1mb\", \"500kb\", \"10mb\", bare number strings like \"1048576\" (bytes),\n * and numeric values. Supports b, kb, mb, gb, tb, pb units.\n * Returns the default 1MB if the value is not provided or invalid.\n * Throws if the parsed value is less than 1.\n */\nexport function parseBodySizeLimit(value: string | number | undefined | null): number {\n if (value === undefined || value === null) return 1 * 1024 * 1024;\n if (typeof value === \"number\") {\n if (value < 1) throw new Error(`Body size limit must be a positive number, got ${value}`);\n return value;\n }\n const trimmed = value.trim();\n const match = trimmed.match(/^(\\d+(?:\\.\\d+)?)\\s*(b|kb|mb|gb|tb|pb)?$/i);\n if (!match) {\n console.warn(\n `[vinext] Invalid bodySizeLimit value: \"${value}\". Expected a number or a string like \"1mb\", \"500kb\". Falling back to 1MB.`,\n );\n return 1 * 1024 * 1024;\n }\n const num = parseFloat(match[1]);\n const unit = (match[2] ?? \"b\").toLowerCase();\n let bytes: number;\n switch (unit) {\n case \"b\":\n bytes = Math.floor(num);\n break;\n case \"kb\":\n bytes = Math.floor(num * 1024);\n break;\n case \"mb\":\n bytes = Math.floor(num * 1024 * 1024);\n break;\n case \"gb\":\n bytes = Math.floor(num * 1024 * 1024 * 1024);\n break;\n case \"tb\":\n bytes = Math.floor(num * 1024 * 1024 * 1024 * 1024);\n break;\n case \"pb\":\n bytes = Math.floor(num * 1024 * 1024 * 1024 * 1024 * 1024);\n break;\n default:\n return 1 * 1024 * 1024;\n }\n if (bytes < 1) throw new Error(`Body size limit must be a positive number, got ${bytes}`);\n return bytes;\n}\n\nexport interface HasCondition {\n type: \"header\" | \"cookie\" | \"query\" | \"host\";\n key: string;\n value?: string;\n}\n\nexport interface NextRedirect {\n source: string;\n destination: string;\n permanent: boolean;\n has?: HasCondition[];\n missing?: HasCondition[];\n}\n\nexport interface NextRewrite {\n source: string;\n destination: string;\n has?: HasCondition[];\n missing?: HasCondition[];\n}\n\nexport interface NextHeader {\n source: string;\n has?: HasCondition[];\n missing?: HasCondition[];\n headers: Array<{ key: string; value: string }>;\n}\n\nexport interface NextI18nConfig {\n /** List of supported locales */\n locales: string[];\n /** The default locale (used when no locale prefix is in the URL) */\n defaultLocale: string;\n /**\n * Whether to auto-detect locale from Accept-Language header.\n * Defaults to true in Next.js.\n */\n localeDetection?: boolean;\n /**\n * Domain-based routing. Each domain maps to a specific locale.\n */\n domains?: Array<{\n domain: string;\n defaultLocale: string;\n locales?: string[];\n http?: boolean;\n }>;\n}\n\n/**\n * MDX compilation options extracted from @next/mdx config.\n * These are passed through to @mdx-js/rollup so that custom\n * remark/rehype/recma plugins configured in next.config work with Vite.\n */\nexport interface MdxOptions {\n remarkPlugins?: unknown[];\n rehypePlugins?: unknown[];\n recmaPlugins?: unknown[];\n}\n\nexport interface NextConfig {\n /** Additional env variables */\n env?: Record<string, string>;\n /** Base URL path prefix */\n basePath?: string;\n /** Whether to add trailing slashes */\n trailingSlash?: boolean;\n /** Internationalization routing config */\n i18n?: NextI18nConfig;\n /** URL redirect rules */\n redirects?: () => Promise<NextRedirect[]> | NextRedirect[];\n /** URL rewrite rules */\n rewrites?: () =>\n | Promise<\n | NextRewrite[]\n | {\n beforeFiles: NextRewrite[];\n afterFiles: NextRewrite[];\n fallback: NextRewrite[];\n }\n >\n | NextRewrite[]\n | {\n beforeFiles: NextRewrite[];\n afterFiles: NextRewrite[];\n fallback: NextRewrite[];\n };\n /** Custom response headers */\n headers?: () => Promise<NextHeader[]> | NextHeader[];\n /** Image optimization config */\n images?: {\n remotePatterns?: Array<{\n protocol?: string;\n hostname: string;\n port?: string;\n pathname?: string;\n search?: string;\n }>;\n domains?: string[];\n unoptimized?: boolean;\n /** Allowed device widths for image optimization. Defaults to Next.js defaults: [640, 750, 828, 1080, 1200, 1920, 2048, 3840] */\n deviceSizes?: number[];\n /** Allowed image sizes for fixed-width images. Defaults to Next.js defaults: [16, 32, 48, 64, 96, 128, 256, 384] */\n imageSizes?: number[];\n /** Allow SVG images through the image optimization endpoint. SVG can contain scripts, so only enable if you trust all image sources. */\n dangerouslyAllowSVG?: boolean;\n /** Content-Disposition header for image responses. Defaults to \"inline\". */\n contentDispositionType?: \"inline\" | \"attachment\";\n /** Content-Security-Policy header for image responses. Defaults to \"script-src 'none'; frame-src 'none'; sandbox;\" */\n contentSecurityPolicy?: string;\n };\n /** Build output mode: 'export' for full static export, 'standalone' for single server */\n output?: \"export\" | \"standalone\";\n /** File extensions treated as routable pages/routes (Next.js pageExtensions) */\n pageExtensions?: string[];\n /** Extra origins allowed to access the dev server. */\n allowedDevOrigins?: string[];\n /**\n * Enable Cache Components (Next.js 16).\n * When true, enables the \"use cache\" directive for pages, components, and functions.\n * Replaces the removed experimental.ppr and experimental.dynamicIO flags.\n */\n cacheComponents?: boolean;\n /** Transpile packages (Vite handles this natively) */\n transpilePackages?: string[];\n /**\n * Packages that should be treated as server-external (not bundled by Vite).\n * Corresponds to Next.js `serverExternalPackages` (or the legacy\n * `experimental.serverComponentsExternalPackages`).\n */\n serverExternalPackages?: string[];\n /** Webpack config (ignored — we use Vite) */\n webpack?: unknown;\n /**\n * Custom build ID generator. If provided, called once at build/dev start.\n * Must return a non-empty string, or null to use the default random ID.\n */\n generateBuildId?: () => string | null | Promise<string | null>;\n /** Any other options */\n [key: string]: unknown;\n}\n\n/**\n * Resolved configuration with all async values awaited.\n */\nexport interface ResolvedNextConfig {\n env: Record<string, string>;\n basePath: string;\n trailingSlash: boolean;\n output: \"\" | \"export\" | \"standalone\";\n pageExtensions: string[];\n cacheComponents: boolean;\n redirects: NextRedirect[];\n rewrites: {\n beforeFiles: NextRewrite[];\n afterFiles: NextRewrite[];\n fallback: NextRewrite[];\n };\n headers: NextHeader[];\n images: NextConfig[\"images\"];\n i18n: NextI18nConfig | null;\n /** MDX remark/rehype/recma plugins extracted from @next/mdx config */\n mdx: MdxOptions | null;\n /** Explicit module aliases preserved from wrapped next.config plugins. */\n aliases: Record<string, string>;\n /** Extra allowed origins for dev server access (from allowedDevOrigins). */\n allowedDevOrigins: string[];\n /** Extra allowed origins for server action CSRF validation (from experimental.serverActions.allowedOrigins). */\n serverActionsAllowedOrigins: string[];\n /** Parsed body size limit for server actions in bytes (from experimental.serverActions.bodySizeLimit). Defaults to 1MB. */\n serverActionsBodySizeLimit: number;\n /**\n * Packages that should be treated as server-external (not bundled by Vite).\n * Sourced from `serverExternalPackages` or the legacy\n * `experimental.serverComponentsExternalPackages` in next.config.\n */\n serverExternalPackages: string[];\n /** Resolved build ID (from generateBuildId, or a random UUID if not provided). */\n buildId: string;\n}\n\nconst CONFIG_FILES = [\"next.config.ts\", \"next.config.mjs\", \"next.config.js\", \"next.config.cjs\"];\n\n/**\n * Check whether an error indicates a CJS module was loaded in an ESM context\n * (i.e. the file uses `require()` which is not available in ESM).\n */\nfunction isCjsError(e: unknown): boolean {\n if (!(e instanceof Error)) return false;\n const msg = e.message;\n return (\n msg.includes(\"require is not a function\") ||\n msg.includes(\"require is not defined\") ||\n msg.includes(\"exports is not defined\") ||\n msg.includes(\"module is not defined\") ||\n msg.includes(\"__dirname is not defined\") ||\n msg.includes(\"__filename is not defined\")\n );\n}\n\n/**\n * Emit a warning when config loading fails, with a targeted hint for\n * known plugin wrappers that are unnecessary in vinext.\n */\nfunction warnConfigLoadFailure(filename: string, err: Error): void {\n const msg = err.message ?? \"\";\n const stack = err.stack ?? \"\";\n const isNextIntlPlugin =\n msg.includes(\"next-intl\") ||\n stack.includes(\"next-intl/plugin\") ||\n stack.includes(\"next-intl/dist\");\n\n console.log();\n console.error(`[vinext] Failed to load ${filename}: ${msg}`);\n console.log();\n if (isNextIntlPlugin) {\n console.warn(\n \"[vinext] Hint: createNextIntlPlugin() is not needed with vinext. \" +\n \"Remove the next-intl/plugin wrapper from your next.config — \" +\n \"vinext auto-detects next-intl and registers the i18n config alias automatically.\",\n );\n }\n}\n\n/**\n * Unwrap the config value from a loaded module, calling it if it's a\n * function-form config (Next.js supports `module.exports = (phase, opts) => config`).\n */\nasync function unwrapConfig(\n mod: any,\n phase: string = PHASE_DEVELOPMENT_SERVER,\n): Promise<NextConfig> {\n const config = mod.default ?? mod;\n if (typeof config === \"function\") {\n const result = await config(phase, {\n defaultConfig: {},\n });\n return result as NextConfig;\n }\n return config as NextConfig;\n}\n\n/**\n * Find and load the next.config file from the project root.\n * Returns null if no config file is found.\n *\n * Attempts Vite's module runner first so TS configs and extensionless local\n * imports (e.g. `import \"./env\"`) resolve consistently. If loading fails due\n * to CJS constructs (`require`, `module.exports`), falls back to `createRequire`\n * so common CJS plugin wrappers (nextra, @next/mdx, etc.) still work.\n */\nexport async function loadNextConfig(\n root: string,\n phase: string = PHASE_DEVELOPMENT_SERVER,\n): Promise<NextConfig | null> {\n for (const filename of CONFIG_FILES) {\n const configPath = path.join(root, filename);\n if (!fs.existsSync(configPath)) continue;\n\n try {\n // Load config via Vite's module runner (TS + extensionless import support)\n const { runnerImport } = await import(\"vite\");\n const { module: mod } = await runnerImport(configPath, {\n root,\n logLevel: \"error\",\n clearScreen: false,\n });\n return await unwrapConfig(mod, phase);\n } catch (e) {\n // If the error indicates a CJS file loaded in ESM context, retry with\n // createRequire which provides a proper CommonJS environment.\n if (isCjsError(e) && (filename.endsWith(\".js\") || filename.endsWith(\".cjs\"))) {\n try {\n const require = createRequire(path.join(root, \"package.json\"));\n const mod = require(configPath);\n return await unwrapConfig({ default: mod }, phase);\n } catch (e2) {\n warnConfigLoadFailure(filename, e2 as Error);\n throw e2;\n }\n }\n\n warnConfigLoadFailure(filename, e as Error);\n throw e;\n }\n }\n\n return null;\n}\n\n/**\n * Generate a UUID that doesn't contain \"ad\" to avoid false-positive ad-blocker hits.\n * Mirrors Next.js's own nanoid retry loop.\n */\nfunction safeUUID(): string {\n let id = randomUUID();\n while (/ad/i.test(id)) id = randomUUID();\n return id;\n}\n\n/**\n * Call the user's generateBuildId function and validate its return value.\n * Follows Next.js semantics: null return falls back to a random UUID; any\n * other non-string throws. Leading/trailing whitespace is trimmed.\n *\n * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/generateBuildId\n */\nasync function resolveBuildId(\n generate: (() => string | null | Promise<string | null>) | undefined,\n): Promise<string> {\n if (!generate) return safeUUID();\n\n const result = await generate();\n\n if (result === null) return safeUUID();\n\n if (typeof result !== \"string\") {\n throw new Error(\n \"generateBuildId did not return a string. https://nextjs.org/docs/messages/generatebuildid-not-a-string\",\n );\n }\n\n const trimmed = result.trim();\n if (trimmed.length === 0) {\n throw new Error(\n \"generateBuildId returned an empty string. https://nextjs.org/docs/messages/generatebuildid-not-a-string\",\n );\n }\n\n return trimmed;\n}\n\n/**\n * Resolve a NextConfig into a fully-resolved ResolvedNextConfig.\n * Awaits async functions for redirects/rewrites/headers.\n */\nexport async function resolveNextConfig(\n config: NextConfig | null,\n root: string = process.cwd(),\n): Promise<ResolvedNextConfig> {\n if (!config) {\n const buildId = await resolveBuildId(undefined);\n const resolved: ResolvedNextConfig = {\n env: {},\n basePath: \"\",\n trailingSlash: false,\n output: \"\",\n pageExtensions: normalizePageExtensions(),\n cacheComponents: false,\n redirects: [],\n rewrites: { beforeFiles: [], afterFiles: [], fallback: [] },\n headers: [],\n images: undefined,\n i18n: null,\n mdx: null,\n aliases: {},\n allowedDevOrigins: [],\n serverActionsAllowedOrigins: [],\n serverActionsBodySizeLimit: 1 * 1024 * 1024,\n serverExternalPackages: [],\n buildId,\n };\n detectNextIntlConfig(root, resolved);\n return resolved;\n }\n\n // Resolve redirects\n let redirects: NextRedirect[] = [];\n if (config.redirects) {\n const result = await config.redirects();\n redirects = Array.isArray(result) ? result : [];\n }\n\n // Resolve rewrites\n let rewrites = {\n beforeFiles: [] as NextRewrite[],\n afterFiles: [] as NextRewrite[],\n fallback: [] as NextRewrite[],\n };\n if (config.rewrites) {\n const result = await config.rewrites();\n if (Array.isArray(result)) {\n rewrites.afterFiles = result;\n } else {\n rewrites = {\n beforeFiles: result.beforeFiles ?? [],\n afterFiles: result.afterFiles ?? [],\n fallback: result.fallback ?? [],\n };\n }\n }\n\n {\n const allRewrites = [...rewrites.beforeFiles, ...rewrites.afterFiles, ...rewrites.fallback];\n const externalRewrites = allRewrites.filter((rewrite) => isExternalUrl(rewrite.destination));\n\n if (externalRewrites.length > 0) {\n const noun = externalRewrites.length === 1 ? \"external rewrite\" : \"external rewrites\";\n const listing = externalRewrites\n .map((rewrite) => ` ${rewrite.source} → ${rewrite.destination}`)\n .join(\"\\n\");\n\n console.warn(\n `[vinext] Found ${externalRewrites.length} ${noun} that proxy requests to external origins:\\n` +\n `${listing}\\n` +\n `Request headers, including credential headers (cookie, authorization, proxy-authorization, x-api-key), ` +\n `are forwarded to the external origin to match Next.js behavior. ` +\n `If you do not want to forward credentials, use an API route or route handler where you control exactly which headers are sent.`,\n );\n }\n }\n\n // Resolve headers\n let headers: NextHeader[] = [];\n if (config.headers) {\n headers = await config.headers();\n }\n\n // Probe wrapped webpack config once so alias extraction and MDX extraction\n // observe the same mock environment.\n const webpackProbe = await probeWebpackConfig(config, root);\n const mdx = webpackProbe.mdx;\n const aliases = {\n ...extractTurboAliases(config, root),\n ...webpackProbe.aliases,\n };\n\n const allowedDevOrigins = Array.isArray(config.allowedDevOrigins) ? config.allowedDevOrigins : [];\n\n // Resolve serverActions.allowedOrigins and bodySizeLimit from experimental config\n const experimental = config.experimental as Record<string, unknown> | undefined;\n const serverActionsConfig = experimental?.serverActions as Record<string, unknown> | undefined;\n const serverActionsAllowedOrigins = Array.isArray(serverActionsConfig?.allowedOrigins)\n ? (serverActionsConfig.allowedOrigins as string[])\n : [];\n const serverActionsBodySizeLimit = parseBodySizeLimit(\n serverActionsConfig?.bodySizeLimit as string | number | undefined,\n );\n\n // Resolve serverExternalPackages — support the current top-level key and the\n // legacy experimental.serverComponentsExternalPackages name that Next.js still\n // accepts (it moved out of experimental in Next.js 14.2).\n const legacyServerComponentsExternal = experimental?.serverComponentsExternalPackages;\n const serverExternalPackages: string[] = Array.isArray(config.serverExternalPackages)\n ? (config.serverExternalPackages as string[])\n : Array.isArray(legacyServerComponentsExternal)\n ? (legacyServerComponentsExternal as string[])\n : [];\n\n // Warn about unsupported webpack usage. We preserve alias injection and\n // extract MDX settings, but all other webpack customization is still ignored.\n if (config.webpack !== undefined) {\n if (mdx || Object.keys(webpackProbe.aliases).length > 0) {\n console.warn(\n '[vinext] next.config option \"webpack\" is only partially supported. ' +\n \"vinext preserves resolve.alias entries and MDX loader settings, but other webpack customization is ignored\",\n );\n } else {\n console.warn(\n '[vinext] next.config option \"webpack\" is not yet supported and will be ignored',\n );\n }\n }\n\n const output = config.output ?? \"\";\n if (output && output !== \"export\" && output !== \"standalone\") {\n console.warn(`[vinext] Unknown output mode \"${output as string}\", ignoring`);\n }\n\n const pageExtensions = normalizePageExtensions(config.pageExtensions);\n\n // Parse i18n config\n let i18n: NextI18nConfig | null = null;\n if (config.i18n) {\n i18n = {\n locales: config.i18n.locales,\n defaultLocale: config.i18n.defaultLocale,\n localeDetection: config.i18n.localeDetection ?? true,\n domains: config.i18n.domains,\n };\n }\n\n const buildId = await resolveBuildId(\n config.generateBuildId as (() => string | null | Promise<string | null>) | undefined,\n );\n\n const resolved: ResolvedNextConfig = {\n env: config.env ?? {},\n basePath: config.basePath ?? \"\",\n trailingSlash: config.trailingSlash ?? false,\n output: output === \"export\" || output === \"standalone\" ? output : \"\",\n pageExtensions,\n cacheComponents: config.cacheComponents ?? false,\n redirects,\n rewrites,\n headers,\n images: config.images,\n i18n,\n mdx,\n aliases,\n allowedDevOrigins,\n serverActionsAllowedOrigins,\n serverActionsBodySizeLimit,\n serverExternalPackages,\n buildId,\n };\n\n // Auto-detect next-intl (lowest priority — explicit aliases from\n // webpack/turbopack already in `aliases` take precedence)\n detectNextIntlConfig(root, resolved);\n\n return resolved;\n}\n\nfunction normalizeAliasEntries(\n aliases: Record<string, unknown> | undefined,\n root: string,\n): Record<string, string> {\n if (!aliases) return {};\n\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(aliases)) {\n if (typeof value !== \"string\") continue;\n normalized[key] = path.isAbsolute(value) ? value : path.resolve(root, value);\n }\n return normalized;\n}\n\nfunction extractTurboAliases(config: NextConfig, root: string): Record<string, string> {\n const experimental = config.experimental as Record<string, unknown> | undefined;\n const experimentalTurbo = experimental?.turbo as Record<string, unknown> | undefined;\n const topLevelTurbopack = config.turbopack as Record<string, unknown> | undefined;\n\n return {\n ...normalizeAliasEntries(\n experimentalTurbo?.resolveAlias as Record<string, unknown> | undefined,\n root,\n ),\n ...normalizeAliasEntries(\n topLevelTurbopack?.resolveAlias as Record<string, unknown> | undefined,\n root,\n ),\n };\n}\n\nasync function probeWebpackConfig(\n config: NextConfig,\n root: string,\n): Promise<{ aliases: Record<string, string>; mdx: MdxOptions | null }> {\n if (typeof config.webpack !== \"function\") {\n return { aliases: {}, mdx: null };\n }\n\n const mockModuleRules: any[] = [];\n const mockConfig = {\n context: root,\n resolve: { alias: {} as Record<string, unknown> },\n module: { rules: mockModuleRules },\n plugins: [] as any[],\n };\n const mockOptions = {\n defaultLoaders: { babel: { loader: \"next-babel-loader\" } },\n isServer: false,\n dev: false,\n dir: root,\n };\n\n try {\n const result = await (config.webpack as Function)(mockConfig, mockOptions);\n const finalConfig = result ?? mockConfig;\n const rules: any[] = finalConfig.module?.rules ?? mockModuleRules;\n return {\n aliases: normalizeAliasEntries(finalConfig.resolve?.alias, root),\n mdx: extractMdxOptionsFromRules(rules),\n };\n } catch {\n return { aliases: {}, mdx: null };\n }\n}\n\n/**\n * Extract MDX compilation options (remark/rehype/recma plugins) from\n * a Next.js config that uses @next/mdx.\n *\n * @next/mdx wraps the config with a webpack function that injects an MDX\n * loader rule. The remark/rehype plugins are captured in that closure.\n * We probe the webpack function with a mock config to extract them.\n */\nexport async function extractMdxOptions(\n config: NextConfig,\n root: string = process.cwd(),\n): Promise<MdxOptions | null> {\n return (await probeWebpackConfig(config, root)).mdx;\n}\n\n/**\n * Probe file candidates relative to root. Returns the first one that exists,\n * or null if none match.\n */\nfunction probeFiles(root: string, candidates: string[]): string | null {\n for (const candidate of candidates) {\n const abs = path.resolve(root, candidate);\n if (fs.existsSync(abs)) return abs;\n }\n return null;\n}\n\nconst I18N_REQUEST_CANDIDATES = [\n \"i18n/request.ts\",\n \"i18n/request.tsx\",\n \"i18n/request.js\",\n \"i18n/request.jsx\",\n \"src/i18n/request.ts\",\n \"src/i18n/request.tsx\",\n \"src/i18n/request.js\",\n \"src/i18n/request.jsx\",\n];\n\n/**\n * Detect next-intl in the project and auto-register the `next-intl/config`\n * alias if needed.\n *\n * next-intl's `createNextIntlPlugin()` crashes in vinext because it calls\n * `require('next/package.json')` to check the Next.js version. Instead,\n * vinext detects next-intl and registers the alias automatically.\n *\n * Note: `require.resolve('next-intl')` walks up to parent `node_modules`\n * directories via standard Node module resolution. In a monorepo, next-intl\n * installed at the workspace root will trigger detection even if not listed\n * in the project's own package.json. This is acceptable since a workspace-root\n * install implies the user wants it available.\n *\n * Mutates `resolved.aliases` and `resolved.env` in place.\n */\nexport function detectNextIntlConfig(root: string, resolved: ResolvedNextConfig): void {\n // Explicit alias wins — user or plugin already set it\n if (resolved.aliases[\"next-intl/config\"]) return;\n\n // Check if next-intl is installed (use main entry — some packages\n // don't expose ./package.json in their exports map)\n const require = createRequire(path.join(root, \"package.json\"));\n try {\n require.resolve(\"next-intl\");\n } catch {\n return; // next-intl not installed\n }\n\n // Probe for the i18n request config file\n const configPath = probeFiles(root, I18N_REQUEST_CANDIDATES);\n if (!configPath) return;\n\n resolved.aliases[\"next-intl/config\"] = configPath;\n\n if (resolved.trailingSlash) {\n resolved.env._next_intl_trailing_slash = \"true\";\n }\n}\n\nfunction extractMdxOptionsFromRules(rules: any[]): MdxOptions | null {\n // Search through webpack rules for the MDX loader injected by @next/mdx\n for (const rule of rules) {\n const loaders = extractMdxLoaders(rule);\n if (loaders) return loaders;\n }\n return null;\n}\n\n/**\n * Recursively search a webpack rule (which may have nested `oneOf` arrays)\n * for an MDX loader and extract its remark/rehype/recma plugin options.\n */\nfunction extractMdxLoaders(rule: any): MdxOptions | null {\n if (!rule) return null;\n\n // Check `oneOf` arrays (Next.js uses these extensively)\n if (Array.isArray(rule.oneOf)) {\n for (const child of rule.oneOf) {\n const result = extractMdxLoaders(child);\n if (result) return result;\n }\n }\n\n // Check `use` array (loader chain)\n const use = Array.isArray(rule.use) ? rule.use : rule.use ? [rule.use] : [];\n for (const loader of use) {\n const loaderPath = typeof loader === \"string\" ? loader : loader?.loader;\n if (typeof loaderPath === \"string\" && isMdxLoader(loaderPath)) {\n const opts = typeof loader === \"object\" ? loader.options : {};\n return extractPluginsFromOptions(opts);\n }\n }\n\n // Check direct `loader` field\n if (typeof rule.loader === \"string\" && isMdxLoader(rule.loader)) {\n return extractPluginsFromOptions(rule.options);\n }\n\n return null;\n}\n\nfunction isMdxLoader(loaderPath: string): boolean {\n return (\n loaderPath.includes(\"mdx\") &&\n (loaderPath.includes(\"@next\") ||\n loaderPath.includes(\"@mdx-js\") ||\n loaderPath.includes(\"mdx-js-loader\") ||\n loaderPath.includes(\"next-mdx\"))\n );\n}\n\nfunction extractPluginsFromOptions(opts: any): MdxOptions | null {\n if (!opts || typeof opts !== \"object\") return null;\n\n const remarkPlugins = Array.isArray(opts.remarkPlugins) ? opts.remarkPlugins : undefined;\n const rehypePlugins = Array.isArray(opts.rehypePlugins) ? opts.rehypePlugins : undefined;\n const recmaPlugins = Array.isArray(opts.recmaPlugins) ? opts.recmaPlugins : undefined;\n\n // Only return if at least one plugin array is non-empty\n if (\n (remarkPlugins && remarkPlugins.length > 0) ||\n (rehypePlugins && rehypePlugins.length > 0) ||\n (recmaPlugins && recmaPlugins.length > 0)\n ) {\n return {\n ...(remarkPlugins && remarkPlugins.length > 0 ? { remarkPlugins } : {}),\n ...(rehypePlugins && rehypePlugins.length > 0 ? { rehypePlugins } : {}),\n ...(recmaPlugins && recmaPlugins.length > 0 ? { recmaPlugins } : {}),\n };\n }\n\n return null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"next-config.js","names":[],"sources":["../../src/config/next-config.ts"],"sourcesContent":["/**\n * next.config.js / next.config.mjs / next.config.ts parser\n *\n * Loads the Next.js config file (if present) and extracts supported options.\n * Unsupported options are logged as warnings.\n */\nimport path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport fs from \"node:fs\";\nimport { randomUUID } from \"node:crypto\";\nimport { PHASE_DEVELOPMENT_SERVER } from \"../shims/constants.js\";\nimport { normalizePageExtensions } from \"../routing/file-matcher.js\";\nimport { isExternalUrl } from \"./config-matchers.js\";\n\n/**\n * Parse a body size limit value (string or number) into bytes.\n * Accepts Next.js-style strings like \"1mb\", \"500kb\", \"10mb\", bare number strings like \"1048576\" (bytes),\n * and numeric values. Supports b, kb, mb, gb, tb, pb units.\n * Returns the default 1MB if the value is not provided or invalid.\n * Throws if the parsed value is less than 1.\n */\nexport function parseBodySizeLimit(value: string | number | undefined | null): number {\n if (value === undefined || value === null) return 1 * 1024 * 1024;\n if (typeof value === \"number\") {\n if (value < 1) throw new Error(`Body size limit must be a positive number, got ${value}`);\n return value;\n }\n const trimmed = value.trim();\n const match = trimmed.match(/^(\\d+(?:\\.\\d+)?)\\s*(b|kb|mb|gb|tb|pb)?$/i);\n if (!match) {\n console.warn(\n `[vinext] Invalid bodySizeLimit value: \"${value}\". Expected a number or a string like \"1mb\", \"500kb\". Falling back to 1MB.`,\n );\n return 1 * 1024 * 1024;\n }\n const num = parseFloat(match[1]);\n const unit = (match[2] ?? \"b\").toLowerCase();\n let bytes: number;\n switch (unit) {\n case \"b\":\n bytes = Math.floor(num);\n break;\n case \"kb\":\n bytes = Math.floor(num * 1024);\n break;\n case \"mb\":\n bytes = Math.floor(num * 1024 * 1024);\n break;\n case \"gb\":\n bytes = Math.floor(num * 1024 * 1024 * 1024);\n break;\n case \"tb\":\n bytes = Math.floor(num * 1024 * 1024 * 1024 * 1024);\n break;\n case \"pb\":\n bytes = Math.floor(num * 1024 * 1024 * 1024 * 1024 * 1024);\n break;\n default:\n return 1 * 1024 * 1024;\n }\n if (bytes < 1) throw new Error(`Body size limit must be a positive number, got ${bytes}`);\n return bytes;\n}\n\nexport interface HasCondition {\n type: \"header\" | \"cookie\" | \"query\" | \"host\";\n key: string;\n value?: string;\n}\n\nexport interface NextRedirect {\n source: string;\n destination: string;\n permanent: boolean;\n has?: HasCondition[];\n missing?: HasCondition[];\n}\n\nexport interface NextRewrite {\n source: string;\n destination: string;\n has?: HasCondition[];\n missing?: HasCondition[];\n}\n\nexport interface NextHeader {\n source: string;\n has?: HasCondition[];\n missing?: HasCondition[];\n headers: Array<{ key: string; value: string }>;\n}\n\nexport interface NextI18nConfig {\n /** List of supported locales */\n locales: string[];\n /** The default locale (used when no locale prefix is in the URL) */\n defaultLocale: string;\n /**\n * Whether to auto-detect locale from Accept-Language header.\n * Defaults to true in Next.js.\n */\n localeDetection?: boolean;\n /**\n * Domain-based routing. Each domain maps to a specific locale.\n */\n domains?: Array<{\n domain: string;\n defaultLocale: string;\n locales?: string[];\n http?: boolean;\n }>;\n}\n\n/**\n * MDX compilation options extracted from @next/mdx config.\n * These are passed through to @mdx-js/rollup so that custom\n * remark/rehype/recma plugins configured in next.config work with Vite.\n */\nexport interface MdxOptions {\n remarkPlugins?: unknown[];\n rehypePlugins?: unknown[];\n recmaPlugins?: unknown[];\n}\n\nexport interface NextConfig {\n /** Additional env variables */\n env?: Record<string, string>;\n /** Base URL path prefix */\n basePath?: string;\n /** Whether to add trailing slashes */\n trailingSlash?: boolean;\n /** Internationalization routing config */\n i18n?: NextI18nConfig;\n /** URL redirect rules */\n redirects?: () => Promise<NextRedirect[]> | NextRedirect[];\n /** URL rewrite rules */\n rewrites?: () =>\n | Promise<\n | NextRewrite[]\n | {\n beforeFiles: NextRewrite[];\n afterFiles: NextRewrite[];\n fallback: NextRewrite[];\n }\n >\n | NextRewrite[]\n | {\n beforeFiles: NextRewrite[];\n afterFiles: NextRewrite[];\n fallback: NextRewrite[];\n };\n /** Custom response headers */\n headers?: () => Promise<NextHeader[]> | NextHeader[];\n /** Image optimization config */\n images?: {\n remotePatterns?: Array<{\n protocol?: string;\n hostname: string;\n port?: string;\n pathname?: string;\n search?: string;\n }>;\n domains?: string[];\n unoptimized?: boolean;\n /** Allowed device widths for image optimization. Defaults to Next.js defaults: [640, 750, 828, 1080, 1200, 1920, 2048, 3840] */\n deviceSizes?: number[];\n /** Allowed image sizes for fixed-width images. Defaults to Next.js defaults: [16, 32, 48, 64, 96, 128, 256, 384] */\n imageSizes?: number[];\n /** Allow SVG images through the image optimization endpoint. SVG can contain scripts, so only enable if you trust all image sources. */\n dangerouslyAllowSVG?: boolean;\n /** Content-Disposition header for image responses. Defaults to \"inline\". */\n contentDispositionType?: \"inline\" | \"attachment\";\n /** Content-Security-Policy header for image responses. Defaults to \"script-src 'none'; frame-src 'none'; sandbox;\" */\n contentSecurityPolicy?: string;\n };\n /** Build output mode: 'export' for full static export, 'standalone' for single server */\n output?: \"export\" | \"standalone\";\n /** File extensions treated as routable pages/routes (Next.js pageExtensions) */\n pageExtensions?: string[];\n /** Extra origins allowed to access the dev server. */\n allowedDevOrigins?: string[];\n /**\n * Enable Cache Components (Next.js 16).\n * When true, enables the \"use cache\" directive for pages, components, and functions.\n * Replaces the removed experimental.ppr and experimental.dynamicIO flags.\n */\n cacheComponents?: boolean;\n /** Transpile packages (Vite handles this natively) */\n transpilePackages?: string[];\n /**\n * Packages that should be treated as server-external (not bundled by Vite).\n * Corresponds to Next.js `serverExternalPackages` (or the legacy\n * `experimental.serverComponentsExternalPackages`).\n */\n serverExternalPackages?: string[];\n /** Webpack config (ignored — we use Vite) */\n webpack?: unknown;\n /**\n * Custom build ID generator. If provided, called once at build/dev start.\n * Must return a non-empty string, or null to use the default random ID.\n */\n generateBuildId?: () => string | null | Promise<string | null>;\n /** Any other options */\n [key: string]: unknown;\n}\n\n/**\n * Resolved configuration with all async values awaited.\n */\nexport interface ResolvedNextConfig {\n env: Record<string, string>;\n basePath: string;\n trailingSlash: boolean;\n output: \"\" | \"export\" | \"standalone\";\n pageExtensions: string[];\n cacheComponents: boolean;\n redirects: NextRedirect[];\n rewrites: {\n beforeFiles: NextRewrite[];\n afterFiles: NextRewrite[];\n fallback: NextRewrite[];\n };\n headers: NextHeader[];\n images: NextConfig[\"images\"];\n i18n: NextI18nConfig | null;\n /** MDX remark/rehype/recma plugins extracted from @next/mdx config */\n mdx: MdxOptions | null;\n /** Explicit module aliases preserved from wrapped next.config plugins. */\n aliases: Record<string, string>;\n /** Extra allowed origins for dev server access (from allowedDevOrigins). */\n allowedDevOrigins: string[];\n /** Extra allowed origins for server action CSRF validation (from experimental.serverActions.allowedOrigins). */\n serverActionsAllowedOrigins: string[];\n /** Packages whose barrel imports should be optimized (from experimental.optimizePackageImports). */\n optimizePackageImports: string[];\n /** Parsed body size limit for server actions in bytes (from experimental.serverActions.bodySizeLimit). Defaults to 1MB. */\n serverActionsBodySizeLimit: number;\n /**\n * Packages that should be treated as server-external (not bundled by Vite).\n * Sourced from `serverExternalPackages` or the legacy\n * `experimental.serverComponentsExternalPackages` in next.config.\n */\n serverExternalPackages: string[];\n /** Resolved build ID (from generateBuildId, or a random UUID if not provided). */\n buildId: string;\n}\n\nconst CONFIG_FILES = [\"next.config.ts\", \"next.config.mjs\", \"next.config.js\", \"next.config.cjs\"];\n\n/**\n * Check whether an error indicates a CJS module was loaded in an ESM context\n * (i.e. the file uses `require()` which is not available in ESM).\n */\nfunction isCjsError(e: unknown): boolean {\n if (!(e instanceof Error)) return false;\n const msg = e.message;\n return (\n msg.includes(\"require is not a function\") ||\n msg.includes(\"require is not defined\") ||\n msg.includes(\"exports is not defined\") ||\n msg.includes(\"module is not defined\") ||\n msg.includes(\"__dirname is not defined\") ||\n msg.includes(\"__filename is not defined\")\n );\n}\n\n/**\n * Emit a warning when config loading fails, with a targeted hint for\n * known plugin wrappers that are unnecessary in vinext.\n */\nfunction warnConfigLoadFailure(filename: string, err: Error): void {\n const msg = err.message ?? \"\";\n const stack = err.stack ?? \"\";\n const isNextIntlPlugin =\n msg.includes(\"next-intl\") ||\n stack.includes(\"next-intl/plugin\") ||\n stack.includes(\"next-intl/dist\");\n\n console.log();\n console.error(`[vinext] Failed to load ${filename}: ${msg}`);\n console.log();\n if (isNextIntlPlugin) {\n console.warn(\n \"[vinext] Hint: createNextIntlPlugin() is not needed with vinext. \" +\n \"Remove the next-intl/plugin wrapper from your next.config — \" +\n \"vinext auto-detects next-intl and registers the i18n config alias automatically.\",\n );\n }\n}\n\n/**\n * Unwrap the config value from a loaded module, calling it if it's a\n * function-form config (Next.js supports `module.exports = (phase, opts) => config`).\n */\nasync function unwrapConfig(\n mod: any,\n phase: string = PHASE_DEVELOPMENT_SERVER,\n): Promise<NextConfig> {\n const config = mod.default ?? mod;\n if (typeof config === \"function\") {\n const result = await config(phase, {\n defaultConfig: {},\n });\n return result as NextConfig;\n }\n return config as NextConfig;\n}\n\n/**\n * Find and load the next.config file from the project root.\n * Returns null if no config file is found.\n *\n * Attempts Vite's module runner first so TS configs and extensionless local\n * imports (e.g. `import \"./env\"`) resolve consistently. If loading fails due\n * to CJS constructs (`require`, `module.exports`), falls back to `createRequire`\n * so common CJS plugin wrappers (nextra, @next/mdx, etc.) still work.\n */\nexport async function loadNextConfig(\n root: string,\n phase: string = PHASE_DEVELOPMENT_SERVER,\n): Promise<NextConfig | null> {\n for (const filename of CONFIG_FILES) {\n const configPath = path.join(root, filename);\n if (!fs.existsSync(configPath)) continue;\n\n try {\n // Load config via Vite's module runner (TS + extensionless import support)\n const { runnerImport } = await import(\"vite\");\n const { module: mod } = await runnerImport(configPath, {\n root,\n logLevel: \"error\",\n clearScreen: false,\n });\n return await unwrapConfig(mod, phase);\n } catch (e) {\n // If the error indicates a CJS file loaded in ESM context, retry with\n // createRequire which provides a proper CommonJS environment.\n if (isCjsError(e) && (filename.endsWith(\".js\") || filename.endsWith(\".cjs\"))) {\n try {\n const require = createRequire(path.join(root, \"package.json\"));\n const mod = require(configPath);\n return await unwrapConfig({ default: mod }, phase);\n } catch (e2) {\n warnConfigLoadFailure(filename, e2 as Error);\n throw e2;\n }\n }\n\n warnConfigLoadFailure(filename, e as Error);\n throw e;\n }\n }\n\n return null;\n}\n\n/**\n * Generate a UUID that doesn't contain \"ad\" to avoid false-positive ad-blocker hits.\n * Mirrors Next.js's own nanoid retry loop.\n */\nfunction safeUUID(): string {\n let id = randomUUID();\n while (/ad/i.test(id)) id = randomUUID();\n return id;\n}\n\n/**\n * Call the user's generateBuildId function and validate its return value.\n * Follows Next.js semantics: null return falls back to a random UUID; any\n * other non-string throws. Leading/trailing whitespace is trimmed.\n *\n * @see https://nextjs.org/docs/app/api-reference/config/next-config-js/generateBuildId\n */\nasync function resolveBuildId(\n generate: (() => string | null | Promise<string | null>) | undefined,\n): Promise<string> {\n if (!generate) return safeUUID();\n\n const result = await generate();\n\n if (result === null) return safeUUID();\n\n if (typeof result !== \"string\") {\n throw new Error(\n \"generateBuildId did not return a string. https://nextjs.org/docs/messages/generatebuildid-not-a-string\",\n );\n }\n\n const trimmed = result.trim();\n if (trimmed.length === 0) {\n throw new Error(\n \"generateBuildId returned an empty string. https://nextjs.org/docs/messages/generatebuildid-not-a-string\",\n );\n }\n\n return trimmed;\n}\n\n/**\n * Resolve a NextConfig into a fully-resolved ResolvedNextConfig.\n * Awaits async functions for redirects/rewrites/headers.\n */\nexport async function resolveNextConfig(\n config: NextConfig | null,\n root: string = process.cwd(),\n): Promise<ResolvedNextConfig> {\n if (!config) {\n const buildId = await resolveBuildId(undefined);\n const resolved: ResolvedNextConfig = {\n env: {},\n basePath: \"\",\n trailingSlash: false,\n output: \"\",\n pageExtensions: normalizePageExtensions(),\n cacheComponents: false,\n redirects: [],\n rewrites: { beforeFiles: [], afterFiles: [], fallback: [] },\n headers: [],\n images: undefined,\n i18n: null,\n mdx: null,\n aliases: {},\n allowedDevOrigins: [],\n serverActionsAllowedOrigins: [],\n optimizePackageImports: [],\n serverActionsBodySizeLimit: 1 * 1024 * 1024,\n serverExternalPackages: [],\n buildId,\n };\n detectNextIntlConfig(root, resolved);\n return resolved;\n }\n\n // Resolve redirects\n let redirects: NextRedirect[] = [];\n if (config.redirects) {\n const result = await config.redirects();\n redirects = Array.isArray(result) ? result : [];\n }\n\n // Resolve rewrites\n let rewrites = {\n beforeFiles: [] as NextRewrite[],\n afterFiles: [] as NextRewrite[],\n fallback: [] as NextRewrite[],\n };\n if (config.rewrites) {\n const result = await config.rewrites();\n if (Array.isArray(result)) {\n rewrites.afterFiles = result;\n } else {\n rewrites = {\n beforeFiles: result.beforeFiles ?? [],\n afterFiles: result.afterFiles ?? [],\n fallback: result.fallback ?? [],\n };\n }\n }\n\n {\n const allRewrites = [...rewrites.beforeFiles, ...rewrites.afterFiles, ...rewrites.fallback];\n const externalRewrites = allRewrites.filter((rewrite) => isExternalUrl(rewrite.destination));\n\n if (externalRewrites.length > 0) {\n const noun = externalRewrites.length === 1 ? \"external rewrite\" : \"external rewrites\";\n const listing = externalRewrites\n .map((rewrite) => ` ${rewrite.source} → ${rewrite.destination}`)\n .join(\"\\n\");\n\n console.warn(\n `[vinext] Found ${externalRewrites.length} ${noun} that proxy requests to external origins:\\n` +\n `${listing}\\n` +\n `Request headers, including credential headers (cookie, authorization, proxy-authorization, x-api-key), ` +\n `are forwarded to the external origin to match Next.js behavior. ` +\n `If you do not want to forward credentials, use an API route or route handler where you control exactly which headers are sent.`,\n );\n }\n }\n\n // Resolve headers\n let headers: NextHeader[] = [];\n if (config.headers) {\n headers = await config.headers();\n }\n\n // Probe wrapped webpack config once so alias extraction and MDX extraction\n // observe the same mock environment.\n const webpackProbe = await probeWebpackConfig(config, root);\n const mdx = webpackProbe.mdx;\n const aliases = {\n ...extractTurboAliases(config, root),\n ...webpackProbe.aliases,\n };\n\n const allowedDevOrigins = Array.isArray(config.allowedDevOrigins) ? config.allowedDevOrigins : [];\n\n // Resolve serverActions.allowedOrigins and bodySizeLimit from experimental config\n const experimental = config.experimental as Record<string, unknown> | undefined;\n const serverActionsConfig = experimental?.serverActions as Record<string, unknown> | undefined;\n const serverActionsAllowedOrigins = Array.isArray(serverActionsConfig?.allowedOrigins)\n ? (serverActionsConfig.allowedOrigins as string[])\n : [];\n const serverActionsBodySizeLimit = parseBodySizeLimit(\n serverActionsConfig?.bodySizeLimit as string | number | undefined,\n );\n\n // Resolve optimizePackageImports from experimental config\n const rawOptimize = experimental?.optimizePackageImports;\n const optimizePackageImports = Array.isArray(rawOptimize)\n ? rawOptimize.filter((x): x is string => typeof x === \"string\")\n : [];\n\n // Resolve serverExternalPackages — support the current top-level key and the\n // legacy experimental.serverComponentsExternalPackages name that Next.js still\n // accepts (it moved out of experimental in Next.js 14.2).\n const legacyServerComponentsExternal = experimental?.serverComponentsExternalPackages;\n const serverExternalPackages: string[] = Array.isArray(config.serverExternalPackages)\n ? (config.serverExternalPackages as string[])\n : Array.isArray(legacyServerComponentsExternal)\n ? (legacyServerComponentsExternal as string[])\n : [];\n\n // Warn about unsupported webpack usage. We preserve alias injection and\n // extract MDX settings, but all other webpack customization is still ignored.\n if (config.webpack !== undefined) {\n if (mdx || Object.keys(webpackProbe.aliases).length > 0) {\n console.warn(\n '[vinext] next.config option \"webpack\" is only partially supported. ' +\n \"vinext preserves resolve.alias entries and MDX loader settings, but other webpack customization is ignored\",\n );\n } else {\n console.warn(\n '[vinext] next.config option \"webpack\" is not yet supported and will be ignored',\n );\n }\n }\n\n const output = config.output ?? \"\";\n if (output && output !== \"export\" && output !== \"standalone\") {\n console.warn(`[vinext] Unknown output mode \"${output as string}\", ignoring`);\n }\n\n const pageExtensions = normalizePageExtensions(config.pageExtensions);\n\n // Parse i18n config\n let i18n: NextI18nConfig | null = null;\n if (config.i18n) {\n i18n = {\n locales: config.i18n.locales,\n defaultLocale: config.i18n.defaultLocale,\n localeDetection: config.i18n.localeDetection ?? true,\n domains: config.i18n.domains,\n };\n }\n\n const buildId = await resolveBuildId(\n config.generateBuildId as (() => string | null | Promise<string | null>) | undefined,\n );\n\n const resolved: ResolvedNextConfig = {\n env: config.env ?? {},\n basePath: config.basePath ?? \"\",\n trailingSlash: config.trailingSlash ?? false,\n output: output === \"export\" || output === \"standalone\" ? output : \"\",\n pageExtensions,\n cacheComponents: config.cacheComponents ?? false,\n redirects,\n rewrites,\n headers,\n images: config.images,\n i18n,\n mdx,\n aliases,\n allowedDevOrigins,\n serverActionsAllowedOrigins,\n optimizePackageImports,\n serverActionsBodySizeLimit,\n serverExternalPackages,\n buildId,\n };\n\n // Auto-detect next-intl (lowest priority — explicit aliases from\n // webpack/turbopack already in `aliases` take precedence)\n detectNextIntlConfig(root, resolved);\n\n return resolved;\n}\n\nfunction normalizeAliasEntries(\n aliases: Record<string, unknown> | undefined,\n root: string,\n): Record<string, string> {\n if (!aliases) return {};\n\n const normalized: Record<string, string> = {};\n for (const [key, value] of Object.entries(aliases)) {\n if (typeof value !== \"string\") continue;\n normalized[key] = path.isAbsolute(value) ? value : path.resolve(root, value);\n }\n return normalized;\n}\n\nfunction extractTurboAliases(config: NextConfig, root: string): Record<string, string> {\n const experimental = config.experimental as Record<string, unknown> | undefined;\n const experimentalTurbo = experimental?.turbo as Record<string, unknown> | undefined;\n const topLevelTurbopack = config.turbopack as Record<string, unknown> | undefined;\n\n return {\n ...normalizeAliasEntries(\n experimentalTurbo?.resolveAlias as Record<string, unknown> | undefined,\n root,\n ),\n ...normalizeAliasEntries(\n topLevelTurbopack?.resolveAlias as Record<string, unknown> | undefined,\n root,\n ),\n };\n}\n\nasync function probeWebpackConfig(\n config: NextConfig,\n root: string,\n): Promise<{ aliases: Record<string, string>; mdx: MdxOptions | null }> {\n if (typeof config.webpack !== \"function\") {\n return { aliases: {}, mdx: null };\n }\n\n const mockModuleRules: any[] = [];\n const mockConfig = {\n context: root,\n resolve: { alias: {} as Record<string, unknown> },\n module: { rules: mockModuleRules },\n plugins: [] as any[],\n };\n const mockOptions = {\n defaultLoaders: { babel: { loader: \"next-babel-loader\" } },\n isServer: false,\n dev: false,\n dir: root,\n };\n\n try {\n const result = await (config.webpack as Function)(mockConfig, mockOptions);\n const finalConfig = result ?? mockConfig;\n const rules: any[] = finalConfig.module?.rules ?? mockModuleRules;\n return {\n aliases: normalizeAliasEntries(finalConfig.resolve?.alias, root),\n mdx: extractMdxOptionsFromRules(rules),\n };\n } catch {\n return { aliases: {}, mdx: null };\n }\n}\n\n/**\n * Extract MDX compilation options (remark/rehype/recma plugins) from\n * a Next.js config that uses @next/mdx.\n *\n * @next/mdx wraps the config with a webpack function that injects an MDX\n * loader rule. The remark/rehype plugins are captured in that closure.\n * We probe the webpack function with a mock config to extract them.\n */\nexport async function extractMdxOptions(\n config: NextConfig,\n root: string = process.cwd(),\n): Promise<MdxOptions | null> {\n return (await probeWebpackConfig(config, root)).mdx;\n}\n\n/**\n * Probe file candidates relative to root. Returns the first one that exists,\n * or null if none match.\n */\nfunction probeFiles(root: string, candidates: string[]): string | null {\n for (const candidate of candidates) {\n const abs = path.resolve(root, candidate);\n if (fs.existsSync(abs)) return abs;\n }\n return null;\n}\n\nconst I18N_REQUEST_CANDIDATES = [\n \"i18n/request.ts\",\n \"i18n/request.tsx\",\n \"i18n/request.js\",\n \"i18n/request.jsx\",\n \"src/i18n/request.ts\",\n \"src/i18n/request.tsx\",\n \"src/i18n/request.js\",\n \"src/i18n/request.jsx\",\n];\n\n/**\n * Detect next-intl in the project and auto-register the `next-intl/config`\n * alias if needed.\n *\n * next-intl's `createNextIntlPlugin()` crashes in vinext because it calls\n * `require('next/package.json')` to check the Next.js version. Instead,\n * vinext detects next-intl and registers the alias automatically.\n *\n * Note: `require.resolve('next-intl')` walks up to parent `node_modules`\n * directories via standard Node module resolution. In a monorepo, next-intl\n * installed at the workspace root will trigger detection even if not listed\n * in the project's own package.json. This is acceptable since a workspace-root\n * install implies the user wants it available.\n *\n * Mutates `resolved.aliases` and `resolved.env` in place.\n */\nexport function detectNextIntlConfig(root: string, resolved: ResolvedNextConfig): void {\n // Explicit alias wins — user or plugin already set it\n if (resolved.aliases[\"next-intl/config\"]) return;\n\n // Check if next-intl is installed (use main entry — some packages\n // don't expose ./package.json in their exports map)\n const require = createRequire(path.join(root, \"package.json\"));\n try {\n require.resolve(\"next-intl\");\n } catch {\n return; // next-intl not installed\n }\n\n // Probe for the i18n request config file\n const configPath = probeFiles(root, I18N_REQUEST_CANDIDATES);\n if (!configPath) return;\n\n resolved.aliases[\"next-intl/config\"] = configPath;\n\n if (resolved.trailingSlash) {\n resolved.env._next_intl_trailing_slash = \"true\";\n }\n}\n\nfunction extractMdxOptionsFromRules(rules: any[]): MdxOptions | null {\n // Search through webpack rules for the MDX loader injected by @next/mdx\n for (const rule of rules) {\n const loaders = extractMdxLoaders(rule);\n if (loaders) return loaders;\n }\n return null;\n}\n\n/**\n * Recursively search a webpack rule (which may have nested `oneOf` arrays)\n * for an MDX loader and extract its remark/rehype/recma plugin options.\n */\nfunction extractMdxLoaders(rule: any): MdxOptions | null {\n if (!rule) return null;\n\n // Check `oneOf` arrays (Next.js uses these extensively)\n if (Array.isArray(rule.oneOf)) {\n for (const child of rule.oneOf) {\n const result = extractMdxLoaders(child);\n if (result) return result;\n }\n }\n\n // Check `use` array (loader chain)\n const use = Array.isArray(rule.use) ? rule.use : rule.use ? [rule.use] : [];\n for (const loader of use) {\n const loaderPath = typeof loader === \"string\" ? loader : loader?.loader;\n if (typeof loaderPath === \"string\" && isMdxLoader(loaderPath)) {\n const opts = typeof loader === \"object\" ? loader.options : {};\n return extractPluginsFromOptions(opts);\n }\n }\n\n // Check direct `loader` field\n if (typeof rule.loader === \"string\" && isMdxLoader(rule.loader)) {\n return extractPluginsFromOptions(rule.options);\n }\n\n return null;\n}\n\nfunction isMdxLoader(loaderPath: string): boolean {\n return (\n loaderPath.includes(\"mdx\") &&\n (loaderPath.includes(\"@next\") ||\n loaderPath.includes(\"@mdx-js\") ||\n loaderPath.includes(\"mdx-js-loader\") ||\n loaderPath.includes(\"next-mdx\"))\n );\n}\n\nfunction extractPluginsFromOptions(opts: any): MdxOptions | null {\n if (!opts || typeof opts !== \"object\") return null;\n\n const remarkPlugins = Array.isArray(opts.remarkPlugins) ? opts.remarkPlugins : undefined;\n const rehypePlugins = Array.isArray(opts.rehypePlugins) ? opts.rehypePlugins : undefined;\n const recmaPlugins = Array.isArray(opts.recmaPlugins) ? opts.recmaPlugins : undefined;\n\n // Only return if at least one plugin array is non-empty\n if (\n (remarkPlugins && remarkPlugins.length > 0) ||\n (rehypePlugins && rehypePlugins.length > 0) ||\n (recmaPlugins && recmaPlugins.length > 0)\n ) {\n return {\n ...(remarkPlugins && remarkPlugins.length > 0 ? { remarkPlugins } : {}),\n ...(rehypePlugins && rehypePlugins.length > 0 ? { rehypePlugins } : {}),\n ...(recmaPlugins && recmaPlugins.length > 0 ? { recmaPlugins } : {}),\n };\n }\n\n return null;\n}\n"],"mappings":"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"}
|
package/dist/deploy.js
CHANGED
|
@@ -636,17 +636,34 @@ export default {
|
|
|
636
636
|
* Response headers take precedence over middleware headers for all headers
|
|
637
637
|
* except Set-Cookie, which is additive (both middleware and response cookies
|
|
638
638
|
* are preserved). Matches the behavior in prod-server.ts. Uses getSetCookie()
|
|
639
|
-
* to preserve multiple Set-Cookie values.
|
|
639
|
+
* to preserve multiple Set-Cookie values. Keep this in sync with
|
|
640
|
+
* prod-server.ts and server/worker-utils.ts.
|
|
640
641
|
*/
|
|
641
642
|
function mergeHeaders(
|
|
642
643
|
response: Response,
|
|
643
644
|
extraHeaders: Record<string, string | string[]>,
|
|
644
645
|
statusOverride?: number,
|
|
645
646
|
): Response {
|
|
646
|
-
|
|
647
|
+
const NO_BODY_RESPONSE_STATUSES = new Set([204, 205, 304]);
|
|
648
|
+
function isVinextStreamedHtmlResponse(response: Response): boolean {
|
|
649
|
+
return response.__vinextStreamedHtmlResponse === true;
|
|
650
|
+
}
|
|
651
|
+
function isContentLengthHeader(name: string): boolean {
|
|
652
|
+
return name.toLowerCase() === "content-length";
|
|
653
|
+
}
|
|
654
|
+
function cancelResponseBody(response: Response): void {
|
|
655
|
+
const body = response.body;
|
|
656
|
+
if (!body || body.locked) return;
|
|
657
|
+
void body.cancel().catch(() => {
|
|
658
|
+
/* ignore cancellation failures on discarded bodies */
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
const status = statusOverride ?? response.status;
|
|
647
663
|
const merged = new Headers();
|
|
648
664
|
// Middleware/config headers go in first (lower precedence)
|
|
649
665
|
for (const [k, v] of Object.entries(extraHeaders)) {
|
|
666
|
+
if (isContentLengthHeader(k)) continue;
|
|
650
667
|
if (Array.isArray(v)) {
|
|
651
668
|
for (const item of v) merged.append(k, item);
|
|
652
669
|
} else {
|
|
@@ -661,9 +678,40 @@ function mergeHeaders(
|
|
|
661
678
|
});
|
|
662
679
|
const responseCookies = response.headers.getSetCookie?.() ?? [];
|
|
663
680
|
for (const cookie of responseCookies) merged.append("set-cookie", cookie);
|
|
681
|
+
|
|
682
|
+
const shouldDropBody = NO_BODY_RESPONSE_STATUSES.has(status);
|
|
683
|
+
const shouldStripStreamLength =
|
|
684
|
+
isVinextStreamedHtmlResponse(response) && merged.has("content-length");
|
|
685
|
+
|
|
686
|
+
if (
|
|
687
|
+
!Object.keys(extraHeaders).some((key) => !isContentLengthHeader(key)) &&
|
|
688
|
+
statusOverride === undefined &&
|
|
689
|
+
!shouldDropBody &&
|
|
690
|
+
!shouldStripStreamLength
|
|
691
|
+
) {
|
|
692
|
+
return response;
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (shouldDropBody) {
|
|
696
|
+
cancelResponseBody(response);
|
|
697
|
+
merged.delete("content-encoding");
|
|
698
|
+
merged.delete("content-length");
|
|
699
|
+
merged.delete("content-type");
|
|
700
|
+
merged.delete("transfer-encoding");
|
|
701
|
+
return new Response(null, {
|
|
702
|
+
status,
|
|
703
|
+
statusText: status === response.status ? response.statusText : undefined,
|
|
704
|
+
headers: merged,
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if (shouldStripStreamLength) {
|
|
709
|
+
merged.delete("content-length");
|
|
710
|
+
}
|
|
711
|
+
|
|
664
712
|
return new Response(response.body, {
|
|
665
|
-
status
|
|
666
|
-
statusText: response.statusText,
|
|
713
|
+
status,
|
|
714
|
+
statusText: status === response.status ? response.statusText : undefined,
|
|
667
715
|
headers: merged,
|
|
668
716
|
});
|
|
669
717
|
}
|