Next.js15应用路由器专家 nextjs-15-specialist

这是一个专门针对Next.js 15框架的应用路由器技能指南,提供完整的服务器组件、客户端组件、数据获取、缓存策略、服务器操作和元数据管理的全面解决方案。包含150+实际代码示例和最佳实践,帮助开发者正确实现现代Next.js应用架构,避免常见错误,优化性能。关键词:Next.js 15, App Router, 服务器组件, 数据获取, 缓存策略, 服务器操作, React框架, 前端开发, Web性能优化。

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

name: nextjs-15-specialist description: 处理Next.js 15功能、App Router、服务器组件、服务器操作或数据获取模式时使用。确保正确使用服务器与客户端组件以及现代Next.js模式。 allowed-tools: Read, Grep, Glob, WebFetch

Next.js 15 + App Router 专家

Quetrex开发的完整Next.js 15参考指南。

此技能提供关于所有Next.js 15 App Router模式的全面指导,确保代理首次即能正确实现现代Next.js。


关键规则(绝不违反)

这些规则是不可协商的。违反将导致构建失败。

1. 始终使用来自next/image<Image> - 绝不使用<img>

// ✅ 始终这样做
import Image from 'next/image'

<Image src="/logo.png" alt="Logo" width={200} height={100} />
<Image src={user.avatar} alt={user.name} width={40} height={40} />

// ❌ 绝不这样做 - 构建将失败
<img src="/logo.png" alt="Logo" />
<img src={user.avatar} alt={user.name} />

原因: Next.js Image组件提供自动优化、懒加载,并防止布局偏移。ESLint配置为在<img>使用时使构建失败。

2. 服务器组件是默认的 - 仅在需要时添加’use client’

3. 绝不创建异步客户端组件

4. 始终为fetch()指定缓存策略


何时使用此技能

在以下情况时使用此技能:

  • 创建新路由或页面
  • 实现数据获取(服务器组件 vs 客户端组件)
  • 服务器与客户端组件决策
  • 服务器操作和表单处理
  • 流式传输和Suspense
  • 元数据和SEO
  • 路由处理程序(API路由)
  • 缓存策略
  • 性能优化

完整文档

此技能包含涵盖每个Next.js 15模式的全面指南:

📁 App Router 完整指南

45+ 示例涵盖:

  • 基于文件的路由(page.tsx, layout.tsx, route.ts)
  • 动态路由([id], […slug], [[…slug]])
  • 路由组((group))
  • 私有文件夹(_folder)
  • 路由处理程序(API路由)
  • 布局和模板
  • 加载UI(loading.tsx)
  • 错误边界(error.tsx, global-error.tsx)
  • 未找到页面(not-found.tsx)
  • 并行路由(@folder)
  • 拦截路由((.)folder)
  • 路由段配置(dynamic, revalidate, runtime)

🔄 数据获取完整指南

35+ 示例涵盖:

  • 服务器组件数据获取(async/await)
  • 客户端组件数据获取(useEffect, React Query, SWR)
  • 并行数据获取(Promise.all)
  • 顺序数据获取(防止瀑布流)
  • 流式数据(Suspense边界)
  • 服务器发送事件(用于Quetrex语音的SSE)
  • 数据变更(服务器操作)
  • 乐观更新(useOptimistic)
  • 表单处理(useFormStatus, useActionState)
  • 请求去重
  • 预加载数据

💾 缓存策略指南

35+ 示例涵盖:

  • 请求记忆化(自动去重)
  • 数据缓存(fetch缓存行为)
  • 完整路由缓存(静态 vs 动态)
  • 路由器缓存(客户端缓存)
  • 缓存配置(force-cache, no-store, revalidate)
  • 缓存标签(revalidateTag, revalidatePath)
  • 按需重新验证
  • 基于时间的重新验证(ISR)
  • 缓存调试技术
  • 选择退出缓存

服务器操作完整指南

