nextjs-patterns

GitHub

提供 Next.js 生产级应用开发的最佳实践,涵盖 App Router、Server Components、缓存策略及全栈架构模式,指导前后端分离与组件设计。

categories/frontend/nextjs-patterns/SKILL.md cosmicstack-labs/mercury-agent-skills

触发场景

询问 Next.js 项目结构规范 查询 Server Components 与 Client Components 的使用场景 了解 App Router 路由与数据获取机制

安装

npx skills add cosmicstack-labs/mercury-agent-skills --skill nextjs-patterns -g -y
更多选项

非标准路径

npx skills add https://github.com/cosmicstack-labs/mercury-agent-skills/tree/main/categories/frontend/nextjs-patterns -g -y

不安装直接使用

npx skills use cosmicstack-labs/mercury-agent-skills@nextjs-patterns

指定 Agent (Claude Code)

npx skills add cosmicstack-labs/mercury-agent-skills --skill nextjs-patterns -a claude-code -g -y

安装 repo 全部 skill

npx skills add cosmicstack-labs/mercury-agent-skills --all -g -y

预览 repo 内 skill

npx skills add cosmicstack-labs/mercury-agent-skills --list

SKILL.md

Frontmatter
{
    "name": "nextjs-patterns",
    "metadata": {
        "tags": [
            "nextjs",
            "react",
            "server-components",
            "app-router",
            "full-stack",
            "ssr",
            "ssg",
            "isr"
        ],
        "author": "cosmicstack-labs",
        "version": "1.0.0",
        "category": "frontend"
    },
    "description": "Next.js best practices, server components, app router patterns, caching strategies, and full-stack architecture"
}

Next.js Patterns

Comprehensive guide to building production-grade Next.js applications with the App Router, Server Components, and modern React patterns.

Core Architecture

App Router vs Pages Router

Aspect App Router Pages Router
Components Server Components by default Client Components only
Routing File-system based with layout nesting File-system based, flat
Data Fetching Server-side fetch, use, cache primitives getServerSideProps, getStaticProps
Loading States loading.js files Manual implementation
Error Handling error.js files Manual implementation
Streaming Built-in with Suspense boundaries Not supported

Project Structure

my-app/
├── app/
│   ├── layout.tsx          # Root layout
│   ├── page.tsx            # Home page
│   ├── loading.tsx         # Root loading state
│   ├── error.tsx           # Root error boundary
│   ├── not-found.tsx       # 404 page
│   ├── (auth)/             # Route group
│   │   ├── login/page.tsx
│   │   └── register/page.tsx
│   ├── dashboard/
│   │   ├── layout.tsx      # Dashboard layout
│   │   ├── page.tsx        # Dashboard home
│   │   ├── loading.tsx
│   │   └── settings/
│   │       └── page.tsx
│   └── api/
│       └── [...route]/route.ts  # API handlers
├── components/
│   ├── ui/                 # Shared UI components
│   └── features/           # Feature-specific components
├── lib/
│   ├── db.ts              # Database client
│   ├── auth.ts            # Auth utilities
│   └── utils.ts           # Shared utilities
└── public/
    └── images/

Server Components (RSC)

When to Use Server vs Client

// ✅ SERVER COMPONENT (default) — Use for:
// - Data fetching from databases/APIs
// - Accessing backend resources directly
// - Keeping sensitive logic on server
// - Reducing client bundle size
// - SEO-critical content
async function ProductPage({ params }: { params: { id: string } }) {
  const product = await db.product.findUnique({ where: { id: params.id } });
  return <ProductDetail product={product} />;
}

// ✅ CLIENT COMPONENT — Use for:
// - Interactivity (onClick, onChange, etc.)
// - useState, useReducer, useEffect
// - Browser-only APIs
// - Custom hooks
// - Event listeners
'use client';
function AddToCartButton({ productId }: { productId: string }) {
  const [added, setAdded] = useState(false);
  return (
    <button onClick={() => { addToCart(productId); setAdded(true); }}>
      {added ? 'Added!' : 'Add to Cart'}
    </button>
  );
}

