Skip to main content

nextjs-server-components

Use when next.js Server Components for optimal performance. Use when building data-intensive Next.js applications.

Quellinformationen

Repository
TheBushidoCollective/han
Letzte Quellaktivität
11. Februar 2026 um 17:47
Erkannte Sprache von SKILL.md
Englisch
Sterne
198
Forks
22

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
nextjs-server-components
user-invocable
false
description
Use when next.js Server Components for optimal performance. Use when building data-intensive Next.js applications.
allowed-tools
["Bash","Read"]
# Next.js Server Components Master Server Components in Next.js to build high-performance applications with server-side rendering and data fetching. ## Server Components Basics In Next.js App Router, all components are Server Components by default: ```typescript // app/posts/page.tsx (Server Component by default) async function getPosts() { const res = await fetch('https://api.example.com/posts', { next: { revalidate: 3600 } // Cache for 1 hour }); if (!res.ok) throw new Error('Failed to fetch posts'); return res.json(); } export default async function Posts() { const posts = await getPosts(); return ( <div> <h1>Blog Posts</h1> {posts.map((post: Post) => ( <article key={post.id}> <h2>{post.title}</h2> <p>{post.content}</p> <span>{new Date(post.date).toLocaleDateString()}</span> </article> ))} </div> ); } // Direct database access (server-only) import { db } from '@/lib/db'; export default async function Users() { const users = await db.user.findMany({ select: { id: true, name: true, email: true } }); return ( <div> {users.map(user => ( <div key={user.id}> {user.name} - {user.email} </div> ))} </div> ); } ``` ## Server vs Client Components Decision Tree ```typescript // Use Server Components when: // - Fetching data // - Accessing backend resources directly // - Keeping sensitive information on server // - Keeping large dependencies on server // Server Component (default) export default async function ServerComp() { const data = await fetchData(); return <div>{data}</div>; } // Use Client Components when: // - Using interactivity (onClick, onChange, etc.) // - Using state or lifecycle hooks (useState, useEffect) // - Using browser-only APIs (localStorage, window, etc.) // - Using custom hooks that depend on state/effects // - Using React Context // Client Component 'use client'; import { useState } from 'react'; export default function ClientComp() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> Count: {count} </button> ); } // Composition: Server Component with Client Component export default async function Page() { const data = await fetchData(); // Server-side return ( <div> <ServerContent data={data} /> <InteractiveButton /> {/* Client Component */} </div> ); } ``` ## Server Actions for Mutations ```typescript // app/actions.ts - Server Actions 'use server'; import { revalidatePath } from 'next/cache'; import { redirect } from 'next/navigation'; export async function createPost(formData: FormData) { const title = formData.get('title') as string; const content = formData.get('content') as string; const post = await db.post.create({ data: { title, content } }); revalidatePath('/posts'); redirect(`/posts/${post.id}`); } export async function updatePost(id: string, formData: FormData) { const title = formData.get('title') as string; const content = formData.get('content') as string; await db.post.update({ where: { id }, data: { title, content } }); revalidatePath(`/posts/${id}`); return { success: true }; } export async function deletePost(id: string) { await db.post.delete({ where: { id } }); revalidatePath('/posts'); } // app/posts/new/page.tsx - Using Server Actions export default function NewPost() { return ( <form action={createPost}> <input name="title" placeholder="Title" required /> <textarea name="content" placeholder="Content" required /> <button type="submit">Create Post</button> </form> ); } // With client-side enhancement 'use client'; import { useFormStatus, useFormState } from 'react-dom'; import { createPost } from './actions'; function SubmitButton() { const { pending } = useFormStatus(); return ( <button type="submit" disabled={pending}> {pending ? 'Creating...' : 'Create Post'} </button> ); } export default function NewPostForm() { const [state, formAction] = useFormState(createPost, null); return ( <form action={formAction}> <input name="title" required /> <textarea name="content" required /> {state?.error && <p className="error">{state.error}</p>} <SubmitButton /> </form> ); } ``` ## Data Fetching Patterns ```typescript // Parallel data fetching async function getUser(id: string) { const res = await fetch(`/api/users/${id}`); return res.json(); } async function getUserPosts(id: string) { const res = await fetch(`/api/users/${id}/posts`); return res.json(); } export default async function UserProfile({ params }: { params: { id: string } }) { // Fetch in parallel const [user, posts] = await Promise.all([ getUser(params.id), getUserPosts(params.id) ]); return ( <div> <UserInfo user={user} /> <UserPosts posts={posts} /> </div> ); } // Sequential data fetching (when needed) export default async function Dashboard() { // Fetch user first const user = await getUser(); // Then fetch user-specific data const settings = await getUserSettings(user.id); const notifications = await getUserNotifications(user.id); return ( <div> <UserHeader user={user} settings={settings} /> <Notifications items={notifications} /> </div> ); } // Waterfall optimization with Suspense import { Suspense } from 'react'; export default function Page() { return ( <div> {/* User loads first */} <Suspense fallback={<UserSkeleton />}> <User /> </Suspense> {/* These load in parallel */} <div className="grid"> <Suspense fallback={<SettingsSkeleton />}> <Settings /> </Suspense> <Suspense fallback={<NotificationsSkeleton />}> <Notifications /> </Suspense> </div> </div> ); } ``` ## Streaming with Suspense ```typescript // app/dashboard/page.tsx import { Suspense } from 'react'; export default function Dashboard() { return ( <div> <h1>Dashboard</h1> {/* Fast component renders immediately */} <QuickStats /> {/* Slow components stream in */} <Suspense fallback={<ChartSkeleton />}> <RevenueChart /> </Suspense> <Suspense fallback={<TableSkeleton />}> <RecentOrders /> </Suspense> <Suspense fallback={<ActivitySkeleton />}> <ActivityFeed /> </Suspense> </div> ); } async function RevenueChart() { // Slow data fetch const data = await fetchRevenueData(); return <Chart data={data} />; } async function RecentOrders() { const orders = await fetchOrders({ limit: 10 }); return ( <table> {orders.map(order => ( <tr key={order.id}> <td>{order.id}</td> <td>{order.total}</td> </tr> ))} </table> ); } // Nested Suspense for granular streaming async function ActivityFeed() { return ( <div> <h2>Activity</h2> <Suspense fallback={<div>Loading comments...</div>}> <Comments /> </Suspense> <Suspense fallback={<div>Loading likes...</div>}> <Likes /> </Suspense> </div> ); } ``` ## Server Component Patterns ```typescript // Pattern 1: Data fetching in Server Component async function fetchProduct(id: string) { const product = await db.product.findUnique({ where: { id } }); return product; } export default async function ProductPage({ params }: { params: { id: string } }) { const product = await fetchProduct(params.id); return ( <div> <ProductDetails product={product} /> <AddToCartButton productId={product.id} /> {/* Client Component */} </div> ); } // Pattern 2: Server Component as data provider async function ProductWithReviews({ id }: { id: string }) { const [product, reviews] = await Promise.all([ fetchProduct(id), fetchReviews(id) ]); return ( <> <ProductInfo product={product} /> <ReviewList reviews={reviews} /> <ReviewForm productId={id} /> {/* Client Component */} </> ); } // Pattern 3: Composing Server and Client Components export default async function Page() { const data = await fetchData(); return ( <ClientWrapper> {/* Server Component children work inside Client Components */} <ServerContent data={data} /> </ClientWrapper> ); } // Pattern 4: Props passing from Server to Client export default async function Layout({ children }: { children: React.ReactNode }) { const user = await getUser(); return ( <div> <ClientHeader user={user} /> {/* Pass server data to client */} <main>{children}</main> </div> ); } ``` ## Client Component Patterns ```typescript // Pattern 1: Minimal Client Component 'use client'; import { useState } from 'react'; export function Counter({ initialCount = 0 }: { initialCount?: number }) { const [count, setCount] = useState(initialCount); return ( <button onClick={() => setCount(count + 1)}> Count: {count} </button> ); } // Pattern 2: Client Component with Server Component children 'use client'; import { useState } from 'react'; export function Tabs({ children }: { children: React.ReactNode }) { const [activeTab, setActiveTab] = useState(0); return ( <div> <div className="tabs"> <button onClick={() => setActiveTab(0)}>Tab 1</button> <button onClick={() => setActiveTab(1)}>Tab 2</button> </div> <div>{children}</div> </div> ); } // Usage: Server Component children work export default async function Page() { const data = await fetchData(); return ( <Tabs> <ServerContent data={data} /> </Tabs> ); } // Pattern 3: Client wrapper with context 'use client'; import { createContext, useContext, useState } from 'react'; const ThemeContext = createContext<{ theme: string; setTheme: (theme: string) => void; } | null>(null); export function ThemeProvider({ children }: { children: React.ReactNode }) { const [theme, setTheme] = useState('light'); return ( <ThemeContext.Provider value={{ theme, setTheme }}>
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen