跳到主要内容

Next.js 升级检查清单

这篇不按“功能介绍”写,而是按升级时最容易漏掉的点来收。

先判断当前项目处在哪一代

1. 还在 9 到 12

这类项目通常带着这些特征:

  • pages/ 是绝对主线
  • 数据获取以 getStaticProps / getServerSideProps 为核心
  • 很少接触 Server Components
  • 业务团队对缓存标签、Server Actions、路由段级边界不熟

这类项目不适合一步跨太大。现实一点的迁移方式通常是:

  1. 先把依赖版本、Node 版本、React 版本抬起来
  2. 再决定是否引入 App Router
  3. 最后再处理 15 / 16 的默认语义变化

2. 已经在 13 或 14

这类项目通常已经开始接触:

  • app/
  • layout.tsx
  • Server Actions
  • RSC

这种情况下,升级重点通常不在“新概念学习”,而在:

  • Async Request APIs
  • 缓存默认值变化
  • Turbopack 和构建脚本
  • middlewareproxy

升到 15 前先检查什么

1. 请求时 API 是否仍按同步方式使用

重点搜这些:

  • cookies()
  • headers()
  • draftMode()
  • params
  • searchParams

如果这些逻辑还默认按同步对象来取值,15 开始就应该逐步改成异步访问。

2. 是否默认依赖缓存行为

重点检查:

  • fetch 有没有显式声明缓存策略
  • GET Route Handlers 是否隐式依赖静态缓存
  • 页面切换时是否默认认为客户端导航结果会复用缓存

3. React 相关依赖是否一起升级

至少一起检查:

  • react
  • react-dom
  • @types/react
  • @types/react-dom

升到 16 前先检查什么

1. Node.js 和 TypeScript 基线

16 的官方要求是:

  • Node.js 20.9+
  • TypeScript 5.1+

这件事很容易被忽略,因为 CI、容器镜像、远端构建环境可能比本地更旧。

2. 构建脚本是否仍绑定旧时代假设

检查 package.json

{
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack"
}
}

16 之后这类写法通常可以收回普通形式:

{
"scripts": {
"dev": "next dev",
"build": "next build"
}
}

如果项目有自定义 webpack 配置,又暂时不能迁移,就需要显式退回:

{
"scripts": {
"dev": "next dev --webpack",
"build": "next build --webpack"
}
}

3. middleware 是否要迁到 proxy

如果当前逻辑是普通请求边界控制,可以开始准备迁移。

如果当前逻辑强依赖 Edge runtime,16 这一轮不能机械迁移,先保留旧方案更稳。

4. next lint 是否仍在主流程里

16 已经移除了 next lint。如果构建脚本或 CI 还写着这条命令,需要切到 ESLint CLI 或其他工具链。

从 9 到 16 的现实迁移节奏

如果项目真的很老,比较稳的节奏通常不是“一步到位”,而是分三段:

第一段:先把基础环境抬高

  • Node.js
  • React
  • TypeScript
  • eslint-config-next

第二段:先完成 Pages Router 时代的兼容升级

  • 图片组件
  • Link 行为
  • 构建链差异
  • 被移除的老配置项

第三段:再决定 App Router 和 15 / 16 语义迁移

  • Async Request APIs
  • 缓存策略
  • Turbopack
  • proxy
  • cacheComponents

最实用的几个命令

升到最新版

pnpm next upgrade

如果版本较早,还可以用官方升级 codemod:

npx @next/codemod@canary upgrade latest

生成异步请求相关类型辅助

npx next typegen

next lint 迁移到 ESLint CLI

pnpm dlx @next/codemod@canary next-lint-to-eslint-cli .

升级时最值得保守处理的三块

  1. 缓存
  2. 自定义 webpack 配置
  3. 中间件 / 代理边界

这三块一旦误判,问题通常不是简单报错,而是运行语义变化、构建失败或线上行为和预期不一致。

参考资料