应用路由器Skill app-router

此技能提供Next.js App Router的全面指导,帮助开发者创建和管理路由、布局、加载状态、错误边界等,优化前端应用结构。关键词:Next.js, App Router, 路由, 布局, 组件, 前端开发。

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

名称: 应用路由器 描述: 当用户要求“创建Next.js路由”、“添加页面”、“设置布局”、“实现加载状态”、“添加错误边界”、“组织路由”、“创建动态路由”,或需要指导Next.js App Router文件约定和路由模式时,应使用此技能。 版本: 1.0.0

Next.js应用路由器模式

概述

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

核心文件约定

路由文件

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

文件 用途
page.tsx 路由的独特UI,使路由公开可访问
layout.tsx 共享的UI包装器,在导航间保持状态
loading.tsx 使用React Suspense的加载UI
error.tsx 路由段的错误边界
not-found.tsx 404响应的UI
template.tsx 类似于布局,但在导航时重新渲染
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              # / (主页)
├── about/
│   └── page.tsx          # /about
└── blog/
    ├── page.tsx          # /blog
    └── [slug]/
        └── page.tsx      # /blog/:slug

页面组件

页面默认是服务器组件:

// app/about/page.tsx
export default function AboutPage() {
  return (
    <main>
      <h1>关于我们</h1>
      <p>欢迎来到我们公司。</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">加载中...</div>
}

错误边界

优雅地处理错误:

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

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

路由组

组织路由而不影响URL结构:

app/
├── (marketing)/
│   ├── layout.tsx        # 营销布局
│   ├── about/page.tsx    # /about
│   └── contact/page.tsx  # /contact
└── (shop)/
    ├── layout.tsx        # 商店布局
    └── products/page.tsx # /products

元数据

静态元数据

// app/about/page.tsx
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: '关于我们',
  description: '了解更多关于我们公司的信息',
}

动态元数据

// 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 - 并行和拦截路由