首页
/ Next.js 16 升级实战指南:Turbopack 默认化、middleware 更名 proxy 与全量破坏性变更解析

Next.js 16 升级实战指南:Turbopack 默认化、middleware 更名 proxy 与全量破坏性变更解析

2026-09-04 12:44:22作者:何举烈Damon

本文基于 Next.js 仓库中的官方升级文档 version-16.mdx 撰写,完整覆盖从 Next.js 15 升级到 16 的操作步骤、所有破坏性变更与默认值调整,并辅以仓库源码佐证。读完本文,你将掌握升级 codemod 的正确用法、Turbopack 默认启用后的 webpack 兼容策略、Async Request APIs 的迁移方式,以及 middleware 更名为 proxy、缓存 API 升级等每一项变更的具体应对方案。

升级路径总览:AI Agent 或手动升级

仓库根目录的 UPGRADING.md 已将其内容整体迁移至 docs/01-app/02-guides/upgrading/ 指南目录,其中 Version 16 指南提供了两条升级路径:

路径一:使用 AI Agent(官方推荐)。官方文档提供了一个可直接交给编码 Agent 的提示词,要求其先确认 AGENTS.md 指向与版本匹配的 Next.js 文档,再以 16 升级指南为唯一事实来源执行迁移,在机械性变更上优先使用 codemod,升级完成后运行运行时验证流程(如 next-dev-loop skill),最后复查 AGENTS.md 状态。

路径二:手动升级,按顺序执行四步:

  1. (可选)设置 AI Agent 文档,为后续 Agent 工作建立版本匹配的文档基础;
  2. 运行升级 codemod(下文详述);
  3. 若不想运行 codemod,则手动安装最新依赖;
  4. 逐条处理本文列出的破坏性变更,运行相关检查并修复遗留问题。

设置 AI Agent 文档

升级前可先运行:

npx @next/codemod@canary agents-md

该命令生成 AGENTS.md,其托管区块形如:

<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ
from your training data. Read the relevant guide in `node_modules/next/dist/docs/`
before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->

升级完成后要再次核对 AGENTS.md 指向的版本。Next.js 16.2 及以后应指向打包在 node_modules/next/dist/docs/ 中的文档;若升级前曾把文档下载到 .next-docs/,需更新指向并清理该目录。从文档描述看,该托管区块由 next dev 自动写入并重新添加,可通过 node_modules/next/dist/server/lib/generate-agent-files.js 验证其行为。

使用 upgrade codemod

推荐的方式是直接运行官方 codemod(完整 codemod 手册见 codemods.mdx):

pnpm dlx @next/codemod@canary upgrade latest   # pnpm
npx @next/codemod@canary upgrade latest         # npm
yarn dlx @next/codemod@canary upgrade latest    # yarn
bunx @next/codemod@canary upgrade latest        # bun

upgrade 子命令可接受 patchminormajor、dist tag(latestcanaryrc)或精确版本号,默认行为是 stable 版本下的 minor 升级;-y, --yes 会跳过所有交互提示并接受默认值,且当 stdin 不是 TTY 时(CI、AI Agent 场景)自动启用。该 codemod 自动完成以下机械性迁移:

  • next.config.js 更新为新的 turbopack 配置形式;
  • next lint 迁移到 ESLint CLI;
  • 从弃用的 middleware 约定迁移到 proxy
  • 移除已稳定 API 上的 unstable_ 前缀;
  • 从页面与布局中移除 experimental_ppr Route Segment Config。

注意upgrade codemod 不会运行全部迁移 codemod。若项目仍在使用 Next.js 15 兼容期的同步 paramssearchParamscookies()headers()draftMode() 访问,需额外运行:

npx @next/codemod@canary next-async-request-api .

手动安装依赖

若不使用 codemod,手动安装最新版 Next.js 与 React:

pnpm add next@latest react@latest react-dom@latest
# 或 npm install / yarn add / bun add 对应命令

