技术4 min read

Next.js App Router 入门指南

什么是 App Router?

Next.js 13 引入了全新的 App Router,它基于 React Server Components 构建,带来了更好的性能和开发体验。

App Router 是 Next.js 的未来方向,它提供了更灵活的路由系统、更好的布局支持,以及更高效的渲染方式。

目录结构

App Router 使用 app 目录来组织路由:

app/
├── layout.tsx      # 根布局
├── page.tsx        # 首页
├── about/
│   └── page.tsx    # 关于页面
├── blog/
│   ├── page.tsx    # 博客列表
│   └── [slug]/
│       └── page.tsx # 博客详情
└── api/
    └── route.ts    # API 路由

关键特性

1. 服务端组件

默认情况下,App Router 中的组件是服务端组件。这意味着它们在服务器上渲染,减少了客户端 JavaScript 的大小。

// 这是一个服务端组件(默认)
export default async function ServerComponent() {
  const data = await fetch('https://api.example.com/data');
  const posts = await data.json();

  return (
    <div>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.excerpt}</p>
        </article>
      ))}
    </div>
  );
}

2. 客户端组件

需要交互的组件需要添加 'use client' 指令:

'use client';

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>当前计数: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        增加
      </button>
      <button onClick={() => setCount(0)}>
        重置
      </button>
    </div>
  );
}

3. 布局系统

布局在导航时不会重新渲染,这使得状态保持成为可能:

// app/layout.tsx
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="zh">
      <body>
        <header>
          <nav>导航栏</nav>
        </header>
        <main>{children}</main>
        <footer>页脚</footer>
      </body>
    </html>
  );
}

4. 加载状态

使用 loading.tsx 文件创建加载状态:

// app/blog/loading.tsx
export default function Loading() {
  return (
    <div className="loading">
      <div className="spinner" />
      <p>加载中...</p>
    </div>
  );
}

5. 错误处理

使用 error.tsx 文件处理错误:

'use client';

// app/blog/error.tsx
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <div>
      <h2>出错了!</h2>
      <p>{error.message}</p>
      <button onClick={() => reset()}>重试</button>
    </div>
  );
}

与 Pages Router 的对比

特性 App Router Pages Router
React Server Components ✅ 支持 ❌ 不支持
布局嵌套 ✅ 原生支持 ⚠️ 需要自定义
数据获取 async/await getServerSideProps
流式渲染 ✅ 支持 ❌ 不支持
加载状态 loading.tsx 自定义实现
错误处理 error.tsx 自定义实现

数据获取

App Router 支持在组件中直接获取数据:

// 服务端组件中获取数据
async function getPosts() {
  const res = await fetch('https://api.example.com/posts');
  if (!res.ok) {
    throw new Error('获取文章失败');
  }
  return res.json();
}

export default async function BlogPage() {
  const posts = await getPosts();

  return (
    <div>
      <h1>博客文章</h1>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.content}</p>
        </article>
      ))}
    </div>
  );
}

总结

App Router 是 Next.js 的未来方向,它提供了更好的性能和更灵活的布局系统。对于新项目,强烈建议使用 App Router。

如果你正在使用 Pages Router,也不必急于迁移。两种路由系统可以共存,你可以逐步将页面迁移到 App Router。


相关资源: