Next.js 16 发射台
Next.js 16:Turbopack 默认(2-5× 快速构建),缓存组件('use cache'),以及 proxy.ts 用于显式控制。
何时使用
✅ Next.js 16, Turbopack, 缓存组件, proxy 迁移, App Router, React 19.2
❌ 页面路由器, Next.js ≤15, 通用 React 问题
要求
| 工具 | 版本 |
|---|---|
| Node.js | 20.9.0+ |
| TypeScript | 5.1.0+ |
| React | 19.2+ |
快速开始
# 新项目
npx create-next-app@latest my-app
# 升级现有
npx @next/codemod@canary upgrade latest
npm install next@latest react@latest react-dom@latest
推荐:TypeScript, ESLint, Tailwind, App Router, Turbopack, @/* 别名。
最小设置
// app/layout.tsx
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
// app/page.tsx
export default function Page() {
return <h1>Hello, Next.js 16!</h1>
}
配置
// next.config.ts
import type { NextConfig } from 'next'
const nextConfig: NextConfig = {
cacheComponents: true,
reactCompiler: true,
}
export default nextConfig
v15 → v16 变更
| v15 | v16 |
|---|---|
experimental.turbopack |
默认 |
experimental.ppr |
cacheComponents |
middleware.ts (Edge) |
proxy.ts (Node) |
同步 params |
await params |
核心模式
1. 服务器组件(默认)
export default async function BlogPage() {
const res = await fetch('https://api.example.com/posts')
const posts = await res.json()
return <PostList posts={posts} />
}
2. 缓存组件
import { cacheLife } from 'next/cache'
export default async function BlogPage() {
'use cache'
cacheLife('hours')
const posts = await fetch('https://api.example.com/posts').then(r => r.json())
return <PostList posts={posts} />
}
3. 客户端组件
'use client'
import { useState } from 'react'
export default function Counter() {
const [count, setCount] = useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
</div>
)
}
4. 代理边界
// app/proxy.ts
export function proxy(request: NextRequest) {
if (!request.cookies.get('auth') && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
5. 缓存标签 + 服务器操作
// app/blog/page.tsx
'use cache'
cacheLife('hours')
cacheTag('blog-posts')
export default async function BlogList() {
const posts = await db.posts.findMany()
return <PostList posts={posts} />
}
// app/actions.ts
'use server'
import { updateTag } from 'next/cache'
export async function createPost(data: PostData) {
await db.posts.create(data)
updateTag('blog-posts')
}
6. 带有 Suspense 的流式传输
export default function Dashboard() {
return (
<div>
<Suspense fallback={<Skeleton />}>
<RevenueCard />
</Suspense>
<Suspense fallback={<Skeleton />}>
<UsersCard />
</Suspense>
</div>
)
}
async function RevenueCard() {
const data = await db.analytics.revenue()
return <div>{data}</div>
}
关键概念
- Turbopack - Rust 打包器,增量编译,快速刷新
- 服务器组件 - 默认在
app/中,零客户端 JS - 客户端组件 -
'use client',钩子,浏览器 API - 缓存组件 -
'use cache'+cacheLife()用于 PPR - 代理边界 -
proxy.ts用于认证/重写/重定向 - 部分预渲染 - 静态外壳 + 动态流式传输
迁移清单
-
异步请求 API
npx @next/codemod@canary async-request-api更新:
const { slug } = await params -
middleware.ts → proxy.ts
- 重命名文件,导出
proxy - 仅 Node 运行时(不是 Edge)
- 重命名文件,导出
-
配置更新
- 移除
experimental.*标志 - 启用
cacheComponents,reactCompiler - 移除
serverRuntimeConfig/publicRuntimeConfig
- 移除
-
缓存组件
- 用
cacheComponents: true替换experimental.ppr - 用
<Suspense>包装动态部分
- 用
-
图像
- 为查询字符串配置
images.localPatterns
- 为查询字符串配置
查看 references/nextjs16-migration-playbook.md 获取完整指南。
常见陷阱
❌ 将 'use cache' 与运行时 API(cookies(), headers())混合使用
❌ 在启用缓存组件时缺少 <Suspense>
❌ 在 Turbopack 下使用波浪号 Sass 导入
❌ 在 Edge 运行时运行 proxy.ts
✅ 首先读取 cookies/headers,作为属性传递给缓存组件
✅ 用 <Suspense> 包装动态子组件
✅ 使用标准 Sass 导入
✅ 使用 Node 运行时代理
决策指南
启用缓存组件? → 是的,对于静态/半静态内容 → 不是,对于完全动态的仪表板
认证住在哪里?
→ proxy.ts 用于跨路由检查
→ 路由处理程序用于 API 特定逻辑
何时使用 'use client'?
→ 仅当您需要钩子,状态或浏览器 API 时
→ 保持呈现组件在服务器端
生产模式
电子商务
// 带有流式传输的产品页面
export default async function Product({ params }) {
const { id } = await params
const product = await db.products.findById(id)
return (
<>
<ProductInfo product={product} />
<Suspense fallback={<ReviewsSkeleton />}>
<Reviews productId={id} />
</Suspense>
</>
)
}
认证仪表板
// proxy.ts
export function proxy(request: NextRequest) {
const session = request.cookies.get('session')
if (!session && request.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', request.url))
}
}
查看 references/nextjs16-advanced-patterns.md 获取更多蓝图。
性能
- 保持 Turbopack 启用(只有在需要时才使用
--webpack退出) - 使用
Promise.all并行化获取 - 使用
<Suspense>用于流式传输边界 - 为大型存储库启用文件系统缓存
安全
- 使用
server-only包 + React Taint API - 在
proxy.ts中保持认证 - 在服务器操作中验证输入
- 使用
NEXT_PUBLIC_前缀限制环境变量 - 在缓存范围之前提取 cookies/headers
部署
- Vercel:零配置
- Docker/Node:
output: 'standalone' - 监控构建时间(预计速度提升 2-5×)
- 配置缓存生命周期以匹配 CDN
参考文件
- references/nextjs16-reference.md - 安装/配置/检查列表
- references/nextjs16-migration-playbook.md - 迁移指南及代码修改
- references/nextjs16-advanced-patterns.md - 流式传输,缓存,认证模式
- references/NEXTJS_16_COMPLETE_GUIDE.md - 完整文档
- scripts/bootstrap-nextjs16.ps1 - 自动化设置脚本
- assets/app-router-starter/ - 参考实现
资源
版本: 1.1.0 | 更新: 2025-12-27