TypeScript 项目还需同步升级 @types/react@types/react-dom。当前仓库 packages/next/package.json 中的版本号为 16.4.0-canary.14,即本指南对应 16.x 系列。

Node.js 运行时与浏览器支持

要求 变化 / 说明
Node.js 20.9+ 最低版本为 20.9.0(LTS),不再支持 Node.js 18
TypeScript 5+ 最低版本为 5.1.0
浏览器 Chrome 111+、Edge 111+、Firefox 111+、Safari 16.4+

Turbopack 成为默认构建工具

Next.js 16 起,Turbopack 已稳定并成为 next devnext build 的默认引擎。此前需要通过 --turbopack(或 --turbo)手动启用的脚本现在可以直接简化:

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

webpack 配置的兼容性陷阱:若项目定义了自定义 webpack 配置,执行 next build 时会直接构建失败以防止配置错配。三种应对方式:

  • 仍用 Turbopacknext build --turbopack,忽略 webpack 配置;
  • 彻底迁移:把 webpack 配置改写为 Turbopack 兼容选项;
  • 继续使用 Webpack:使用 --webpack 标志退出 Turbopack。例如开发用 Turbopack、构建用 Webpack:
{
  "scripts": {
    "dev": "next dev",
    "build": "next build --webpack",
    "start": "next start"
  }
}

提示:如果构建因"发现 webpack 配置"而失败但你并未定义过 webpack 选项,很可能是某个插件在注入该配置。

turbopack 配置位置

experimental.turbopack 退出实验,提升为 nextConfig 顶层选项:

// Next.js 15
const nextConfig: NextConfig = {
  experimental: { turbopack: { /* options */ } },
}

// Next.js 16
const nextConfig: NextConfig = {
  turbopack: { /* options */ },
}

16 版本引入了多项新 Turbopack 选项,包括高级 webpack loader 条件与 debugIds 等。

resolveAlias fallback

部分项目中客户端代码会 import 含 Node.js 原生模块的文件,产生 Module not found: Can't resolve 'fs' 一类错误。首选方案是重构代码使客户端 bundle 不引用原生模块;不可行时,可用 turbopack.resolveAlias 让浏览器侧加载空模块(等价于 Webpack 的 resolve.fallback 静默错误):

const nextConfig: NextConfig = {
  turbopack: {
    resolveAlias: {
      fs: { browser: './empty.ts' },
    },
  },
}

Sass 的 node_modules 导入

Turbopack 完整支持从 node_modules 导入 Sass,但不支持 Webpack 的 ~ 前缀

/* Webpack 旧写法 */
@import '~bootstrap/dist/css/bootstrap.min.css';

/* Turbopack 写法(去掉 ~) */
@import 'bootstrap/dist/css/bootstrap.min.css';

无法修改源码时可用别名兜底:turbopack: { resolveAlias: { '~*': '*' } }

Turbopack 文件系统缓存

Turbopack 会在磁盘上跨运行保存编译器产物,显著加快重启后的编译速度。next devnext build 默认都启用了文件缓存(分别由 experimental.turbopackFileSystemCacheForDevexperimental.turbopackFileSystemCacheForBuild 控制),可在 API 参考中配置或禁用。

Async Request APIs 完全移除同步访问(破坏性变更)

Version 15 引入 Async Request APIs 时保留了临时同步兼容;从 Next.js 16 起,同步访问被彻底移除,以下 API 只能通过异步方式访问:

  • cookiesheadersdraftMode
  • layoutpageroutedefaultopengraph-imagetwitter-imageiconapple-icon 中的 params
  • page 中的 searchParams

同步代码应通过 next-async-request-api codemod 迁移:它会把 cookies()headers()draftMode() 的调用改写为 awaitReact.use() 解包;对无法自动迁移的位置,会插入以 @next/codemod 前缀的注释或 UnsafeUnwrapped* 类型断言,在手动处理并删除这些标记之前,构建会持续报错,这是刻意设计的安全网。

