Server Components Intro
Introduction to React Server Components and how they change data fetching, bundles, and client boundaries.
What Are Server Components
Server Components render on the server only — their code never ships to the client bundle. They can async await data, access databases directly, and read filesystem resources without API layers.
They complement Client Components (`"use client"`) which handle interactivity. A typical page mixes server components for data and structure with small client islands for buttons, forms, and animations.
- Render on server, zero client JS for RSC code
- Direct data/database access
- Mix with Client Components
Client Boundary Rules
Adding `"use client"` at file top marks a module and its imports as client bundle. Client Components can import other client modules and receive Server Components as children passed as props (composition pattern).
Server Components cannot import Client Components directly — pass them as children or props slots instead. Props from Server to Client must be serializable — no functions, class instances, or Dates without conversion.
- "use client" marks client boundary
- Server can pass client components as children
- Serializable props only across boundary
Data Fetching Without Waterfalls
Server Components fetch during render on the server. Colocate fetch with the component needing data. Parallel fetches happen naturally when sibling server components each fetch independently.
Suspense boundaries stream HTML as segments complete — users see shell immediately while slow data loads. Avoid sequential await chains in one component when parallel fetches suffice.
- Fetch colocated with components
- Parallel sibling fetches
- Suspense for streaming
When to Stay Client-Side
Use Client Components for useState, useEffect, event handlers, browser APIs (localStorage, geolocation), and third-party widgets requiring window. Interactive charts, maps, and rich text editors typically need client boundaries.
Push `"use client"` as deep as possible — a client button inside a server layout keeps most of the page in the server bundle. Avoid marking entire pages client unless necessary.
- Client for hooks and browser APIs
- Push client boundary deep
- Third-party widgets often need client
Next.js App Router Integration
Next.js App Router defaults to Server Components in app/ directory. page.tsx and layout.tsx are server unless marked client. loading.tsx and error.tsx are special files for Suspense and error boundaries.
Migration from Pages Router: move data fetching from getServerSideProps into async Server Components. Replace _app client wrappers with root layout and selective client providers.
- app/ defaults to Server Components
- Special files: loading, error, not-found
- Migrate getServerSideProps to async RSC