-
-
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
Next.js: Remove next/config usage in Next.js >=v16 projects #32547
Conversation
WalkthroughAdded browser build entries in nextjs and nextjs-vite to export ./config/preview from ./src/config/preview.ts with dts disabled and exposed in package exports. Introduced getNextjsVersion utility to read the installed Next.js version. Preset logic in both frameworks always includes the Storybook Next.js preview annotation and conditionally includes the config/preview annotation when Next.js < 16. Webpack config for Next.js now only adds the next/config alias and runtime config DefinePlugin for Next.js < 16. Removed side-effect imports of ./config/preview from preview.tsx files. Sequence Diagram(s)sequenceDiagram
autonumber
participant Dev as Developer
participant Preset as Storybook Preset
participant Utils as getNextjsVersion
participant Ann as Annotation Builder
Dev->>Preset: Initialize preset
Preset->>Utils: Read installed Next.js version
Utils-->>Preset: version (e.g., 15.x / 16.x)
Preset->>Ann: Build annotations
Note right of Ann #DDEBF7: Always include @storybook/nextjs/preview
alt Next.js < 16.0.0
Ann->>Ann: Add @storybook/nextjs/config/preview
else Next.js >= 16.0.0
Ann->>Ann: Do not add extra config preview
end
Ann-->>Preset: Final annotations
Preset-->>Dev: Preset ready
sequenceDiagram
autonumber
participant Preset as Next.js Preset
participant Utils as getNextjsVersion
participant WP as Webpack Config
Preset->>Utils: Determine Next.js version
Utils-->>Preset: version
Preset->>WP: Initialize webpack config
alt Next.js < 16.0.0
WP->>WP: Add alias('next/config') and set runtime config via DefinePlugin
Note right of WP #FFF2CC: Legacy runtime behavior retained
else Next.js >= 16.0.0
WP->>WP: Skip alias and runtime config define
Note right of WP #E6F4EA: Behavior gated for 16+
end
WP-->>Preset: Final webpack config
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).Please share your feedback with us on this Discord post. Comment |
|
View your CI Pipeline Execution ↗ for commit c2f498a
☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
code/frameworks/nextjs/package.json (2)
82-116: Add dependency on @storybook/nextjs-vite (required by preset annotations).This package imports @storybook/nextjs-vite/preview and @storybook/nextjs-vite/config/preview at runtime. Without a declared dep, consumers installing only @storybook/nextjs will hit module resolution failures.
Apply this diff to add the dependency:
"dependencies": { "@babel/core": "^7.24.4", @@ "@storybook/builder-webpack5": "workspace:*", "@storybook/preset-react-webpack": "workspace:*", "@storybook/react": "workspace:*", + "@storybook/nextjs-vite": "workspace:*", "@types/semver": "^7.3.4",
129-131: Extend Next peer range to include v16.Code paths explicitly support Next.js 16+, but the peer range excludes it, causing npm/yarn peer warnings or installs to fail in strict setups.
Apply this diff:
- "next": "^14.1.0 || ^15.0.0", + "next": "^14.1.0 || ^15.0.0 || ^16.0.0",code/frameworks/nextjs-vite/package.json (2)
82-87: Declare semver as a runtime dependency.Used by src/preset.ts; relying on hoisting will break consumers.
Apply this diff:
"dependencies": { "@storybook/builder-vite": "workspace:*", "@storybook/react": "workspace:*", "@storybook/react-vite": "workspace:*", + "semver": "^7.3.5", "styled-jsx": "5.1.6", "vite-plugin-storybook-nextjs": "^2.0.7" },
95-100: Extend Next peer range to include v16.Aligns peer contract with new behavior and gating logic.
Apply this diff:
- "next": "^14.1.0 || ^15.0.0", + "next": "^14.1.0 || ^15.0.0 || ^16.0.0",
🧹 Nitpick comments (1)
code/frameworks/nextjs-vite/src/utils.ts (1)
6-7: Cache the Next.js version to avoid repeated sync fs reads.Minor optimization; avoids multiple disk hits in multi-call scenarios.
Apply this diff:
-export const getNextjsVersion = (): string => - JSON.parse(readFileSync(join(resolvePackageDir('next'), 'package.json'), 'utf8')).version; +let __cachedNextVersion: string | undefined; +export const getNextjsVersion = (): string => { + if (!__cachedNextVersion) { + __cachedNextVersion = JSON.parse( + readFileSync(join(resolvePackageDir('next'), 'package.json'), 'utf8') + ).version; + } + return __cachedNextVersion; +};
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
code/frameworks/nextjs-vite/build-config.ts(1 hunks)code/frameworks/nextjs-vite/package.json(1 hunks)code/frameworks/nextjs-vite/src/preset.ts(2 hunks)code/frameworks/nextjs-vite/src/preview.tsx(1 hunks)code/frameworks/nextjs-vite/src/utils.ts(1 hunks)code/frameworks/nextjs/build-config.ts(1 hunks)code/frameworks/nextjs/package.json(1 hunks)code/frameworks/nextjs/src/config/webpack.ts(3 hunks)code/frameworks/nextjs/src/preset.ts(1 hunks)code/frameworks/nextjs/src/preview.tsx(0 hunks)
💤 Files with no reviewable changes (1)
- code/frameworks/nextjs/src/preview.tsx
🧰 Additional context used
🧠 Learnings (6)
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Group related mocks together
Applied to files:
code/frameworks/nextjs-vite/package.jsoncode/frameworks/nextjs-vite/build-config.tscode/frameworks/nextjs/package.jsoncode/frameworks/nextjs/build-config.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Avoid mocking only a subset of required dependencies
Applied to files:
code/frameworks/nextjs-vite/package.jsoncode/frameworks/nextjs-vite/build-config.tscode/frameworks/nextjs/package.jsoncode/frameworks/nextjs/build-config.ts
📚 Learning: 2025-09-17T08:11:47.196Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.196Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Mock all required dependencies that the test subject uses
Applied to files:
code/frameworks/nextjs-vite/package.jsoncode/frameworks/nextjs-vite/build-config.tscode/frameworks/nextjs/build-config.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Document complex mock behaviors
Applied to files:
code/frameworks/nextjs-vite/package.jsoncode/frameworks/nextjs-vite/build-config.tscode/frameworks/nextjs/build-config.ts
📚 Learning: 2025-09-17T08:11:47.197Z
Learnt from: CR
PR: storybookjs/storybook#0
File: .cursor/rules/spy-mocking.mdc:0-0
Timestamp: 2025-09-17T08:11:47.197Z
Learning: Applies to **/*.test.{ts,tsx,js,jsx} : Keep mock implementations simple and focused
Applied to files:
code/frameworks/nextjs-vite/build-config.tscode/frameworks/nextjs/build-config.ts
📚 Learning: 2025-09-24T09:39:39.209Z
Learnt from: ndelangen
PR: storybookjs/storybook#32507
File: code/core/src/manager/globals/globals-module-info.ts:25-33
Timestamp: 2025-09-24T09:39:39.209Z
Learning: In Storybook, storybook/actions/decorator is a preview-only entrypoint and should not be included in manager globals configuration. The duplicatedKeys array in code/core/src/manager/globals/globals-module-info.ts is specifically for manager-side externalization, not preview entrypoints.
Applied to files:
code/frameworks/nextjs-vite/build-config.tscode/frameworks/nextjs-vite/src/preview.tsxcode/frameworks/nextjs/build-config.ts
🧬 Code graph analysis (4)
code/frameworks/nextjs-vite/src/utils.ts (1)
code/core/src/shared/utils/module.ts (1)
resolvePackageDir(27-32)
code/frameworks/nextjs-vite/src/preset.ts (1)
code/frameworks/nextjs-vite/src/utils.ts (1)
getNextjsVersion(6-7)
code/frameworks/nextjs/src/preset.ts (2)
code/frameworks/nextjs-vite/src/utils.ts (1)
getNextjsVersion(6-7)code/frameworks/nextjs/src/utils.ts (1)
getNextjsVersion(24-25)
code/frameworks/nextjs/src/config/webpack.ts (1)
code/frameworks/nextjs/src/utils.ts (2)
getNextjsVersion(24-25)addScopedAlias(71-75)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: normal
- GitHub Check: Danger JS
- GitHub Check: Core Unit Tests, windows-latest
🔇 Additional comments (7)
code/frameworks/nextjs/package.json (1)
38-38: Add export for ./config/preview — LGTMPublic export aligns with new build entry. No concerns.
code/frameworks/nextjs-vite/src/preview.tsx (1)
5-5: Removal of unused type and side-effect import — LGTMType import narrowed correctly; side-effect loading now handled via preset annotations.
Please confirm Next < 16 still loads @storybook/nextjs-vite/config/preview via the updated preset.
code/frameworks/nextjs-vite/build-config.ts (1)
14-18: New browser entry for ./config/preview — LGTMExport surface matches package exports; dts disabled as expected.
code/frameworks/nextjs-vite/package.json (1)
38-38: Add export for ./config/preview — LGTMMatches build entry; no types mapping expected (dts disabled).
code/frameworks/nextjs/build-config.ts (1)
14-18: New browser entry for ./config/preview — LGTMConsistent with added export; dts:false appropriate.
code/frameworks/nextjs/src/config/webpack.ts (2)
68-79: Guarded __NEXT_RUNTIME_CONFIG define (LGTM)Defining process.env.__NEXT_RUNTIME_CONFIG only for Next < 16 is correct and matches the intent to drop it on 16+.
4-4: Confirmed:semveris a runtime dependency for the package that ships this filecode/frameworks/nextjs/package.json lists dependencies.semver = ^7.3.5 — no change required.
| 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'))); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 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'))); | |
| } | |
| const annotations = [ | |
| ...entry, | |
| fileURLToPath(import.meta.resolve('@storybook/nextjs-vite/preview')), | |
| ]; | |
| const nextjsVersion = getNextjsVersion(); | |
| const coerced = semver.coerce(nextjsVersion)?.version ?? nextjsVersion; | |
| const isNext16orNewer = semver.gte(coerced, '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'))); | |
| } |
🤖 Prompt for AI Agents
In code/frameworks/nextjs-vite/src/preset.ts around lines 40 to 51, the semver
check treats prerelease Next.js versions (canary/rc) as older than 16.0.0;
change the gating to treat prereleases as >=16 by calling
semver.gte(nextjsVersion, '16.0.0', { includePrerelease: true }) when computing
isNext16orNewer so canary/rc versions opt into the v16 path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
| 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'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The 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
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 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'); | |
| import semver from 'semver'; | |
| import type { Configuration as WebpackConfig } from 'webpack'; | |
| import { addScopedAlias, getNextjsVersion, resolveNextConfig } from '../utils'; | |
| 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) | |
| } |
🤖 Prompt for AI Agents
In code/frameworks/nextjs/src/config/webpack.ts around lines 4 to 10, avoid
resolving the installed Next.js version at module import time and make the >=16
check tolerant to missing Next and prereleases: replace the top-level
nextjsVersion/isNext16orNewer constants with a small lazy helper (e.g., function
isNext16orNewer()) that calls getNextjsVersion() inside a try/catch, treats
missing or errored resolution as a safe low version (e.g., "0.0.0"), and uses
semver.gte(version, '16.0.0', { includePrerelease: true }) (or equivalent semver
API) to treat canary/prerelease versions as >=16; update any call sites to
invoke the helper instead of using the import-time boolean.
| // TODO: Remove this once we only support Next.js 16 and above | ||
| if (!isNext16orNewer) { | ||
| addScopedAlias(baseConfig, 'next/config'); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Version‑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:
- code/frameworks/nextjs/src/config/preview.ts
- code/frameworks/nextjs-vite/src/config/preview.ts
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.
code/frameworks/nextjs/src/preset.ts
Outdated
| const annotations = [ | ||
| ...entry, | ||
| fileURLToPath(import.meta.resolve('@storybook/nextjs-vite/preview')), | ||
| ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cross-package import requires dependency.
Using @storybook/nextjs-vite/preview from @storybook/nextjs means @storybook/nextjs must declare a dep on @storybook/nextjs-vite (not rely on monorepo hoisting).
Dependency addition is proposed in code/frameworks/nextjs/package.json.
🤖 Prompt for AI Agents
In code/frameworks/nextjs/src/preset.ts around lines 51 to 54, the file imports
'@storybook/nextjs-vite/preview' directly which requires that @storybook/nextjs
declare an explicit dependency on @storybook/nextjs-vite; update
code/frameworks/nextjs/package.json to add "@storybook/nextjs-vite" (with the
appropriate version or workspace spec) to dependencies (not devDependencies) so
the package no longer relies on monorepo hoisting, then run install and update
lockfile so the import resolves correctly.
| 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'))); | ||
| } | ||
|
|
||
| return annotations; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Missing import for getNextjsVersion and prerelease handling.
- getNextjsVersion is used but not imported — this will fail at runtime.
- Treat Next 16 prereleases as >=16.
Apply these diffs:
Add import near the other local imports:
+import { getNextjsVersion } from './utils';Improve the semver check:
- 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');🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Check: semver imported in nextjs-vite preset"
rg -nP "from ['\"]semver['\"]" code/frameworks/nextjs-vite/src/preset.ts || true
echo "Check: semver present in nextjs-vite/package.json dependencies"
rg -nP '"dependencies"\s*:\s*\{[\s\S]*"semver"' -n code/frameworks/nextjs-vite/package.json || true
echo "Check: nextjs preset references @storybook/nextjs-vite paths"
rg -nP "@storybook/nextjs-vite/(preview|config/preview)" code/frameworks/nextjs/src/preset.ts
echo "Check: @storybook/nextjs declares dep on @storybook/nextjs-vite"
rg -nP '"@storybook/nextjs-vite"\s*:\s*' code/frameworks/nextjs/package.json || true
echo "Check: getNextjsVersion imported in nextjs preset"
rg -nP 'import\s*\{\s*getNextjsVersion\s*\}\s*from\s*[\'"]./utils[\'"]' code/frameworks/nextjs/src/preset.ts || true
echo "Check: peer next range includes ^16 in both packages"
rg -nP '"next"\s*:\s*".*\^16' code/frameworks/nextjs/package.json code/frameworks/nextjs-vite/package.json || trueLength of output: 563
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "==== nextjs preset content ===="
sed -n '1,240p' code/frameworks/nextjs/src/preset.ts || true
echo
echo "==== search for getNextjsVersion occurrences (definition and imports) ===="
rg -n --hidden 'getNextjsVersion' || true
echo
echo "==== files exporting getNextjsVersion ===="
rg -n --hidden 'export .*getNextjsVersion|export function getNextjsVersion' || true
echo
echo "==== show candidate utils files under nextjs ===="
rg -n --hidden 'getNextjsVersion' code/frameworks/nextjs -S || true
echo
echo "==== semver import in nextjs preset ===="
rg -nP "from ['\"]semver['\"]" code/frameworks/nextjs/src/preset.ts || true
echo
echo "==== semver import in project ===="
rg -nP "from ['\"]semver['\"]" || true
echo
echo "==== show nextjs package.json ===="
sed -n '1,240p' code/frameworks/nextjs/package.json || true
echo
echo "==== show nextjs-vite package.json ===="
sed -n '1,240p' code/frameworks/nextjs-vite/package.json || trueLength of output: 21767
Add missing import and treat Next 16 prereleases as >=16
previewAnnotations calls getNextjsVersion but there is no static import — add the import and coerce prerelease versions before semver.gte so Next 16 prereleases count as >=16.
+import { getNextjsVersion } from './utils';- 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
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| 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'))); | |
| } | |
| return annotations; | |
| import { getNextjsVersion } from './utils'; | |
| const nextjsVersion = getNextjsVersion(); | |
| const coerced = semver.coerce(nextjsVersion)?.version ?? nextjsVersion; | |
| const isNext16orNewer = semver.gte(coerced, '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'))); | |
| } | |
| return annotations; |
🤖 Prompt for AI Agents
In code/frameworks/nextjs/src/preset.ts around lines 56 to 64, add a static
import for getNextjsVersion at the top of the file and normalize prerelease
Next.js versions before comparison so Next 16 prereleases count as >=16;
specifically, call getNextjsVersion(), coerce/normalize the returned version
(e.g. via semver.coerce or equivalent to strip prerelease metadata) and use that
normalized value with semver.gte(nextVersionNormalized, '16.0.0') when setting
isNext16orNewer, keeping the rest of the logic unchanged.
Package BenchmarksCommit: The following packages have significant changes to their size or dependencies:
|
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 18 | 18 | 0 |
| Self size | 2.07 MB | 2.06 MB | 🎉 -10 KB 🎉 |
| Dependency size | 9.44 MB | 9.43 MB | 🎉 -10 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/addon-vitest
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 6 | 6 | 0 |
| Self size | 501 KB | 491 KB | 🎉 -10 KB 🎉 |
| Dependency size | 1.53 MB | 1.53 MB | 0 B |
| Bundle Size Analyzer | Link | Link |
@storybook/builder-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 11 | 11 | 0 |
| Self size | 330 KB | 319 KB | 🎉 -10 KB 🎉 |
| Dependency size | 1.30 MB | 1.30 MB | 🚨 +18 B 🚨 |
| Bundle Size Analyzer | Link | Link |
@storybook/html-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 14 | 14 | 0 |
| Self size | 23 KB | 23 KB | 0 B |
| Dependency size | 1.67 MB | 1.66 MB | 🎉 -10 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/nextjs
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 531 | 531 | 0 |
| Self size | 950 KB | 940 KB | 🎉 -10 KB 🎉 |
| Dependency size | 58.43 MB | 58.41 MB | 🎉 -21 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/nextjs-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 124 | 124 | 0 |
| Self size | 4.01 MB | 4.09 MB | 🚨 +71 KB 🚨 |
| Dependency size | 21.62 MB | 21.59 MB | 🎉 -31 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/preact-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 14 | 14 | 0 |
| Self size | 14 KB | 14 KB | 🎉 -18 B 🎉 |
| Dependency size | 1.65 MB | 1.64 MB | 🎉 -10 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-native-web-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 157 | 157 | 0 |
| Self size | 31 KB | 31 KB | 🎉 -24 B 🎉 |
| Dependency size | 23.01 MB | 22.97 MB | 🎉 -31 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 114 | 114 | 0 |
| Self size | 37 KB | 37 KB | 🚨 +24 B 🚨 |
| Dependency size | 19.56 MB | 19.53 MB | 🎉 -31 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-webpack5
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 272 | 272 | 0 |
| Self size | 25 KB | 25 KB | 0 B |
| Dependency size | 43.35 MB | 43.33 MB | 🎉 -21 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/svelte-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 19 | 19 | 0 |
| Self size | 59 KB | 59 KB | 0 B |
| Dependency size | 26.79 MB | 26.78 MB | 🎉 -10 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/sveltekit
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 20 | 20 | 0 |
| Self size | 58 KB | 58 KB | 🚨 +30 B 🚨 |
| Dependency size | 26.85 MB | 26.84 MB | 🎉 -10 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/vue3-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 109 | 109 | 0 |
| Self size | 38 KB | 38 KB | 0 B |
| Dependency size | 43.78 MB | 43.77 MB | 🎉 -10 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/web-components-vite
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 15 | 15 | 0 |
| Self size | 20 KB | 20 KB | 🎉 -18 B 🎉 |
| Dependency size | 1.70 MB | 1.68 MB | 🎉 -10 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/cli
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 187 | 187 | 0 |
| Self size | 901 KB | 890 KB | 🎉 -11 KB 🎉 |
| Dependency size | 79.76 MB | 79.76 MB | 🎉 -660 B 🎉 |
| Bundle Size Analyzer | Link | Link |
@storybook/react-dom-shim
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 0 | 0 | 0 |
| Self size | 22 KB | 12 KB | 🎉 -10 KB 🎉 |
| Dependency size | 785 B | 785 B | 0 B |
| Bundle Size Analyzer | Link | Link |
@storybook/preset-create-react-app
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 68 | 68 | 0 |
| Self size | 36 KB | 26 KB | 🎉 -10 KB 🎉 |
| Dependency size | 5.97 MB | 5.97 MB | 0 B |
| Bundle Size Analyzer | Link | Link |
@storybook/react
| Before | After | Difference | |
|---|---|---|---|
| Dependency count | 2 | 2 | 0 |
| Self size | 894 KB | 884 KB | 🎉 -10 KB 🎉 |
| Dependency size | 28 KB | 18 KB | 🎉 -10 KB 🎉 |
| Bundle Size Analyzer | Link | Link |
…next-config-in-Next-v16 Next.js: Remove next/config usage in Next.js >=v16 projects (cherry picked from commit b81780a)
Closes #
What I did
I have removed the usage of
next/config(runtime config) in Next.js versions 16 and above.Related: https://github.com/vercel/next.js/pull/83944/files
Checklist for Contributors
Testing
The changes in this PR are covered in the following automated tests:
Manual testing
This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!
Documentation
MIGRATION.MD
Checklist for Maintainers
When this PR is ready for testing, make sure to add
ci:normal,ci:mergedorci:dailyGH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found incode/lib/cli-storybook/src/sandbox-templates.tsMake sure this PR contains one of the labels below:
Available labels
bug: Internal changes that fixes incorrect behavior.maintenance: User-facing maintenance tasks.dependencies: Upgrading (sometimes downgrading) dependencies.build: Internal-facing build tooling & test updates. Will not show up in release changelog.cleanup: Minor cleanup style change. Will not show up in release changelog.documentation: Documentation only changes. Will not show up in release changelog.feature request: Introducing a new feature.BREAKING CHANGE: Changes that break compatibility in some way with current major version.other: Changes that don't fit in the above categories.🦋 Canary release
This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the
@storybookjs/coreteam here.core team members can create a canary release here or locally with
gh workflow run --repo storybookjs/storybook canary-release-pr.yml --field pr=<PR_NUMBER>Summary by CodeRabbit
New Features
Refactor
Chores