Server Components vs Client Components
Server Components execute on the server and can keep server-only work out of the browser bundle, while Client Components execute in the browser and support interactivity, state, and browser APIs. In frameworks such as Next.js, the two can be composed to keep interactive code close to where it is needed.
A Server Component is rendered in a server environment rather than executed as interactive component code in the browser. It can access server-side resources such as databases or filesystem APIs when the framework permits them, and its implementation does not become part of the client JavaScript bundle in the same way a Client Component does.
A Client Component is a component whose code is intended to run in the browser. In React applications using Server Components, a file marked with `"use client"` establishes a client boundary; components imported beneath that boundary are treated as client-side code unless another framework-specific rule applies. Client Components can use browser APIs and interactive React features such as `useState` and event handlers.
The two types are composable, but the boundary matters. Server Components can render Client Components and pass serializable data to them. A Client Component cannot directly import a Server Component, because that would require server-only implementation details to execute in the browser; instead, a common pattern is to pass server-rendered UI into a Client Component through `children` or another supported composition mechanism.
The main architectural benefit is selective client-side JavaScript. Put data fetching and noninteractive rendering on the server when appropriate, and isolate stateful or browser-dependent behavior in smaller Client Components. This can reduce the amount of JavaScript sent to the browser while preserving rich interaction.
Key points
- Server Components execute in a server environment; Client Components execute in the browser.
- Client Components can use state, event handlers, and browser-only APIs.
- `"use client"` marks a client boundary in React Server Components environments.
- Server Components can render Client Components and pass supported serializable props.
- Keeping the client boundary small can reduce browser JavaScript and preserve server-side data access.
Interview questions
How do Server and Client Components work together on a page?
A server-rendered component tree can contain interactive Client Component boundaries. The server can prepare data and render the surrounding UI, then provide supported props to the client portion. Client Components handle browser interaction without requiring the entire surrounding tree to become client code. A good design keeps server-only concerns and data access on the server while isolating browser behavior behind appropriately small client boundaries.
What is the difference between a Server Component and a Client Component?
A Server Component runs in a server environment and is useful for server-side data access and rendering that does not require browser interaction. A Client Component runs in the browser and can use state, event handlers, and browser APIs. In a React Server Components setup, `"use client"` establishes a client boundary. A typical application keeps interactive behavior in Client Components while leaving noninteractive work on the server.
Why can't a Client Component directly import a Server Component?
The imported Server Component may contain code that only makes sense in the server environment, such as access to a server-only resource. Importing it into client code would blur the execution boundary and could expose or require server-only implementation details in the browser. Instead, Server Components can render Client Components and provide data or supported composition slots. The exact composition APIs depend on the React framework being used.
What does `"use client"` do?
In a React Server Components environment, `"use client"` is a directive that marks a module as a Client Component entry point. It creates a boundary between server-oriented and client-oriented component code. Code imported through that boundary is generally included in the client-side dependency graph according to the framework's rules. It is therefore useful to place the directive at the smallest practical component boundary.
When would you choose a Client Component instead of a Server Component?
Choose a Client Component when the UI needs browser-only capabilities or interaction that requires client execution. Examples include local state with `useState`, event handlers, effects, and browser APIs such as `localStorage` or `window`. If those requirements are limited to a small part of a page, it is often useful to keep that part as a small Client Component rather than making the entire page client-side. The precise trade-offs depend on the framework and application.