31+ 示例涵盖:

  • 基本服务器操作模式
  • 表单操作(渐进增强)
  • 按钮操作(程序化调用)
  • useFormStatus钩子(加载状态)
  • useActionState钩子(状态管理)
  • useOptimistic钩子(乐观UI)
  • 操作中的错误处理
  • 使用Zod验证
  • 返回JSON vs 重定向
  • 安全性(身份验证,CSRF)
  • 速率限制
  • 数据库事务

🎯 元数据API指南

26+ 示例涵盖:

  • 静态元数据(导出对象)
  • 动态元数据(generateMetadata)
  • 基于文件的元数据(icon.png, opengraph-image.png)
  • Open Graph元数据
  • Twitter卡片
  • JSON-LD结构化数据
  • 视口配置
  • PWA清单
  • Robots.txt
  • 站点地图生成

模式验证器

可执行的Python脚本,检查:

  • 服务器组件不使用仅限客户端的API
  • 客户端组件具有’use client’指令
  • 数据获取使用适当的缓存策略
  • 服务器操作标记为’use server’
  • 元数据API使用正确
  • 图像优化(使用<Image>而非<img>)
  • 重量级组件的动态导入

运行方式:python validate-patterns.py /path/to/src


快速参考

服务器与客户端组件决策树

是否需要交互性(onClick, onChange等)?
├─ 是 → 客户端组件('use client')
└─ 否 → 服务器组件(默认)

是否需要React钩子(useState, useEffect)?
├─ 是 → 客户端组件
└─ 否 → 服务器组件

是否需要浏览器API(window, localStorage)?
├─ 是 → 客户端组件
└─ 否 → 服务器组件

是否需要获取数据?
├─ 使用服务器组件(首选)
└─ 仅在数据必须位于客户端时使用客户端组件

组件是否纯粹是展示性的?
└─ 服务器组件(性能更好)

常见模式

1. 服务器组件数据获取

// app/projects/page.tsx
export default async function ProjectsPage() {
  const projects = await db.project.findMany()
  return <ProjectList projects={projects} />
}

2. 具有交互性的客户端组件

// components/ProjectCard.tsx
'use client'

import { useState } from 'react'

export function ProjectCard({ project }: Props) {
  const [loading, setLoading] = useState(false)

  const handleDelete = async () => {
    setLoading(true)
    await deleteProject(project.id)
    setLoading(false)
  }

  return (
    <div>
      <h2>{project.name}</h2>
      <button onClick={handleDelete} disabled={loading}>
        删除
      </button>
    </div>
  )
}

3. 带表单的服务器操作

// app/actions.ts
'use server'

export async function createProject(formData: FormData) {
  const name = formData.get('name') as string
  const project = await db.project.create({ data: { name } })
  revalidatePath('/projects')
  return { success: true, project }
}

// app/projects/new/page.tsx
import { createProject } from '@/app/actions'

export default function NewProjectPage() {
  return (
    <form action={createProject}>
      <input name="name" required />
      <button type="submit">创建</button>
    </form>
  )
}

4. 使用Suspense进行流式传输

// app/dashboard/page.tsx
import { Suspense } from 'react'

export default function DashboardPage() {
  return (
    <div>
      <Suspense fallback={<ProjectsSkeleton />}>
        <ProjectsAsync />
      </Suspense>
      <Suspense fallback={<UsersSkeleton />}>
        <UsersAsync />
      </Suspense>
    </div>
  )
}

async function ProjectsAsync() {
  const projects = await fetchProjects() // 慢查询
  return <ProjectList projects={projects} />
}

5. 动态元数据

// app/blog/[slug]/page.tsx
import type { Metadata } from 'next'

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug: string }>
}): Promise<Metadata> {
  const { slug } = await params
  const post = await fetchPost(slug)

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [post.coverImage],
    },
  }
}

Quetrex最佳实践

1. 默认为服务器组件

// ✅ 做:服务器组件(默认)
export default async function ProjectsPage() {
  const projects = await fetchProjects()
  return <ProjectList projects={projects} />
}

// ❌ 不做:不需要时使用客户端组件
'use client'
export default function ProjectsPage() {
  const [projects, setProjects] = useState([])
  useEffect(() => {
    fetchProjects().then(setProjects)
  }, [])
  return <ProjectList projects={projects} />
}

