Back to Next.js tutorials
Intermediate14 min read

Server Components

Default server rendering for smaller bundles, direct data access, and improved security boundaries.

Default To Server Rendering

Server Components execute only on the server. Their JavaScript is not included in the client bundle — only the rendered output (RSC payload) crosses the wire. This dramatically reduces bundle size for data-heavy pages.

They can be async functions awaiting database queries, file reads, and microservice calls without API route indirection. Secrets in server code never reach the browser.

  • Zero client JS for server component logic
  • Async/await direct data access
  • Secrets stay on server
export default async function Page() {
  const posts = await db.post.findMany();
  return <PostList posts={posts} />;
}

Fetch Close To The Data

Colocate data fetching in the component that renders the data. Sibling Server Components fetching independently run in parallel on the server. Parent-child sequential awaits create waterfalls — restructure into siblings when possible.

Next.js extends fetch with caching semantics on the server. Deduplicate identical fetches within a request automatically.

  • Colocate fetch with consuming component
  • Parallel sibling fetches avoid waterfalls
  • Automatic fetch deduplication per request

Serialization Boundaries

Props passed from Server to Client Components must be JSON-serializable — plain objects, arrays, strings, numbers, booleans, null. No functions, class instances, Symbols, or Dates (convert Dates to strings).

Server Components can render Client Components by importing them or receiving them as children. Client Components cannot import Server Components — pass server output as children props instead.

  • Serializable props across boundary
  • Convert Dates and custom types
  • Client cannot import Server directly

Composition Patterns

Server page renders Client interactive shell with Server static content as children: `<ClientModal><ServerContent /></ClientModal>`. This keeps interactivity localized while maximizing server-rendered content.

Extract shared server logic into async server utilities imported by multiple routes — not into client hooks. Shared types live in neutral modules importable from both sides.

  • Server children through client slots
  • Shared server utilities for data
  • Neutral modules for shared types

Debugging Server Components

Console.log in Server Components outputs to the terminal, not browser DevTools. Use React DevTools Components tab to inspect server/client boundaries in development.

Errors in Server Components surface as error boundaries or 500 responses. Add error.tsx per route for graceful degradation. Log server errors with request context in production monitoring.

  • Server logs in terminal
  • error.tsx for server render failures
  • Monitor server component errors in production

Get In Touch


Ready to discuss your next project? Drop me a message.