Next.jsAppRouter前端开发专家Skill frontend-nextjs-app-router

Next.js App Router前端开发专家技能,专注于现代React应用架构。提供Next.js 13+ App Router完整解决方案,包括服务器组件优化、动态路由配置、嵌套布局实现、性能优化策略和ERP系统开发。关键词:Next.js App Router、React服务器组件、前端架构、动态路由、性能优化、TypeScript、shadcn/ui、SEO优化、企业级应用开发。

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

name: frontend-nextjs-app-router description: | 用于处理Next.js App Router相关任务 - 在/app/目录下创建页面、设置动态路由([id]/page.tsx)、实现嵌套布局/模板(layout.tsx)、优化服务器/客户端组件、或构建ERP角色页面(管理员/教师/学生仪表板)。自动用于所有/app/目录操作、动态路由和App Router特定功能。

Next.js App Router专家

概述

Next.js App Router开发专家指导,包括页面创建、动态路由、嵌套布局、服务器/客户端组件优化和ERP角色仪表板。

核心能力

1. 页面创建 (/app/.../page.tsx)

规则:

  • 默认使用服务器组件(无’use client’指令)
  • 使用fetch()或ORM查询直接进行异步数据获取
  • 初始数据加载不使用useEffect
  • 使用Suspense边界处理加载状态
  • 通过generateMetadata()设置SEO元数据

模板:

// app/dashboard/page.tsx
import { Suspense } from 'react';
import { TaskList } from '@/components/TaskList';
import { TaskListSkeleton } from '@/components/TaskListSkeleton';

export const metadata = {
  title: '仪表板',
  description: '您的任务管理仪表板',
};

export default async function DashboardPage() {
  const tasks = await fetchTasks();

  return (
    <main className="p-4">
      <h1>仪表板</h1>
      <Suspense fallback={<TaskListSkeleton />}>
        <TaskList initialTasks={tasks} />
      </Suspense>
    </main>
  );
}

2. 动态路由 ([slug]/page.tsx)

使用场景:

  • 学生档案:app/students/[studentId]/page.tsx
  • 任务详情:app/tasks/[taskId]/page.tsx
  • 课程页面:app/courses/[courseId]/page.tsx

规则:

  • params属性提取参数(只读)
  • 使用generateMetadata()进行SEO优化
  • 使用not-found.tsx处理404

模板:

// app/students/[studentId]/page.tsx
import { notFound } from 'next/navigation';

type Params = Promise<{ studentId: string }>;

export async function generateMetadata({ params }: { params: Params }) {
  const { studentId } = await params;
  const student = await getStudent(studentId);

  if (!student) return { title: '学生未找到' };

  return {
    title: `${student.name} - 学生档案`,
  };
}

export default async function StudentProfile({ params }: { params: Params }) {
  const { studentId } = await params;
  const student = await getStudent(studentId);

  if (!student) notFound();

  return <StudentProfileView student={student} />;
}

3. 并行路由 (@folder)

使用场景:

  • 仪表板变体:app/dashboard@(admin|teacher)/page.tsx
  • 拆分布局:app/settings@(user|organization)/layout.tsx

模板:

// app/dashboard/@admin/page.tsx - 管理员仪表板
export default function AdminDashboard() {
  return <AdminPanel />;
}

// app/dashboard/@teacher/page.tsx - 教师仪表板
export default function TeacherDashboard() {
  return <TeacherPanel />;
}

4. 布局与模板

根布局 (app/layout.tsx):

import { Providers } from '@/components/Providers';
import './globals.css';

export const metadata = {
  title: 'Todo Evolution',
  description: '教育任务管理',
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="zh-CN">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

嵌套布局 (app/dashboard/layout.tsx):

import { DashboardNav } from '@/components/DashboardNav';

export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <div className="flex min-h-screen">
      <DashboardNav />
      <main className="flex-1 p-6">{children}</main>
    </div>
  );
}

模板 (app/tasks/template.tsx):

// 导航时重新执行,保留表单状态
export default function TasksTemplate({ children }: { children: React.ReactNode }) {
  return (
    <div className="bg-gray-50 min-h-screen">
      <header className="bg-white shadow">
        <h1>任务</h1>
      </header>
      {children}
    </div>
  );
}

5. 服务器与客户端组件

服务器组件用于:

  • 数据获取
  • 直接数据库查询
  • 静态内容
  • 仅服务器操作

客户端组件 ('use client') 用于:

  • 浏览器API (window, localStorage)
  • 事件处理程序 (onClick, onSubmit)
  • React钩子 (useState, useEffect)
  • 状态管理 (Zustand, Redux)
  • 交互性
// 服务器组件(默认)
export default async function TaskList() {
  const tasks = await fetchTasks(); // 直接数据库查询
  return <div>{tasks.map(/* ... */)}</div>;
}

// 客户端组件
'use client';
import { useTaskStore } from '@/store/tasks';

export function TaskFilter() {
  const { filter, setFilter } = useTaskStore();
  return <button onClick={() => setFilter('all')}>所有任务</button>;
}

6. ERP角色页面

角色守卫:

// app/admin/page.tsx
import { requireRole } from '@/lib/auth';
import { redirect } from 'next/navigation';

export default async function AdminPage() {
  const session = await getSession();

  if (session?.role !== 'admin') {
    redirect('/unauthorized');
  }

  return <AdminDashboard />;
}

KPI仪表板 (Recharts):

'use client';
import { BarChart, Bar, XAxis, YAxis, Tooltip } from 'recharts';

export function TaskKPIChart({ data }: { data: TaskStats[] }) {
  return (
    <BarChart width={600} height={300} data={data}>
      <XAxis dataKey="date" />
      <YAxis />
      <Tooltip />
      <Bar dataKey="completed" fill="#22c55e" />
    </BarChart>
  );
}

7. 错误与加载状态

错误边界 (error.tsx):

'use client';
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <div>
      <h2>出错了!</h2>
      <button onClick={reset}>重试</button>
    </div>
  );
}

加载状态 (loading.tsx):

export default function Loading() {
  return <div className="animate-pulse">加载中...</div>;
}

// 或使用Suspense:
export default async function Page() {
  return (
    <Suspense fallback={<Loading />}>
      <Content />
    </Suspense>
  );
}

8. shadcn/ui集成

安装:

npx shadcn@latest add button card input dialog

在服务器组件中使用:

import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader } from '@/components/ui/card';

export default async function TaskPage() {
  const tasks = await getTasks();

  return (
    <Card>
      <CardHeader>任务</CardHeader>
      <CardContent>
        {tasks.map(task => (
          <div key={task.id}>{task.title}</div>
        ))}
      </CardContent>
    </Card>
  );
}

工作流决策树

用户请求分析实施路径

  1. “创建仪表板/管理员页面” → 使用服务器组件的page.tsx → 异步数据获取 → 如需导航则添加layout.tsx

  2. “动态学生档案” → 创建[studentId]/page.tsx → 提取参数 → 添加generateMetadata() → 如需则创建not-found.tsx

  3. “添加共享布局” → 在目标文件夹创建layout.tsx → 如需则用Providers包装 → 保持子组件渲染

  4. “添加表单”'use client'组件 → 使用useState管理表单数据 → 使用服务器操作提交或API路由

  5. “KPI图表/分析”'use client'用于Recharts → 服务器组件父级进行数据获取 → 通过props传递数据

质量检查清单

任务完成前检查:

  • [ ] TypeScript严格模式已启用
  • [ ] 默认使用服务器组件
  • [ ] 仅在必要时使用'use client'
  • [ ] 使用generateMetadata()进行SEO优化
  • [ ] 异步数据使用Suspense边界
  • [ ] 需要时使用错误边界(error.tsx)
  • [ ] 无水合不匹配
  • [ ] 性能优化(无阻塞渲染)
  • [ ] 移动优先响应式设计
  • [ ] 可访问性(ARIA标签,键盘导航)

常见模式

模式1:服务器组件 + 客户端组件混合

// 服务器组件
export default async function Page() {
  const tasks = await fetchTasks();
  return <TaskList tasks={tasks} />; // 客户端组件用于交互性
}

'use client';
function TaskList({ tasks }: { tasks: Task[] }) {
  const [filter, setFilter] = useState('all');
  const filtered = tasks.filter(/* ... */);
  return <div>{filtered.map(/* ... */)}</div>;
}

模式2:路由组组织

app/
  (marketing)/     # 组:无URL段
    about/page.tsx
    contact/page.tsx
  (dashboard)/      # 组:无URL段
    layout.tsx
    page.tsx

模式3:API路由(路由处理器)

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

export async function GET() {
  const tasks = await db.query.tasks.findMany();
  return NextResponse.json(tasks);
}

export async function POST(request: Request) {
  const body = await request.json();
  const task = await createTask(body);
  return NextResponse.json(task, { status: 201 });
}

触发示例

  • “创建仪表板页面” → 生成带服务器组件的app/dashboard/page.tsx
  • “动态学生档案路由” → 带参数和元数据的app/students/[studentId]/page.tsx
  • “添加共享布局” → 带子组件的app/dashboard/layout.tsx
  • “带图表的管理面板” → 服务器组件 + 客户端图表组件
  • “创建登录页面” → 'use client'表单组件 + API路由
  • “自定义404页面” → app/not-found.tsx
  • “错误处理” → app/dashboard/error.tsx

参考

高级模式请参阅references/app-router-patterns.md,路由处理器示例请参阅references/api-routes.md