用 typegen 生成类型辅助迁移

运行 npx next typegen(15.5 引入)可自动生成全局类型助手 PagePropsLayoutPropsRouteContext,实现类型安全的异步迁移:

// /app/blog/[slug]/page.tsx
export default async function Page(props: PageProps<'/blog/[slug]'>) {
  const { slug } = await props.params
  const query = await props.searchParams
  return <h1>Blog Post: {slug}</h1>
}

图像生成与 sitemap 的异步参数(破坏性变更)

opengraph-imagetwitter-imageiconapple-icon 的图像生成函数现在接收 paramsid 作为 PromisegenerateImageMetadata 仍接收同步 params

// Next.js 15:同步访问
export function generateImageMetadata({ params }) {
  const { slug } = params
  return [{ id: '1' }, { id: '2' }]
}
export default function Image({ params, id }) {
  const slug = params.slug
  const imageId = id // string
}

// Next.js 16:异步访问
export async function generateImageMetadata({ params }) {
  const { slug } = params
  return [{ id: '1' }, { id: '2' }]
}
export default async function Image({ params, id }) {
  const { slug } = await params
  const imageId = await id // Promise<string>
}

sitemap 生成函数同样改为接收 id 的 Promise(原值可能是数字,需要时 Number(resolvedId) 转换):

export async function generateSitemaps() {
  return [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }]
}
export default async function sitemap({ id }) {
  const resolvedId = await id // id is now Promise<string>
  const start = Number(resolvedId) * 50000
}

React 19.2 与 React Compiler 支持

Next.js 16 的 App Router 使用包含 React 19.2 特性的最新 React Canary,亮点包括 View Transitions(Transition 内更新元素的动画)、useEffectEvent(把非响应式逻辑从 Effect 中抽出为可复用的 Effect Event 函数)与 Activity(以 display: none 隐藏 UI 同时保留状态并清理 Effects 的"后台活动")。

React Compiler 的支持在 Next.js 16 中稳定化(非默认开启,官方仍在收集各类型应用的构建性能数据):

const nextConfig: NextConfig = {
  reactCompiler: true, // 从 experimental 提升为稳定选项
}

需安装编译器插件:npm install -D babel-plugin-react-compiler(或对应 pnpm/yarn/bun 命令)。注意该选项依赖 Babel,开启后开发编译与构建耗时会增加。

缓存 API 变化

revalidateTag 必须传第二个参数

revalidateTag 现在要求第二个参数指定 cacheLife profile,单参数形式已弃用并会产生 TypeScript 错误:

// Before
revalidateTag('posts')
// After
revalidateTag('posts', 'max')

revalidateTag 适用于允许轻微更新延迟的内容(博客、商品目录、文档),读者在数据后台刷新期间看到陈旧内容。若需要"立即生效"语义,改用 Server Actions 专用的 updateTag

updateTag:read-your-writes 语义

'use server'
import { updateTag } from 'next/cache'

export async function updateUserProfile(userId: string, profile: Profile) {
  await db.users.update(userId, profile)
  // 过期缓存并在同一请求内立即刷新——用户马上看到自己的改动
  updateTag(`user-${userId}`)
}

适合表单、用户设置等期望即时反馈的工作流。

refresh:在 Server Action 中刷新客户端路由

'use server'
import { refresh } from 'next/cache'

export async function markNotificationAsRead(notificationId: string) {
  await db.notifications.markAsRead(notificationId)
  refresh() // 刷新头部显示的未读计数
}

cacheLife / cacheTag 稳定化

unstable_cacheLifeunstable_cacheTagunstable_ 前缀不再需要:

// 之前
import { unstable_cacheLife as cacheLife, unstable_cacheTag as cacheTag } from 'next/cache'
// 之后
import { cacheLife, cacheTag } from 'next/cache'