Composing Server and Client Components

// ✅ CORRECT: Server Component wrapping Client Component
async function ProductPage({ id }: { id: string }) {
  const product = await getProduct(id);
  // Server component passes data as props to client component
  return (
    <div>
      <ProductDetails product={product} />
      <AddToCartButton productId={id} />
    </div>
  );
}

// ❌ WRONG: Client Component importing Server Component
'use client';
import ServerComponent from './ServerComponent'; // ❌ Won't work
function ClientPage() {
  return <ServerComponent />; // Error: Cannot import server component into client
}

// ✅ CORRECT: Pass Server Component as children
'use client';
function ClientLayout({ children }: { children: React.ReactNode }) {
  const [isOpen, setIsOpen] = useState(false);
  return (
    <div>
      <button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
      {isOpen && children} {/* Server component rendered here */}
    </div>
  );
}

Data Fetching Patterns

Server-Side Data Fetching

// app/products/page.tsx
async function ProductsPage() {
  // Direct database access — no API route needed
  const products = await db.product.findMany({
    take: 20,
    orderBy: { createdAt: 'desc' },
  });
  
  return <ProductGrid products={products} />;
}

// With parallel fetching for multiple data sources
async function DashboardPage() {
  const [user, posts, analytics] = await Promise.all([
    getCurrentUser(),
    getRecentPosts(),
    getAnalytics(),
  ]);
  
  return (
    <DashboardShell user={user}>
      <PostList posts={posts} />
      <AnalyticsChart data={analytics} />
    </DashboardShell>
  );
}

Revalidation Strategies

// Time-based revalidation (ISR)
export const revalidate = 3600; // Revalidate every hour

// On-demand revalidation (revalidateTag / revalidatePath)
'use server';
export async function publishPost(formData: FormData) {
  const post = await createPost(formData);
  revalidateTag('posts');
  revalidatePath('/blog');
  redirect(`/blog/${post.slug}`);
}

// Dynamic data — no caching
export const dynamic = 'force-dynamic';

// Static data — cache forever
export const dynamic = 'force-static';

Streaming with Suspense

// app/dashboard/page.tsx
import { Suspense } from 'react';

export default function DashboardPage() {
  return (
    <div>
      <h1>Dashboard</h1>
      <Suspense fallback={<DashboardSkeleton />}>
        <DashboardContent />
      </Suspense>
      <Suspense fallback={<ActivitySkeleton />}>
        <RecentActivity />
      </Suspense>
    </div>
  );
}

async function DashboardContent() {
  const data = await fetchDashboardData(); // This suspends
  return <DashboardCharts data={data} />;
}

async function RecentActivity() {
  const activity = await fetchRecentActivity(); // This loads independently
  return <ActivityFeed items={activity} />;
}

Route Handlers & API Patterns

// app/api/products/route.ts
export async function GET(request: Request) {
  const { searchParams } = new URL(request.url);
  const page = parseInt(searchParams.get('page') || '1');
  const limit = parseInt(searchParams.get('limit') || '20');
  
  const products = await db.product.findMany({
    skip: (page - 1) * limit,
    take: limit,
  });
  
  return Response.json({ products, page, limit });
}

export async function POST(request: Request) {
  const body = await request.json();
  const product = await db.product.create({ data: body });
  return Response.json(product, { status: 201 });
}

Common Patterns

Route Groups for Organization

// app/(marketing)/page.tsx — Public marketing pages
// app/(dashboard)/page.tsx — Authenticated dashboard
// app/(auth)/login/page.tsx — Auth pages with different layout

Middleware for Auth

