构建Next.js应用Skill building-nextjs-apps

本技能专注于使用Next.js 16框架构建现代化Web应用程序,涵盖从项目初始化、架构设计到部署的全流程。内容包括Next.js 16的重大变更(异步params/searchParams、Turbopack、缓存组件)、App Router模式、服务器组件与客户端组件的最佳实践、API路由设计、中间件配置(proxy.ts)、数据获取策略、项目结构规范以及开发工具集成(Next.js DevTools MCP)。适用于前端开发者、全栈工程师构建高性能、可扩展的React应用,特别适合需要SEO优化、服务器端渲染和现代化开发体验的项目。

前端开发 0 次安装 7 次浏览 更新于 3/2/2026

name: building-nextjs-apps description: | 使用正确的模式和独特的设计构建Next.js 16应用程序。适用于创建页面、布局、动态路由、从Next.js 15升级或实现proxy.ts。涵盖重大变更(异步params/searchParams、Turbopack、cacheComponents)和前端美学。不适用于构建非React或纯后端应用程序。

Next.js 16应用程序

使用独特的设计正确构建Next.js 16应用程序。

关键重大变更(Next.js 16)

1. params和searchParams现在都是Promise

这是最常见的错误。

// 错误 - Next.js 15模式(会失败)
export default function Page({ params }: { params: { id: string } }) {
  return <div>ID: {params.id}</div>
}

// 正确 - Next.js 16模式
export default async function Page({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  return <div>ID: {id}</div>
}

2. 客户端组件需要使用use()钩子

"use client"
import { use } from "react"

export default function ClientPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = use(params)
  return <div>ID: {id}</div>
}

3. searchParams也是异步的

export default async function Page({
  searchParams,
}: {
  searchParams: Promise<{ page?: string }>
}) {
  const { page } = await searchParams
  return <div>Page: {page ?? "1"}</div>
}

核心模式

项目设置

npx create-next-app@latest my-app --typescript --tailwind --eslint
cd my-app

# 添加shadcn/ui
npx shadcn@latest init
npx shadcn@latest add button form dialog table sidebar

App Router布局

// app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className="min-h-screen">
        {children}
      </body>
    </html>
  )
}

动态路由

// app/tasks/[id]/page.tsx
export default async function TaskPage({
  params,
}: {
  params: Promise<{ id: string }>
}) {
  const { id } = await params
  const task = await getTask(id)

  return (
    <main>
      <h1>{task.title}</h1>
    </main>
  )
}

服务器操作

// app/actions.ts
"use server"

import { revalidatePath } from "next/cache"

export async function createTask(formData: FormData) {
  const title = formData.get("title") as string

  await db.insert(tasks).values({ title })

  revalidatePath("/tasks")
}

// 在组件中使用
<form action={createTask}>
  <input name="title" />
  <button type="submit">创建</button>
</form>

API路由

// app/api/tasks/route.ts
import { NextResponse } from "next/server"

export async function GET() {
  const tasks = await db.select().from(tasksTable)
  return NextResponse.json(tasks)
}

export async function POST(request: Request) {
  const body = await request.json()
  const task = await db.insert(tasksTable).values(body).returning()
  return NextResponse.json(task, { status: 201 })
}

中间件 → proxy.ts

// proxy.ts(在Next.js 16中替代middleware.ts)
import { NextRequest } from "next/server"

export function proxy(request: NextRequest) {
  // 身份验证检查
  const token = request.cookies.get("token")
  if (!token && request.nextUrl.pathname.startsWith("/dashboard")) {
    return Response.redirect(new URL("/login", request.url))
  }
}

export const config = {
  matcher: ["/dashboard/:path*"],
}

数据获取

服务器组件(默认)

// 这在服务器上运行 - 可以直接使用async/await
async function TaskList() {
  const tasks = await fetch("https://api.example.com/tasks", {
    cache: "no-store", // SSR,或者
    // next: { revalidate: 60 } // ISR
  }).then(r => r.json())

  return (
    <ul>
      {tasks.map(task => <li key={task.id}>{task.title}</li>)}
    </ul>
  )
}

客户端组件

"use client"

import useSWR from "swr"

const fetcher = (url: string) => fetch(url).then(r => r.json())

export function ClientTaskList() {
  const { data, error, isLoading } = useSWR("/api/tasks", fetcher)

  if (isLoading) return <div>加载中...</div>
  if (error) return <div>加载任务时出错</div>

  return (
    <ul>
      {data.map(task => <li key={task.id}>{task.title}</li>)}
    </ul>
  )
}

项目结构

app/
├── layout.tsx           # 根布局
├── page.tsx             # 首页
├── globals.css          # 全局样式
├── api/                 # API路由
│   └── tasks/route.ts
├── tasks/
│   ├── page.tsx         # /tasks
│   └── [id]/page.tsx    # /tasks/:id
├── actions.ts           # 服务器操作
└── proxy.ts             # 请求代理(中间件)
components/
├── ui/                  # shadcn/ui组件
└── task-list.tsx        # 应用组件
lib/
├── db.ts                # 数据库连接
└── utils.ts             # 工具函数

Next.js DevTools MCP

使用next-devtools-mcp服务器进行运行时诊断和开发自动化。

设置

claude mcp add next-devtools npx next-devtools-mcp@latest

或在settings.json中:

{
  "mcpServers": {
    "next-devtools": {
      "type": "stdio",
      "command": "npx",
      "args": ["next-devtools-mcp@latest"]
    }
  }
}

可用工具

工具 用途
init 建立上下文,了解可用工具和最佳实践
nextjs_docs 搜索和获取官方Next.js文档
browser_eval 使用Playwright自动化浏览器测试
nextjs_index 发现正在运行的Next.js开发服务器
nextjs_call 在运行的开发服务器上执行MCP工具
upgrade_nextjs_16 使用代码模式自动升级
enable_cache_components 为Next.js 16配置缓存组件

关键用例

1. 获取实时错误

"我的Next.js应用中有哪些构建错误?"
"显示当前项目中的TypeScript错误"

2. 调试运行时问题

"检查开发服务器日志中的错误"
"仪表板页面上发生了哪些运行时错误?"

3. 升级协助

"将此项目升级到Next.js 16"
"为此应用启用缓存组件"

4. 文档查找

"如何在Next.js 16中使用Image组件?"
"处理动态路由的正确方法是什么?"

Next.js 16 MCP端点

Next.js 16+在http://localhost:3000/_next/mcp(或您的开发服务器端口)暴露内置的MCP端点。devtools MCP会自动发现并连接到正在运行的服务器。


验证

运行:python3 scripts/verify.py

预期:✓ building-nextjs-apps技能就绪

如果验证失败

  1. 检查:references/文件夹中有nextjs-16-patterns.md
  2. 如果仍然失败,请停止并报告

相关技能

  • styling-with-shadcn - Next.js应用的UI组件
  • fetching-library-docs - 最新Next.js文档:--library-id /vercel/next.js --topic routing
  • configuring-better-auth - Next.js应用的OAuth/SSO

参考资料