mcpField
A
app-router

app-router

github.com/davepoon开发3.7k147 次安装今天更新
代码仓库

关于 app-router

介绍 Next.js App Router 路由模式的参考技能,帮助开发者使用 app 目录组织路由与布局,涵盖动态路由以及加载和错误状态。

主要功能

  1. 01路由与特殊文件约定
  2. 02动态路由和全匹配路由
  3. 03嵌套布局与路由组
  4. 04加载与错误状态
  5. 05静态和动态元数据

适用场景

  1. 01组织 Next.js 应用中的路由
  2. 02在不改变 URL 的情况下整理布局
  3. 03构建使用动态路由参数的页面
  4. 04添加加载和错误界面

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/davepoon/buildwithclaude --skill app-router

安装后在 Claude Code 中输入/app-router确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

examples/
dynamic-routes.md
parallel-routes.md
references/
layouts-templates.md
loading-error-states.md
routing-conventions.md

详细介绍

Next.js App Router 模式

概述

App Router 是 Next.js 基于文件系统的路由器,构建于 React Server Components 之上。它使用 app/ 目录结构,其中的文件夹定义路由,特殊文件控制 UI 行为。

核心文件约定

路由文件

每个路由段由一个文件夹定义。文件夹中的特殊文件控制行为:

文件用途
page.tsx路由的专属 UI,使路由可公开访问
layout.tsx共享 UI 外壳,在导航期间保留状态
loading.tsx使用 React Suspense 显示加载 UI
error.tsx路由段的错误边界
not-found.tsx404 响应的 UI
template.tsx类似 layout,但会在导航时重新渲染
default.tsx并行路由的回退内容
文件夹约定
模式用途示例
folder/路由段app/blog/ → /blog
[folder]/动态段app/blog/[slug]/ → /blog/:slug
[...folder]/全捕获段app/docs/[...slug]/ → /docs/*
[[...folder]]/可选全捕获段app/shop/[[...slug]]/ → /shop 或 /shop/*
(folder)/路由组(不影响 URL)app/(marketing)/about/ → /about
@folder/命名插槽(并行路由)app/@modal/login/
_folder/私有文件夹(不纳入路由)app/_components/

创建路由

基本路由结构

要创建新路由,请添加一个包含 page.tsx 的文件夹:

app/
├── page.tsx              # / (home)
├── about/
│   └── page.tsx          # /about
└── blog/
    ├── page.tsx          # /blog
    └── [slug]/
        └── page.tsx      # /blog/:slug
页面组件

页面默认是 Server Component:

// app/about/page.tsx
export default function AboutPage() {
  return (
    <main>
      <h1>About Us</h1>
      <p>Welcome to our company.</p>
    </main>
  )
}
动态路由

通过 params 属性访问路由参数:

// app/blog/[slug]/page.tsx
interface PageProps {
  params: Promise<{ slug: string }>
}

export default async function BlogPost({ params }: PageProps) {
  const { slug } = await params
  const post = await getPost(slug)

  return <article>{post.content}</article>
}

布局

根布局(必需)

每个应用都需要一个包含 <html> 和 <body> 的根布局:

// app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}
嵌套布局

布局会包裹其子级并保留状态:

// app/dashboard/layout.tsx
export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <div className="flex">
      <Sidebar />
      <main className="flex-1">{children}</main>
    </div>
  )
}

加载和错误状态

加载 UI

使用 Suspense 创建即时加载状态:

// app/dashboard/loading.tsx
export default function Loading() {
  return <div className="animate-pulse">Loading...</div>
}
错误边界

妥善处理错误:

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

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={reset}>Try again</button>
    </div>
  )
}

路由组

在不影响 URL 结构的情况下组织路由:

app/
├── (marketing)/
│   ├── layout.tsx        # Marketing layout
│   ├── about/page.tsx    # /about
│   └── contact/page.tsx  # /contact
└── (shop)/
    ├── layout.tsx        # Shop layout
    └── products/page.tsx # /products

元数据

静态元数据
// app/about/page.tsx
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'About Us',
  description: 'Learn more about our company',
}
动态元数据
// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
  const { slug } = await params
  const post = await getPost(slug)
  return { title: post.title }
}

关键模式

  1. 就近放置:将组件、测试和样式放在路由附近
  2. 私有文件夹:使用 _folder 存放非路由文件
  3. 路由组:使用 (folder) 进行组织,且不影响 URL
  4. 并行路由:使用 @slot 构建复杂布局
  5. 拦截路由:使用 (.) 模式创建模态框

资源

如需了解详细模式,请参阅:

  • references/routing-conventions.md - 完整的文件约定
  • references/layouts-templates.md - 布局组合模式
  • references/loading-error-states.md - Suspense 和错误处理
  • examples/dynamic-routes.md - 动态路由示例
  • examples/parallel-routes.md - 并行路由和拦截路由

评论

支持 Markdown