2. 使用适当的缓存策略

// 静态内容(永久缓存)
const categories = await fetch('https://api.example.com/categories', {
  cache: 'force-cache',
}).then(r => r.json())

// 动态内容(无缓存)
const user = await fetch('https://api.example.com/me', {
  cache: 'no-store',
}).then(r => r.json())

// ISR(每小时重新验证)
const products = await fetch('https://api.example.com/products', {
  next: { revalidate: 3600 },
}).then(r => r.json())

3. 实现适当的错误边界

// app/dashboard/error.tsx
'use client'

export default function DashboardError({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <h2>出错了!</h2>
      <button onClick={reset}>重试</button>
    </div>
  )
}

4. 使用加载状态

// app/dashboard/loading.tsx
export default function DashboardLoading() {
  return <DashboardSkeleton />
}

5. 优化图像

// ✅ 做:使用next/image
import Image from 'next/image'

export function ProjectCard({ project }) {
  return (
    <Image
      src={project.image}
      alt={project.name}
      width={400}
      height={300}
    />
  )
}

// ❌ 不做:使用<img>标签
export function ProjectCard({ project }) {
  return <img src={project.image} alt={project.name} />
}

常见错误避免

❌ 错误1:异步客户端组件

// ❌ 不做:这是语法错误
'use client'

export default async function BadComponent() {
  const data = await fetch('/api/data')
  return <div>{data}</div>
}

// ✅ 做:使用服务器组件或useEffect
export default async function GoodComponent() {
  const data = await fetch('/api/data')
  return <div>{data}</div>
}

❌ 错误2:服务器组件中的客户端API

// ❌ 不做:服务器组件不能使用浏览器API
export default function BadComponent() {
  const [state, setState] = useState(false) // 错误!
  return <div>{state}</div>
}

// ✅ 做:添加'use client'指令
'use client'

export default function GoodComponent() {
  const [state, setState] = useState(false)
  return <div>{state}</div>
}

❌ 错误3:缺少缓存策略

// ❌ 不做:缓存行为不明确
const data = await fetch('/api/data')

// ✅ 做:明确的缓存策略
const data = await fetch('/api/data', {
  cache: 'no-store', // 或 'force-cache', 或 { next: { revalidate: 60 } }
})

❌ 错误4:不使用<Image>

// ❌ 不做:未优化的图像
<img src="/logo.png" alt="Logo" />

// ✅ 做:使用Next.js图像优化
<Image src="/logo.png" alt="Logo" width={200} height={100} />

故障排除

错误:“您正在导入一个需要useState的组件…”

解决方案: 向组件文件添加'use client'

错误:“async/await在客户端组件中无效”

解决方案: 移除'use client'或使用useEffect代替异步组件。

错误:“process未定义”

解决方案: 客户端组件中的环境变量需要NEXT_PUBLIC_前缀。

错误:“Headers已发送”

解决方案: 发送响应后不要使用headers()cookies()。在任何流式传输之前调用它们。


官方文档


验证

运行模式验证器检查您的代码:

python .claude/skills/nextjs-15-specialist/validate-patterns.py src/

验证器检查:

  • ✅ 异步客户端组件(禁止)
  • ✅ 服务器组件中的客户端API
  • ✅ 'use client’指令放置
  • ✅ 服务器操作异步函数
  • ✅ 图像优化
  • ✅ 动态路由中的元数据
  • ✅ 重量级组件的动态导入
  • ✅ Fetch缓存策略
  • ✅ 路由段配置

总结

此技能确保您:

  1. 选择正确的组件类型(服务器 vs 客户端)
  2. 实现适当的数据获取模式
  3. 使用适当的缓存策略
  4. 正确处理服务器操作
  5. 优化元数据和SEO
  6. 避免常见的Next.js错误
  7. 遵循Quetrex的架构指南

如有疑问:

  • 阅读特定指南(上方链接)
  • 运行验证器
  • 检查官方Next.js 15文档
  • 默认为服务器组件

最后更新:2025-11-23 Next.js版本:15.5 总示例:150+ 总行数:4,000+