路由与导航性能增强

Next.js 16 对路由导航系统做了整体重构,无需任何代码修改

  • 布局去重:预取多个共享布局的 URL 时,布局只下载一次;
  • 增量预取:只预取缓存中尚缺的片段,而非整页数据。

代价是预取请求数量会增加,但总传输体积显著下降。官方明确这是面向绝大多数应用的合理权衡。

Partial Prerendering:experimental_ppr 移除,改用 cacheComponents

Next.js 16 移除了实验性 PPR 标志与 experimental_ppr 路由段配置,PPR 改由顶层 cacheComponents 配置接入:

const nextConfig = {
  cacheComponents: true,
}
module.exports = nextConfig

16 中的 PPR 与 15 canary 行为不同,当前使用 PPR 的用户应停留在现有 15 canary,迁移路径参见 Migrating to Cache Components 指南。

middleware 更名为 proxy

middleware 文件名被弃用并更名为 proxy,以明确其网络边界与路由定位:

mv middleware.ts proxy.ts   # 或 middleware.js → proxy.js

命名导出 middleware 同步更名:

// proxy.ts
export function proxy(request: Request) {}

配置项中所有含 middleware 的标志同步更名,例如 skipMiddlewareUrlNormalizeskipProxyUrlNormalizeexperimental.middlewarePrefetchexperimental.proxyPrefetch。16 版 codemod 会自动完成这些重命名。

重要限制proxy 不支持 edge 运行时,其运行时固定为 nodejs 且不可配置。若仍需 edge 运行时,请继续使用 middleware(官方表示将在后续小版本补充说明)。

next/image 的安全与默认值调整(多项破坏性变更)

  1. 本地图片带查询字符串需显式声明(防枚举攻击):<Image src="/assets/photo?v=1" /> 这类用法现在要求配置 images.localPatterns.search
const nextConfig: NextConfig = {
  images: {
    localPatterns: [{ pathname: '/assets/**', search: '?v=1' }],
  },
}
  1. minimumCacheTTL 默认值从 60 秒变为 4 小时(14400 秒),减少无 cache-control 头上游图片导致的频繁重验证与 CPU 开销。从源码可以确认该默认值:image-config.tsminimumCacheTTL: 14400, // 4 hours,并在 image-optimizer.ts 中作为缺省值生效。需要旧行为时设回 minimumCacheTTL: 60
  2. imageSizes 默认值移除 16:分析显示几乎没有项目真正下发 16px 宽图片,且 devicePixelRatio: 2 实际会取 32px 图,移除后可减小下发到浏览器的 srcset 体积。需要时显式写回 imageSizes: [16, 32, 48, 64, 96, 128, 256, 384]
  3. qualities 默认从"全部"收窄为 [75]:不在数组内的 quality prop 会被就近强制(如 80 → 75)。需要多档质量时显式配置 qualities: [50, 75, 100]
  4. 本地 IP 限制:默认阻断本地 IP 的图片优化。仅在私有网络(如 VPC 内 split-horizon DNS 导致 400 的场景)设 images.dangerouslyAllowLocalIP: true,并理解其 SSRF 风险。
  5. 最大重定向次数images.maximumRedirects 从无限改为默认 3 次;0 表示禁用,可上调至 5 应对边缘场景。
  6. next/legacy/image 弃用:改为 import Image from 'next/image'
  7. images.domains 弃用:改用更安全的 images.remotePatterns(指定 protocol + hostname)。

其余破坏性变更与行为调整

并发 dev 与 build

next devnext build 现在使用独立输出目录,可并发执行——next dev 输出到 .next/dev;同时引入锁文件机制防止同一项目多个 next dev/next build 实例。Turbopack 追踪命令相应调整为:

npx next internal trace .next-profiles/trace-turbopack.bin

Parallel Routes 必须提供 default.js

所有 parallel route 槽位现在必须有显式 default.js 文件,缺失则构建失败:

