Next.js15模式与最佳实践Skill nextjs-15-patterns

本技能是关于 Next.js 15 框架中 App Router 的核心开发模式与最佳实践的总结。它详细讲解了服务器组件与客户端组件的区别与使用场景、如何利用 Server Actions 进行数据变更、高效的数据获取策略、路由处理器的构建、元数据的动态生成、并行路由的实现,以及一系列提升应用性能与开发效率的最佳实践。关键词包括:Next.js 15, App Router, 服务器组件, 客户端组件, Server Actions, 数据获取, 路由处理器, 元数据, 并行路由, 最佳实践, React 框架, 全栈开发。

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

name: nextjs-15-patterns description: Next.js 15 App Router 模式与最佳实践。

Next.js 15 模式

服务器组件 vs 客户端组件

默认:服务器组件

// app/users/page.tsx - 服务器组件(默认)
export default async function UsersPage() {
  const users = await getUsers(); // 直接访问数据库
  return <UserList users={users} />;
}

客户端组件(需要时使用)

// components/counter.tsx
'use client';

import { useState } from 'react';

export function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

服务器操作

// actions/user-actions.ts
'use server';

import { revalidatePath } from 'next/cache';
import { z } from 'zod';

const CreateUserSchema = z.object({
  name: z.string().min(1),
  email: z.string().email(),
});

export async function createUser(formData: FormData) {
  const validated = CreateUserSchema.safeParse({
    name: formData.get('name'),
    email: formData.get('email'),
  });

  if (!validated.success) {
    return { error: validated.error.flatten() };
  }

  const user = await db.insert(users).values(validated.data).returning();
  revalidatePath('/users');
  return { data: user };
}

数据获取

在服务器组件中

// 直接使用 async/await - 无需 useEffect
async function UserProfile({ id }: { id: string }) {
  const user = await getUser(id);
  if (!user) notFound();
  return <Profile user={user} />;
}

加载状态处理

// app/users/loading.tsx
export default function Loading() {
  return <UserListSkeleton />;
}

错误处理

// app/users/error.tsx
'use client';

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

路由处理器(API)

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

export async function GET() {
  const users = await getUsers();
  return NextResponse.json(users);
}

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

元数据

// app/users/[id]/page.tsx
import { Metadata } from 'next';

export async function generateMetadata({
  params,
}: {
  params: { id: string };
}): Promise<Metadata> {
  const user = await getUser(params.id);
  return {
    title: user?.name ?? '用户',
    description: `${user?.name} 的个人资料`,
  };
}

并行路由

app/
├── @modal/
│   └── (.)photo/[id]/page.tsx  # 拦截式模态框
├── layout.tsx
└── page.tsx

最佳实践

  1. 优先使用服务器组件 - 仅在需要时使用 ‘use client’
  2. 数据获取就近原则 - 在数据使用的地方获取数据
  3. 使用服务器操作 - 用于数据变更,而非 API 路由
  4. 结合 Suspense 实现流式渲染 - 实现渐进式加载
  5. 验证所有输入 - 在服务器操作中使用 Zod 进行验证