名称: nextjs-app-router 描述: 精通Next.js App Router模式,包括路由组、并行路由、拦截路由、布局和加载状态。 允许工具: 读取、写入、编辑、Bash、Glob、Grep
Next.js App Router 技能
为使用高级路由模式和约定实现Next.js App Router提供专家级协助。
能力
- 使用路由组设计应用目录结构
- 实现并行和拦截路由
- 配置布局、模板和加载状态
- 设置错误边界和未找到页面
- 使用Suspense实现流式渲染
- 为API端点配置路由处理器
使用场景
当您需要时调用此技能:
- 为复杂路由构建应用目录结构
- 使用拦截实现模态路由
- 创建并行路由布局
- 配置流式渲染和加载状态
- 构建API路由处理器
输入参数
| 参数 | 类型 | 是否必需 | 描述 |
|---|---|---|---|
| routeType | 字符串 | 是 | 页面、布局、路由、加载、错误 |
| routePath | 字符串 | 是 | 应用目录中的路由路径 |
| features | 数组 | 否 | 并行、拦截、分组 |
| streaming | 布尔值 | 否 | 启用Suspense流式渲染 |
配置示例
{
"routeType": "page",
"routePath": "/dashboard/analytics",
"features": ["parallel", "loading"],
"streaming": true
}
路由结构模式
路由组
app/
├── (auth)/
│ ├── login/
│ │ └── page.tsx
│ ├── register/
│ │ └── page.tsx
│ └── layout.tsx # 认证专用布局
├── (dashboard)/
│ ├── analytics/
│ │ └── page.tsx
│ ├── settings/
│ │ └── page.tsx
│ └── layout.tsx # 带侧边栏的仪表板布局
├── (marketing)/
│ ├── about/
│ │ └── page.tsx
│ ├── pricing/
│ │ └── page.tsx
│ └── layout.tsx # 营销布局
└── layout.tsx # 根布局
并行路由
app/
├── @modal/
│ ├── (.)photos/[id]/
│ │ └── page.tsx # 模态视图
│ └── default.tsx
├── @sidebar/
│ ├── default.tsx
│ └── feed/
│ └── page.tsx
├── photos/
│ └── [id]/
│ └── page.tsx # 全页面视图
├── layout.tsx
└── page.tsx
// app/layout.tsx
export default function Layout({
children,
modal,
sidebar,
}: {
children: React.ReactNode;
modal: React.ReactNode;
sidebar: React.ReactNode;
}) {
return (
<html>
<body>
<div className="flex">
<aside>{sidebar}</aside>
<main>{children}</main>
</div>
{modal}
</body>
</html>
);
}
拦截路由
app/
├── @modal/
│ └── (.)photos/[id]/ # 从同级拦截
│ └── page.tsx
├── feed/
│ └── @modal/
│ └── (..)photos/[id]/ # 从父级拦截
│ └── page.tsx
└── photos/
└── [id]/
└── page.tsx
// app/@modal/(.)photos/[id]/page.tsx
import { Modal } from '@/components/modal';
import Photo from '@/components/photo';
export default function PhotoModal({
params: { id },
}: {
params: { id: string };
}) {
return (
<Modal>
<Photo id={id} />
</Modal>
);
}
加载和错误状态
// app/dashboard/loading.tsx
export default function DashboardLoading() {
return (
<div className="animate-pulse">
<div className="h-8 bg-gray-200 rounded w-1/4 mb-4" />
<div className="h-64 bg-gray-200 rounded" />
</div>
);
}
// app/dashboard/error.tsx
'use client';
export default function DashboardError({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
return (
<div className="p-4 bg-red-50 rounded">
<h2 className="text-red-800 font-bold">出错了!</h2>
<p className="text-red-600">{error.message}</p>
<button
onClick={reset}
className="mt-2 px-4 py-2 bg-red-600 text-white rounded"
>
重试
</button>
</div>
);
}
路由处理器
// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const searchParams = request.nextUrl.searchParams;
const query = searchParams.get('query');
const users = await db.user.findMany({
where: query ? { name: { contains: query } } : undefined,
});
return NextResponse.json(users);
}
export async function POST(request: NextRequest) {
const body = await request.json();
const user = await db.user.create({
data: body,
});
return NextResponse.json(user, { status: 201 });
}
// app/api/users/[id]/route.ts
export async function GET(
request: NextRequest,
{ params }: { params: { id: string } }
) {
const user = await db.user.findUnique({
where: { id: params.id },
});
if (!user) {
return NextResponse.json(
{ error: '用户未找到' },
{ status: 404 }
);
}
return NextResponse.json(user);
}
使用Suspense的流式渲染
// app/dashboard/page.tsx
import { Suspense } from 'react';
import { Analytics, RecentActivity, Stats } from '@/components';
import { StatsSkeleton, ActivitySkeleton } from '@/components/skeletons';
export default function Dashboard() {
return (
<div className="grid gap-4">
<Suspense fallback={<StatsSkeleton />}>
<Stats />
</Suspense>
<div className="grid grid-cols-2 gap-4">
<Suspense fallback={<ActivitySkeleton />}>
<RecentActivity />
</Suspense>
<Suspense fallback={<div>加载分析中...</div>}>
<Analytics />
</Suspense>
</div>
</div>
);
}
最佳实践
- 使用路由组进行组织而不影响URL
- 实现loading.tsx以提供即时反馈
- 使用error.tsx进行优雅的错误处理
- 利用并行路由实现复杂布局
- 使用拦截路由实现模态模式
目标流程
- nextjs全栈开发
- 前端架构设计
- app-router迁移
- 性能优化