// app/@modal/default.tsx
import { notFound } from 'next/navigation'

export default function Default() {
  notFound()   // 或 return null
}

ESLint Flat Config

@next/eslint-plugin-next 默认切换到 ESLint Flat Config 格式,与将移除 legacy 配置支持的 ESLint v10 对齐;使用 .eslintrc 的项目建议迁移到 flat config。

滚动行为不再被覆写

此前若在 <html> 上全局设置了 scroll-behavior: smooth,Next.js 会在 SPA 路由跳转时临时改为 auto 实现瞬时回到顶部、随后恢复。16 起默认不再覆写。想保留旧行为,在根布局加属性:

<html lang="en" data-scroll-behavior="smooth">

构建输出指标调整

next build 输出移除了 sizeFirst Load JS 指标——官方认定在 RSC 服务端驱动架构下这两个数值不准确,且 Turbopack 与 Webpack 实现口径不一。路由级性能测量建议使用 Chrome Lighthouse 等基于 Core Web Vitals 的工具。

另外,next dev 不再重复加载两次配置文件(此前 dev 命令启动与服务端启动各加载一次)。副作用是:配置文件内检查 process.argv 是否包含 'dev' 将返回 falsetypegenbuild 命令仍可见)。依赖该判断的插件建议改查 NODE_ENV === 'development' 或使用配置加载 phase

Build Adapters API(alpha)

首个 alpha 版 Build Adapters API 允许部署平台通过自定义适配器钩入构建流程,修改 Next.js 配置或处理构建产物:

const nextConfig = {
  experimental: {
    adapterPath: require.resolve('./my-adapter.js'),
  },
}
module.exports = nextConfig

adapterPath 在 16.2.0 提升为稳定的顶层选项。

Modern Sass API

sass-loader 升级至 v16,支持现代 Sass 语法与新特性。

已移除的功能清单

移除项 迁移方案
AMP 支持amp 配置、next/ampuseAmp、页面 export const config = { amp: true } 依靠 Next.js 内置优化与现代 Web 标准
next lint 命令及配置文件中的 eslint 选项 直接使用 ESLint 或 Biome;next build 不再执行 linting。可用 codemod 自动迁移:npx @next/codemod@canary next-lint-to-eslint-cli .,它生成含 next/core-web-vitalsnext/typescripteslint.config.mjs 并把脚本改为 eslint .
serverRuntimeConfig / publicRuntimeConfig 服务端值直接在 Server Components 中读 process.env;客户端值用 NEXT_PUBLIC_ 前缀;需要运行时读取(而非构建时打包)时先 await connection() 再读 process.env;敏感值可配合 taint API 防泄漏
devIndicatorsappIsrStatusbuildActivitybuildActivityPosition 选项 指示器本体保留
experimental.dynamicIO / experimental.useCache 采用 Cache Components 的迁移到顶层 cacheComponents: true(注意这不是简单改名,会暴露 <Suspense> 外未缓存数据的构建错误,需要整体采用 Cache Components 模型);未实际采用的直接删除标志
unstable_rootParams 改用 next/root-params

小结

Next.js 16 是一次以"Turbopack 默认化 + 异步请求 API 彻底落地 + 安全默认值收紧"为主线的大版本升级。建议的实操顺序是:确认 Node.js 20.9+ 环境 → 运行 npx @next/codemod@canary upgrade latest 完成机械性迁移 → 按本文清单逐项核对 next/image 默认值、proxy 运行时限制、parallel route default.js 等破坏性变更 → 运行 next typegen 完成类型迁移 → 通过 dev 指示器、浏览器与服务器日志验证关键交互路径。仓库内与升级相关的原始文档均位于 docs/01-app/02-guides/upgrading/,其中 version-15.mdxversion-14.mdx 覆盖历史版本升级,codemods.mdx 提供全部 codemod 的完整参考。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
980
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384