next-upgrade
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseNext.js Upgrade Workflow
Next.js 升级工作流
Structured 9-step workflow for upgrading Next.js applications across major versions. Handles codemod automation, dependency updates, breaking change resolution, and validation.
用于跨主版本升级Next.js应用的9步结构化工作流,支持codemod自动化、依赖更新、破坏性变更解决以及验证功能。
When to Apply
适用场景
Use this skill when:
- Upgrading Next.js to a new major version (13, 14, 15, 16)
- Running codemods to automate breaking change migrations
- Resolving deprecation warnings in an existing Next.js project
- Planning an incremental migration path for large codebases
- Validating that an upgrade did not introduce regressions
当你有以下需求时可使用本工作流:
- 将Next.js升级到新的主版本(13、14、15、16)
- 运行codemod自动完成破坏性变更迁移
- 解决现有Next.js项目中的弃用警告
- 为大型代码库规划增量迁移路径
- 验证升级没有引入回归问题
9-Step Upgrade Workflow
9步升级工作流
Step 1: Detect Current Version
步骤1:检测当前版本
Identify the current Next.js version and target version.
bash
undefined确认当前的Next.js版本和目标升级版本。
bash
undefinedCheck current version
Check current version
cat package.json | grep '"next"'
cat package.json | grep '"next"'
Check Node.js version (Next.js 15+ requires Node 18.18+, Next.js 16 requires Node 20+)
Check Node.js version (Next.js 15+ requires Node 18.18+, Next.js 16 requires Node 20+)
node --version
**Version Requirements:**
| Next.js | Minimum Node.js | Minimum React |
| ------- | --------------- | ------------- |
| 13 | 16.14 | 18.2.0 |
| 14 | 18.17 | 18.2.0 |
| 15 | 18.18 | 19.0.0 |
| 16 | 20.0 | 19.0.0 |node --version
**版本要求:**
| Next.js | 最低Node.js版本 | 最低React版本 |
| ------- | --------------- | ------------- |
| 13 | 16.14 | 18.2.0 |
| 14 | 18.17 | 18.2.0 |
| 15 | 18.18 | 19.0.0 |
| 16 | 20.0 | 19.0.0 |Step 2: Create Upgrade Branch
步骤2:创建升级分支
bash
git checkout -b upgrade/nextjs-{target-version}Always upgrade on a dedicated branch. Never upgrade on main directly.
bash
git checkout -b upgrade/nextjs-{target-version}请始终在专属分支上执行升级操作,永远不要直接在main分支上升级。
Step 3: Run Codemods
步骤3:运行Codemods
Use the official Next.js codemod CLI to automate breaking change migrations.
bash
undefined使用官方Next.js codemod CLI自动完成破坏性变更迁移。
bash
undefinedInteractive mode (recommended) -- selects applicable codemods
Interactive mode (recommended) -- selects applicable codemods
npx @next/codemod@latest upgrade latest
npx @next/codemod@latest upgrade latest
Or target a specific version
Or target a specific version
npx @next/codemod@latest upgrade 15
npx @next/codemod@latest upgrade 16
**Key Codemods by Version:**npx @next/codemod@latest upgrade 15
npx @next/codemod@latest upgrade 16
**各版本核心Codemod:**Next.js 13 to 14
Next.js 13 到 14
- -- Renames
next-image-to-legacy-imageimports tonext/imagenext/legacy/image - -- Migrates from
next-image-experimentalto newnext/legacy/imagenext/image - -- Moves Head metadata to Metadata API exports
metadata
- -- 将
next-image-to-legacy-image导入重命名为next/imagenext/legacy/image - -- 从
next-image-experimental迁移到新的next/legacy/imagenext/image - -- 将Head元数据迁移到Metadata API导出
metadata
Next.js 14 to 15
Next.js 14 到 15
- -- Converts synchronous dynamic APIs (
next-async-request-apis,cookies(),headers(),params) to asyncsearchParams - -- Replaces
next-dynamic-ssr-falsewithssr: falsepattern for{ loading }next/dynamic - -- Moves OG image generation imports to
next-og-importnext/og
- -- 将同步动态API(
next-async-request-apis、cookies()、headers()、params)转换为异步形式searchParams - -- 将
next-dynamic-ssr-false的next/dynamic替换为ssr: false模式{ loading } - -- 将OG图片生成的导入路径迁移到
next-og-importnext/og
Next.js 15 to 16
Next.js 15 到 16
- -- Converts
next-use-cachetounstable_cachedirective'use cache' - -- Migrates cache revalidation to
next-cache-lifeAPIcacheLife() - -- Wraps
next-formelements with<form>where applicablenext/form
- -- 将
next-use-cache转换为unstable_cache指令'use cache' - -- 将缓存重验证逻辑迁移到
next-cache-lifeAPIcacheLife() - -- 在适用的场景下用
next-form包裹next/form元素<form>
Step 4: Update Dependencies
步骤4:更新依赖
bash
undefinedbash
undefinedUpdate Next.js and React together
Update Next.js and React together
npm install next@latest react@latest react-dom@latest
npm install next@latest react@latest react-dom@latest
For Next.js 15+, also update React types
For Next.js 15+, also update React types
npm install -D @types/react@latest @types/react-dom@latest
npm install -D @types/react@latest @types/react-dom@latest
Update eslint config
Update eslint config
npm install -D eslint-config-next@latest
**Peer Dependency Conflicts:**
If you encounter peer dependency conflicts:
1. Check which packages require older React/Next versions
2. Update those packages first, or check for newer versions
3. Use `--legacy-peer-deps` only as a last resort (document why)npm install -D eslint-config-next@latest
**Peer依赖冲突处理:**
如果遇到peer依赖冲突:
1. 检查哪些包依赖旧版本的React/Next
2. 先更新这些包,或者查找是否有可用的新版本
3. 仅作为最后手段使用`--legacy-peer-deps`(请记录使用原因)Step 5: Update Configuration
步骤5:更新配置
Review and update / :
next.config.jsnext.config.tsjavascript
// next.config.ts (Next.js 15+ recommends TypeScript config)
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
// Next.js 15+: experimental features that graduated
// Remove these from experimental:
// - serverActions (now stable in 14+)
// - appDir (now stable in 14+)
// - ppr (now stable in 16+)
// Next.js 16+: new cache configuration
cacheComponents: true, // Enable component-level caching
};
export default nextConfig;Configuration Changes by Version:
| Version | Change |
|---|---|
| 14 | |
| 14 | |
| 15 | |
| 15 | |
| 16 | |
| 16 | |
检查并更新 / :
next.config.jsnext.config.tsjavascript
// next.config.ts (Next.js 15+ recommends TypeScript config)
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
// Next.js 15+: experimental features that graduated
// Remove these from experimental:
// - serverActions (now stable in 14+)
// - appDir (now stable in 14+)
// - ppr (now stable in 16+)
// Next.js 16+: new cache configuration
cacheComponents: true, // Enable component-level caching
};
export default nextConfig;各版本配置变更:
| 版本 | 变更说明 |
|---|---|
| 14 | |
| 14 | |
| 15 | |
| 15 | 已移除 |
| 16 | |
| 16 | 配置 |
Step 6: Resolve Breaking Changes
步骤6:解决破坏性变更
After running codemods, manually resolve remaining breaking changes.
Common Breaking Changes (15 to 16):
-
Async Request APIs:,
cookies(),headers(),paramsare now asyncsearchParamstypescript// Before (Next.js 14) export default function Page({ params }: { params: { id: string } }) { const { id } = params; } // After (Next.js 15+) export default async function Page({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; } -
Caching Default Changed:requests are no longer cached by default in Next.js 15+
fetch()typescript// Before: cached by default fetch('https://api.example.com/data'); // After: explicitly opt-in to caching fetch('https://api.example.com/data', { cache: 'force-cache' }); // Or use 'use cache' directive in Next.js 16 -
Route Handlers: GET route handlers are no longer cached by defaulttypescript
// Next.js 15+: explicitly set caching export const dynamic = 'force-static';
运行codemod后,手动解决剩余的破坏性变更。
常见破坏性变更(15到16):
-
异步请求API:、
cookies()、headers()、params现在都是异步的searchParamstypescript// Before (Next.js 14) export default function Page({ params }: { params: { id: string } }) { const { id } = params; } // After (Next.js 15+) export default async function Page({ params }: { params: Promise<{ id: string }> }) { const { id } = await params; } -
缓存默认值变更:Next.js 15+中请求默认不再缓存
fetch()typescript// Before: cached by default fetch('https://api.example.com/data'); // After: explicitly opt-in to caching fetch('https://api.example.com/data', { cache: 'force-cache' }); // Or use 'use cache' directive in Next.js 16 -
路由处理器:GET路由处理器默认不再缓存typescript
// Next.js 15+: explicitly set caching export const dynamic = 'force-static';
Step 7: Run Tests
步骤7:运行测试
bash
undefinedbash
undefinedRun existing test suite
Run existing test suite
npm test
npm test
Run build to catch compile-time errors
Run build to catch compile-time errors
npm run build
npm run build
Run dev server and check key pages manually
Run dev server and check key pages manually
npm run dev
**Validation Checklist:**
- [ ] Build completes without errors
- [ ] All existing tests pass
- [ ] Key user flows work in dev mode
- [ ] No console warnings about deprecated APIs
- [ ] Server-side rendering works correctly
- [ ] Client-side navigation works correctly
- [ ] API routes return expected responses
- [ ] Middleware functions correctly
- [ ] Static generation (SSG) pages build correctlynpm run dev
**验证检查清单:**
- [ ] 构建无错误完成
- [ ] 所有现有测试通过
- [ ] 核心用户流程在开发模式下正常运行
- [ ] 控制台没有弃用API相关的警告
- [ ] 服务端渲染正常工作
- [ ] 客户端导航正常工作
- [ ] API路由返回预期响应
- [ ] 中间件功能正常
- [ ] 静态生成(SSG)页面构建正常Step 8: Update TypeScript Types
步骤8:更新TypeScript类型
bash
undefinedbash
undefinedRegenerate TypeScript declarations
Regenerate TypeScript declarations
npm run build
npm run build
Fix any new type errors
Fix any new type errors
npx tsc --noEmit
**Common Type Fixes:**
- `PageProps` type changes (params/searchParams become Promise in 15+)
- `Metadata` type updates (new fields added)
- `NextRequest`/`NextResponse` API changes
- Route handler parameter typesnpx tsc --noEmit
**常见类型修复:**
- `PageProps`类型变更(15+版本中params/searchParams变为Promise类型)
- `Metadata`类型更新(新增了字段)
- `NextRequest`/`NextResponse` API变更
- 路由处理器参数类型变更Step 9: Document and Commit
步骤9:记录并提交
bash
undefinedbash
undefinedCreate detailed commit
Create detailed commit
git add -A
git commit -m "chore: upgrade Next.js from {old} to {new}
Breaking changes resolved:
- [list specific changes]
Codemods applied:
- [list codemods run]
Manual fixes:
- [list manual changes]"
undefinedgit add -A
git commit -m "chore: upgrade Next.js from {old} to {new}
Breaking changes resolved:
- [list specific changes]
Codemods applied:
- [list codemods run]
Manual fixes:
- [list manual changes]"
undefinedIncremental Upgrade Path
增量迁移路径
For large version jumps (e.g., 13 to 16), upgrade incrementally:
Next.js 13 -> 14 -> 15 -> 16Why incremental?
- Codemods are version-specific and may not compose correctly across multiple versions
- Easier to debug issues when changes are smaller
- Each version has its own set of breaking changes to resolve
- Tests can validate each intermediate step
For each version step:
- Run codemods for that version
- Update deps
- Fix breaking changes
- Run tests
- Commit checkpoint
- Proceed to next version
对于跨多个大版本升级的场景(例如13到16),请采用增量升级方式:
Next.js 13 -> 14 -> 15 -> 16为什么要增量升级?
- Codemod是版本专属的,跨多个版本运行可能无法正常工作
- 变更范围更小,更容易调试问题
- 每个版本都有自己的一套破坏性变更需要解决
- 可以在每个中间步骤运行测试验证
每个版本升级步骤:
- 运行对应版本的codemod
- 更新依赖
- 修复破坏性变更
- 运行测试
- 提交检查点
- 继续升级下一个版本
Troubleshooting
故障排查
Build fails after upgrade
升级后构建失败
- Clear directory:
.nextrm -rf .next - Clear node_modules:
rm -rf node_modules && npm install - Clear Next.js cache:
rm -rf .next/cache
- 清除目录:
.nextrm -rf .next - 清除node_modules:
rm -rf node_modules && npm install - 清除Next.js缓存:
rm -rf .next/cache
Module not found errors
模块未找到错误
- Check if package was renamed or merged
- Update imports per migration guide
- Check if package needs separate update
- 检查对应包是否被重命名或合并
- 按照迁移指南更新导入路径
- 检查是否需要单独更新该包
Hydration mismatches after upgrade
升级后hydration不匹配
- Check for server/client rendering differences
- Ensure dynamic imports use correct options
- Verify date/locale handling is consistent
- 检查服务端/客户端渲染差异
- 确保动态导入使用了正确的配置项
- 验证日期/区域处理逻辑是一致的
Middleware issues
中间件问题
- Middleware API changed in Next.js 13 (moved to root)
- behavior changed in 15
NextResponse.rewrite() - Check matcher configuration syntax
- Next.js 13中中间件API变更(移动到根目录)
- Next.js 15中行为变更
NextResponse.rewrite() - 检查matcher配置语法
Iron Laws
铁律
- ALWAYS upgrade on a dedicated branch, never on main directly — upgrade branches can be rebased or reverted without disrupting production; direct main upgrades risk deploying half-migrated code.
- NEVER skip intermediate versions in a multi-version jump — Next.js codemods are version-specific and do not compose correctly across major versions; skipping steps leaves un-migrated breaking changes.
- ALWAYS run official codemods before making manual changes — codemods handle the bulk of mechanical migrations; manual-first approaches miss patterns and create divergence from the reference migration path.
- NEVER use without documenting the specific conflict and resolution plan — suppressing peer errors hides version conflicts that will cause runtime failures.
--legacy-peer-deps - ALWAYS validate with a full build plus test suite before merging — the dev server does not exercise SSG, edge runtime, or build optimizations that can fail silently post-upgrade.
- 永远在专属分支上升级,不要直接在main分支上操作——升级分支可以随时变基或回滚,不会影响生产环境;直接在main分支升级可能会部署未完成迁移的代码。
- 永远不要在多版本升级时跳过中间版本——Next.js的codemod是版本专属的,跨主版本无法正常工作;跳过步骤会遗留未迁移的破坏性变更。
- 永远在手动修改前先运行官方codemod——codemod可以处理大部分机械化的迁移工作;先手动修改会遗漏通用模式,导致和参考迁移路径不一致。
- 永远不要在没有记录具体冲突和解决方案的情况下使用——抑制peer依赖错误会隐藏版本冲突,最终导致运行时错误。
--legacy-peer-deps - 永远在合并前通过完整构建和测试套件验证——开发服务器不会运行SSG、边缘运行时、构建优化这些升级后可能静默失败的逻辑。
Anti-Patterns
反模式
| Anti-Pattern | Why It Fails | Correct Approach |
|---|---|---|
| Upgrading on the main branch directly | Half-migrated code can reach production; rollback requires a revert commit | Always create |
| Skipping intermediate versions | Version-specific codemods are not composable; skipped breaking changes cause runtime failures | Upgrade one major version at a time: 13→14→15→16; commit a checkpoint at each step |
| Manual migration before running codemods | Creates divergence from codemod output; codemods cannot merge cleanly with manual edits | Run codemods first; apply manual fixes only for patterns codemods could not handle |
Using | Hidden version conflicts cause runtime failures not visible at install time | Resolve conflicts explicitly; use the flag only with a documented justification |
| Validating only in dev mode | Dev server skips SSG, edge runtime, and build optimizations that can fail post-upgrade | Run |
| 反模式 | 失败原因 | 正确做法 |
|---|---|---|
| 直接在main分支上升级 | 未完成迁移的代码可能进入生产环境;回滚需要提交revert | 始终创建 |
| 跳过中间版本升级 | 版本专属的codemod无法组合使用;跳过的破坏性变更会导致运行时失败 | 每次仅升级一个主版本:13→14→15→16;每个步骤都提交检查点 |
| 运行codemod前先手动迁移 | 会导致和codemod输出不一致;codemod无法和手动修改干净合并 | 先运行codemod;仅对codemod无法处理的模式进行手动修复 |
未记录原因就使用 | 隐藏的版本冲突会导致安装时不可见的运行时错误 | 显式解决冲突;仅在有书面说明理由的情况下使用该flag |
| 仅在开发模式下验证 | 开发服务器会跳过SSG、边缘运行时、构建优化这些升级后可能失败的逻辑 | 运行 |