用途
next-v16 是一个针对 Next.js 16 App Router(2025 年 10 月 GA)的编码技能,用于在生成、审查或重构 Next.js 代码时提供版本匹配的最佳实践。它要求优先阅读 node_modules/next/dist/docs/ 中与已安装版本对应的文档,而不是依赖训练数据。
适用范围
适用于 Next.js 16 App Router,包括 Turbopack、Cache Components 与旧缓存模型、proxy.ts、异步请求 API、Server Components、Server Actions、流式渲染、元数据以及客户端孤岛。
不覆盖:Pages Router、通用 React 19(参见 vercel-react)、非 Next 的服务端渲染。
前提假设
- Next.js 16.x、React 19.2 App Router、Node.js 20.9+、TypeScript 5.1+
- 存在两种缓存模型,需在 next.config 中检测 cacheComponents 后再选择 API
- 两种模型中 fetch 默认都不缓存,需显式选择加入
核心原则
- 生成 Next API 前先阅读 node_modules/next/dist/docs/ 中已安装版本的文档
- 缓存是选择加入的,每个服务端 fetch 都要声明意图
- 网络边界是 proxy.ts(Node.js),负责鉴权门、重写、重定向、请求头修改
- 请求 API 是异步的:await cookies()、await headers()、await draftMode()、await params、await searchParams
- Turbopack 是默认打包器,--webpack 是退出选项,而非 16 的惯用法
- 优先使用 Server Components,将 'use client' 推到交互叶子节点
- 当用户要求审计或现代化 Next 代码时,遵循 references/_review-algorithm.md
必须遵守
- await params、searchParams、cookies()、headers()、draftMode()
- 调用 revalidateTag(tag, profile),其中 cacheLife profile 为 'max' | 'hours' | 'days' | 内联 { expire };单参数形式已弃用
- 当用户必须立即看到写入(read-your-writes)时,在 Server Actions 中使用 updateTag(tag);使用 revalidateTag(tag, 'max') 实现 stale-while-revalidate
- 从 proxy.ts 导出 proxy(具名或默认),运行时为 nodejs,不能设为 Edge
- 在添加 'use cache'、cacheLife 或 cacheTag 前,确认 cacheComponents: true
建议做法
- 仅在显式迁移时启用 Cache Components:cacheComponents: true,然后用 'use cache' + cacheLife 替换段配置 dynamic / revalidate / fetchCache
- 如果应用未采用 experimental.dynamicIO / experimental.useCache / experimental.ppr,移除这些标志;不要将 cacheComponents: true 当作重命名来设置,否则可能因 Suspense 外的未缓存数据导致构建失败
- 不使用 Cache Components 时,用 cache: 'force-cache'、next: { revalidate, tags } 或 unstable_cache 进行缓存
- 在 proxy.ts 上保留 config.matcher,排除 /_next/static、/_next/image 和公共资源
- 使用 next/image 的 remotePatterns(而非已弃用的 images.domains),使用 next/image 而非 next/legacy/image
- 从 app/sitemap.ts 和 app/robots.ts 生成 sitemap/robots
- 从 next/cache 导入 cacheLife / cacheTag(稳定版),不要使用 unstable_cacheLife / unstable_cacheTag
- 将 skipMiddlewareUrlNormalize 重命名为 skipProxyUrlNormalize
应避免
- 在未设置 cacheComponents: true 的应用中生成 'use cache'(该指令是 Cache Components 特性)
- 因为存在 experimental.dynamicIO / experimental.useCache / experimental.ppr 就翻转 cacheComponents: true;启用该标志是编程模型迁移
- 为新代码使用 middleware.ts;仅在仍需要 Edge 运行时保留它,它已弃用
- 同步 params / cookies() / headers()(已移除,不再警告)
- next lint(已移除),改用 ESLint 或 Biome
- experimental.ppr、experimental.dynamicIO、experimental.useCache、export const experimental_ppr(已移除)
- experimental.turbopack(已移至顶层 turbopack)
- experimental.turbo.persistentCaching——这不是 Next 16 API;文件系统缓存是 experimental.turbopackFileSystemCacheForDev / experimental.turbopackFileSystemCacheForBuild(默认开启)
- 将 next dev --turbopack / next build --turbopack 作为 16 的惯用法;Turbopack 已是默认,--webpack 是退出选项
- 在运行默认 next build 时使用自定义 webpack 配置(会失败);迁移到 Turbopack 或传入 --webpack
- 将 revalidateTag 的 'max' 视为 read-your-writes;那是 SWR,应在 Server Actions 中使用 updateTag
- 声称 Server Actions 必须替换所有 Route Handler;Route Handlers 对 cookies、webhooks、OAuth 回调和代理外部 API 仍然正确
与其他技能的交互
- React 19 并发 UI:vercel-react
- 水合后的客户端数据:tanstack-query-v5
- 留在 Next 服务端的表单:workflow/form
两种缓存模型(不要混用)
- cacheComponents 未设置 / false:旧模型。fetch 除非 cache: 'force-cache' 或 next.revalidate,否则不缓存。段配置 dynamic、revalidate、fetchCache 仍有效。非 fetch 使用 unstable_cache。不要生成 'use cache'
- cacheComponents: true:Cache Components。默认动态。用 'use cache' + cacheLife / cacheTag 缓存。段配置 dynamic / revalidate / fetchCache 会报错。PPR 是默认行为。'use cache' 作用域内的 fetch 会被缓存
'use cache' 需要 cacheComponents: true。启用该标志是迁移,不是 Next 16 的自动默认。
失效(两种模型,Next 16 签名):
- revalidateTag(tag, 'max')——stale-while-revalidate;在 Server Actions 和 Route Handlers 中可用
- updateTag(tag)——在同一请求中过期并读取最新;仅 Server Actions
- refresh()——仅刷新未缓存数据;仅 Server Actions
- revalidatePath——未变
Next.js 16 惯用法(不要生成 Next 15 写法)
- proxy.ts + export function proxy(Node)——除非需要 Edge,否则不用 middleware.ts
- Turbopack 默认——next dev / next build 不带 --turbopack。退出:--webpack
- await params / await searchParams / await cookies()
- revalidateTag(tag, profile)——不是 revalidateTag(tag)
- reactCompiler: true 稳定且为选择加入(非默认)
- turbopack: { ... } 位于 Next 配置根——不是 experimental.turbopack
- 并行路由插槽需要 default.js(缺少会导致构建失败)
如何审查或重构
当用户要求审查、重构、现代化或审计 Next 代码时,遵循 references/_review-algorithm.md,不要即兴发挥。
- 选择模式 A(≤约 20 个文件)或模式 B(整棵树)
- 在类别 2 之前从 next.config 检测缓存模型
- 按类别主序扫描,包含范围声明、每类别进度行和覆盖表
- 类别 9 最后(去重 / 合并 / 删除 / 降级 'use client')
规则类别
- 构建与打包——关键——barrels、optimizePackageImports、serverExternalPackages、Turbopack、next/dynamic
- 缓存——关键——fetch 意图、段配置或 'use cache'(取决于模型)、revalidateTag+profile、revalidatePath、React cache()
- Server Components——高——并行 fetch、Suspense、共置、preload、无客户端初始 fetch
- 路由——高——并行/拦截路由、prefetch、proxy.ts、notFound()
- Server Actions——中高——表单、useFormStatus、action 结果、乐观 UI、重新验证。当变更已走外部 API 时跳过
- 流式渲染——中——Suspense、在 await 的路由上使用 loading.tsx、error.tsx、匹配的骨架屏
- 元数据——中——generateMetadata、sitemap.ts、robots.ts、opengraph-image.tsx
- 客户端孤岛——低中——'use client' 叶子、children 插槽、水合、next/script
- 卫生——横切——去重 fetcher、合并路由、死代码、边界审计、命名漂移
完整规则列表:references/compiled.md。规则文件:references/。
参考资料
- Next.js 16 博客
- 升级到 16
- 缓存(Cache Components)
- 不使用 Cache Components 的缓存
- 迁移到 Cache Components
- use cache
- proxy.ts
- middleware → proxy