// middleware.ts
export function middleware(request: NextRequest) {
  const token = request.cookies.get('session');
  const { pathname } = request.nextUrl;
  
  // Protected routes
  if (pathname.startsWith('/dashboard') && !token) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  
  return NextResponse.next();
}

Error Boundaries

// app/dashboard/error.tsx
'use client';
export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  return (
    <div>
      <h2>Something went wrong!</h2>
      <button onClick={() => reset()}>Try again</button>
    </div>
  );
}

Common Mistakes

  1. Overusing client components: Default to Server Components. Only add 'use client' when you need interactivity.
  2. Nesting fetch calls sequentially: Use Promise.all() for independent data fetches.
  3. Ignoring caching defaults: Understand Next.js fetch caching. Use no-store or revalidate explicitly.
  4. Mixing server/client component boundaries incorrectly: Pass Server Components as children to Client Components, don't import them.
  5. Forgetting error and loading states: Always provide error boundaries and loading skeletons for streaming.

版本历史

  • 38e2523 当前 2026-07-05 19:39

同 Skill 集合

categories/ai-ml/agent-audit-logging/SKILL.md
categories/ai-ml/agent-handoff-protocols/SKILL.md
categories/ai-ml/agent-health-monitoring/SKILL.md
categories/ai-ml/agent-task-delegation/SKILL.md
categories/ai-ml/ai-agent-design/SKILL.md
categories/ai-ml/error-recovery-retry/SKILL.md
categories/ai-ml/memory-management/SKILL.md
categories/ai-ml/prompt-engineering/SKILL.md
categories/ai-ml/prompt-version-management/SKILL.md
categories/ai-ml/routerbase-model-gateway/SKILL.md
categories/ai-ml/token-budget-tracking/SKILL.md
categories/automation/daily-briefing/SKILL.md
categories/automation/screenshot/SKILL.md
categories/automation/shell-scripting/SKILL.md
categories/automation/twitter-account-manager/SKILL.md
categories/automation/workflow-automation/SKILL.md
categories/automation/x-twitter-automation/SKILL.md
categories/backend/api-design/SKILL.md
categories/backend/authentication-authorization/SKILL.md
categories/backend/caching-strategies/SKILL.md
categories/backend/database-design/SKILL.md
categories/backend/message-queues/SKILL.md
categories/backend/microservices/SKILL.md
categories/backend/nodejs-patterns/SKILL.md
categories/backend/python-patterns/SKILL.md
categories/backend/serverless-patterns/SKILL.md
categories/business/event-staffing-compliance/SKILL.md
categories/business/event-staffing-ordering/SKILL.md
categories/business/negotiation/SKILL.md
categories/business/startup-strategy/SKILL.md
categories/career/career-planning/SKILL.md
categories/career/interview-prep/SKILL.md
categories/career/linkedin-optimization/SKILL.md
categories/career/resume-writing/SKILL.md
categories/career/salary-negotiation/SKILL.md
categories/creative-personal-development/content-repurposer/SKILL.md
categories/creative-personal-development/daily-standup-journal/SKILL.md
categories/creative-personal-development/decision-matrix/SKILL.md
categories/creative-personal-development/idea-validator/SKILL.md
categories/creative-personal-development/meeting-note-summarizer/SKILL.md
categories/creative-personal-development/personal-branding-statement/SKILL.md
categories/creative-personal-development/storytelling-advisor/SKILL.md
categories/creative-personal-development/time-blocking-scheduler/SKILL.md
categories/data/data-pipeline/SKILL.md
categories/design/accessibility/SKILL.md
categories/design/ui-design-system/SKILL.md
categories/development/api-documentation/SKILL.md
categories/development/architecture-decision-records/SKILL.md
categories/development/clean-code/SKILL.md
categories/development/code-review/SKILL.md

元信息

文件数
0
版本
4c57cf2
Hash
b826187b
收录时间
2026-07-05 19:39

首页 - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-09 12:18
浙ICP备14020137号-1 $访客地图$