-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Next.js: Remove next/config usage in Next.js >=v16 projects #32547
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -11,8 +11,10 @@ import type { StorybookConfigVite } from '@storybook/builder-vite'; | |||||||||||||||||||||||||||||||||||||||||||||||||||
| import { viteFinal as reactViteFinal } from '@storybook/react-vite/preset'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| import postCssLoadConfig from 'postcss-load-config'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import semver from 'semver'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { FrameworkOptions } from './types'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { getNextjsVersion } from './utils'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| const require = createRequire(import.meta.url); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -35,8 +37,20 @@ export const core: PresetProperty<'core'> = async (config, options) => { | |||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const previewAnnotations: PresetProperty<'previewAnnotations'> = (entry = []) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| const result = [...entry, fileURLToPath(import.meta.resolve('@storybook/nextjs-vite/preview'))]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| return result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| const annotations = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ...entry, | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| fileURLToPath(import.meta.resolve('@storybook/nextjs-vite/preview')), | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| const nextjsVersion = getNextjsVersion(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| const isNext16orNewer = semver.gte(nextjsVersion, '16.0.0'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| // TODO: Remove this once we only support Next.js v16 and above | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isNext16orNewer) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| annotations.push(fileURLToPath(import.meta.resolve('@storybook/nextjs-vite/config/preview'))); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+40
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Treat 16 prereleases (canary/rc) as >=16 when gating behavior. semver.gte('16.0.0-canary.1', '16.0.0') is false. You likely want canaries/RCs to opt into the v16 path. Apply this diff: - const nextjsVersion = getNextjsVersion();
- const isNext16orNewer = semver.gte(nextjsVersion, '16.0.0');
+ const nextjsVersion = getNextjsVersion();
+ const coerced = semver.coerce(nextjsVersion)?.version ?? nextjsVersion;
+ const isNext16orNewer = semver.gte(coerced, '16.0.0');📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| return annotations; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const optimizeViteDeps = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| import { readFileSync } from 'node:fs'; | ||
| import { join } from 'node:path'; | ||
|
|
||
| import { resolvePackageDir } from '../../../core/src/shared/utils/module'; | ||
|
|
||
| export const getNextjsVersion = (): string => | ||
| JSON.parse(readFileSync(join(resolvePackageDir('next'), 'package.json'), 'utf8')).version; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,9 +1,13 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| import { fileURLToPath } from 'node:url'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| import type { NextConfig } from 'next'; | ||||||||||||||||||||||||||||||||||||||||||||
| import semver from 'semver'; | ||||||||||||||||||||||||||||||||||||||||||||
| import type { Configuration as WebpackConfig } from 'webpack'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| import { addScopedAlias, resolveNextConfig } from '../utils'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { addScopedAlias, getNextjsVersion, resolveNextConfig } from '../utils'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const nextjsVersion = getNextjsVersion(); | ||||||||||||||||||||||||||||||||||||||||||||
| const isNext16orNewer = semver.gte(nextjsVersion, '16.0.0'); | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+4
to
+10
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid import-time Next version resolution; include canary prereleases in the check Reading the installed Next version at module import time can throw in environments where Next isn’t present (e.g., build/test of this package in isolation). Compute this lazily and be tolerant to absence. Also treat 16.0.0 prereleases (e.g., canary) as “>=16”. Apply this diff to make the check resilient and prerelease-aware: -const nextjsVersion = getNextjsVersion();
-const isNext16orNewer = semver.gte(nextjsVersion, '16.0.0');
+let isNext16orNewer = false;
+try {
+ const nextjsVersion = getNextjsVersion();
+ // Include prereleases like 16.0.0-canary.X as >= 16
+ isNext16orNewer = semver.satisfies(nextjsVersion, '>=16.0.0-0');
+} catch {
+ // If Next isn't resolvable (e.g., during isolated builds/tests), default to legacy behavior (<16)
+}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const tryResolve = (path: string) => { | ||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -22,7 +26,10 @@ export const configureConfig = async ({ | |||||||||||||||||||||||||||||||||||||||||||
| }): Promise<NextConfig> => { | ||||||||||||||||||||||||||||||||||||||||||||
| const nextConfig = await resolveNextConfig({ nextConfigPath }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| addScopedAlias(baseConfig, 'next/config'); | ||||||||||||||||||||||||||||||||||||||||||||
| // TODO: Remove this once we only support Next.js 16 and above | ||||||||||||||||||||||||||||||||||||||||||||
| if (!isNext16orNewer) { | ||||||||||||||||||||||||||||||||||||||||||||
| addScopedAlias(baseConfig, 'next/config'); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+29
to
+32
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVersion‑gate the next/config alias (LGTM) Conditionally aliasing next/config only for Next < 16 aligns with the upstream removal. Run this to ensure no unconditional imports of next/config remain elsewhere: 🏁 Script executed: #!/bin/bash
# Find any imports/requires of next/config and show context
rg -nP -C2 '(?:from\s+["'\'']next/config["'\'']|require\(\s*["'\'']next/config["'\'']\s*\))' \
--type=ts --type=tsx --type=js --type=jsx -g '!**/node_modules/**' codeLength of output: 27 🏁 Script executed: #!/bin/bash
set -euo pipefail
pattern="(?:from\s+['\"]next/config['\"]|require\\(\\s*['\"]next/config['\"]\\s*\\)|import\\(\\s*['\"]next/config['\"]\\s*\\))"
rg -nP -C2 "$pattern" \
-g 'code/**/*.ts' -g 'code/**/*.tsx' -g 'code/**/*.js' -g 'code/**/*.jsx' -g '!code/**/node_modules/**' -S || trueLength of output: 475 Unconditional imports of next/config remain — fix required Direct imports found at:
Gate these imports/use behind the Next <16 check (or convert to a dynamic require used only when Next <16) so runtime/builds on Next ≥16 don't reference the removed module, or make the webpack alias unconditional. |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // @ts-expect-error We know that alias is an object | ||||||||||||||||||||||||||||||||||||||||||||
| if (baseConfig.resolve?.alias?.['react-dom']) { | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -58,14 +65,17 @@ const setupRuntimeConfig = async ( | |||||||||||||||||||||||||||||||||||||||||||
| baseConfig: WebpackConfig, | ||||||||||||||||||||||||||||||||||||||||||||
| nextConfig: NextConfig | ||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<void> => { | ||||||||||||||||||||||||||||||||||||||||||||
| const definePluginConfig: Record<string, any> = { | ||||||||||||||||||||||||||||||||||||||||||||
| const definePluginConfig: Record<string, any> = {}; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| // TODO: Remove this once we only support Next.js 16 and above | ||||||||||||||||||||||||||||||||||||||||||||
| if (!isNext16orNewer) { | ||||||||||||||||||||||||||||||||||||||||||||
| // this mimics what nextjs does client side | ||||||||||||||||||||||||||||||||||||||||||||
| // https://github.com/vercel/next.js/blob/57702cb2a9a9dba4b552e0007c16449cf36cfb44/packages/next/client/index.tsx#L101 | ||||||||||||||||||||||||||||||||||||||||||||
| 'process.env.__NEXT_RUNTIME_CONFIG': JSON.stringify({ | ||||||||||||||||||||||||||||||||||||||||||||
| definePluginConfig['process.env.__NEXT_RUNTIME_CONFIG'] = JSON.stringify({ | ||||||||||||||||||||||||||||||||||||||||||||
| serverRuntimeConfig: {}, | ||||||||||||||||||||||||||||||||||||||||||||
| publicRuntimeConfig: nextConfig.publicRuntimeConfig, | ||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const newNextLinkBehavior = (nextConfig.experimental as any)?.newNextLinkBehavior; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.