Next.js 16 升级实战指南:Turbopack 默认化、middleware 更名 proxy 与全量破坏性变更解析
本文基于 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 状态。
路径二:手动升级,按顺序执行四步:
- (可选)设置 AI Agent 文档,为后续 Agent 工作建立版本匹配的文档基础;
- 运行升级 codemod(下文详述);
- 若不想运行 codemod,则手动安装最新依赖;
- 逐条处理本文列出的破坏性变更,运行相关检查并修复遗留问题。
设置 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 子命令可接受 patch、minor、major、dist tag(latest、canary、rc)或精确版本号,默认行为是 stable 版本下的 minor 升级;-y, --yes 会跳过所有交互提示并接受默认值,且当 stdin 不是 TTY 时(CI、AI Agent 场景)自动启用。该 codemod 自动完成以下机械性迁移:
- 将
next.config.js更新为新的turbopack配置形式; - 从
next lint迁移到 ESLint CLI; - 从弃用的
middleware约定迁移到proxy; - 移除已稳定 API 上的
unstable_前缀; - 从页面与布局中移除
experimental_pprRoute Segment Config。
注意:upgrade codemod 不会运行全部迁移 codemod。若项目仍在使用 Next.js 15 兼容期的同步 params、searchParams、cookies()、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 dev 与 next build 的默认引擎。此前需要通过 --turbopack(或 --turbo)手动启用的脚本现在可以直接简化:
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
}
}
webpack 配置的兼容性陷阱:若项目定义了自定义 webpack 配置,执行 next build 时会直接构建失败以防止配置错配。三种应对方式:
- 仍用 Turbopack:
next 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 dev 与 next build 默认都启用了文件缓存(分别由 experimental.turbopackFileSystemCacheForDev 与 experimental.turbopackFileSystemCacheForBuild 控制),可在 API 参考中配置或禁用。
Async Request APIs 完全移除同步访问(破坏性变更)
Version 15 引入 Async Request APIs 时保留了临时同步兼容;从 Next.js 16 起,同步访问被彻底移除,以下 API 只能通过异步方式访问:
cookies、headers、draftMode;layout、page、route、default、opengraph-image、twitter-image、icon、apple-icon中的params;page中的searchParams。
同步代码应通过 next-async-request-api codemod 迁移:它会把 cookies()、headers()、draftMode() 的调用改写为 await 或 React.use() 解包;对无法自动迁移的位置,会插入以 @next/codemod 前缀的注释或 UnsafeUnwrapped* 类型断言,在手动处理并删除这些标记之前,构建会持续报错,这是刻意设计的安全网。
用 typegen 生成类型辅助迁移
运行 npx next typegen(15.5 引入)可自动生成全局类型助手 PageProps、LayoutProps、RouteContext,实现类型安全的异步迁移:
// /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-image、twitter-image、icon、apple-icon 的图像生成函数现在接收 params 与 id 作为 Promise;generateImageMetadata 仍接收同步 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_cacheLife、unstable_cacheTag 的 unstable_ 前缀不再需要:
// 之前
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 的标志同步更名,例如 skipMiddlewareUrlNormalize → skipProxyUrlNormalize、experimental.middlewarePrefetch → experimental.proxyPrefetch。16 版 codemod 会自动完成这些重命名。
重要限制:proxy 不支持 edge 运行时,其运行时固定为 nodejs 且不可配置。若仍需 edge 运行时,请继续使用 middleware(官方表示将在后续小版本补充说明)。
next/image 的安全与默认值调整(多项破坏性变更)
- 本地图片带查询字符串需显式声明(防枚举攻击):
<Image src="/assets/photo?v=1" />这类用法现在要求配置images.localPatterns.search:
const nextConfig: NextConfig = {
images: {
localPatterns: [{ pathname: '/assets/**', search: '?v=1' }],
},
}
minimumCacheTTL默认值从 60 秒变为 4 小时(14400 秒),减少无cache-control头上游图片导致的频繁重验证与 CPU 开销。从源码可以确认该默认值:image-config.ts 中minimumCacheTTL: 14400, // 4 hours,并在 image-optimizer.ts 中作为缺省值生效。需要旧行为时设回minimumCacheTTL: 60。imageSizes默认值移除 16:分析显示几乎没有项目真正下发 16px 宽图片,且devicePixelRatio: 2实际会取 32px 图,移除后可减小下发到浏览器的srcset体积。需要时显式写回imageSizes: [16, 32, 48, 64, 96, 128, 256, 384]。qualities默认从"全部"收窄为[75]:不在数组内的qualityprop 会被就近强制(如 80 → 75)。需要多档质量时显式配置qualities: [50, 75, 100]。- 本地 IP 限制:默认阻断本地 IP 的图片优化。仅在私有网络(如 VPC 内 split-horizon DNS 导致 400 的场景)设
images.dangerouslyAllowLocalIP: true,并理解其 SSRF 风险。 - 最大重定向次数:
images.maximumRedirects从无限改为默认 3 次;0表示禁用,可上调至 5 应对边缘场景。 next/legacy/image弃用:改为import Image from 'next/image'。images.domains弃用:改用更安全的images.remotePatterns(指定protocol+hostname)。
其余破坏性变更与行为调整
并发 dev 与 build
next dev 与 next 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 输出移除了 size 与 First Load JS 指标——官方认定在 RSC 服务端驱动架构下这两个数值不准确,且 Turbopack 与 Webpack 实现口径不一。路由级性能测量建议使用 Chrome Lighthouse 等基于 Core Web Vitals 的工具。
另外,next dev 不再重复加载两次配置文件(此前 dev 命令启动与服务端启动各加载一次)。副作用是:配置文件内检查 process.argv 是否包含 'dev' 将返回 false(typegen、build 命令仍可见)。依赖该判断的插件建议改查 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/amp 的 useAmp、页面 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-vitals、next/typescript 的 eslint.config.mjs 并把脚本改为 eslint . |
serverRuntimeConfig / publicRuntimeConfig |
服务端值直接在 Server Components 中读 process.env;客户端值用 NEXT_PUBLIC_ 前缀;需要运行时读取(而非构建时打包)时先 await connection() 再读 process.env;敏感值可配合 taint API 防泄漏 |
devIndicators 的 appIsrStatus、buildActivity、buildActivityPosition 选项 |
指示器本体保留 |
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.mdx 与 version-14.mdx 覆盖历史版本升级,codemods.mdx 提供全部 codemod 的完整参考。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00