The world of web development is always evolving, and the introduction of server components React marks one of the biggest shifts in recent memory. Put simply, they are a new type of component that runs exclusively on the server, allowing them to render UI without sending their underlying JavaScript to the user’s browser. If you’ve heard the buzz around React 18, Next.js 13, and this new way of building web apps, you’re in the right place. This guide breaks down everything you need to know about this new paradigm, from the basic concepts to the nitty gritty details.
We’ll explore how these components work, why they’re a game changer for performance, and how you can leverage them to build faster, more efficient applications. Whether you’re a seasoned developer or using a visual UI builder like WeWeb that handles the heavy lifting for you, understanding these principles is key to navigating the modern web.
The Core Concepts: What Are Server Components?
At its heart, the new model splits your app into two types of components. Let’s break down what that means.
An Overview of Server Components
A Server Component is a new type of React component that runs exclusively on the server. Unlike traditional components that get bundled up and sent to the user’s browser, a Server Component does its work ahead of time (either when the app is built or when a user makes a request).
The result is pure UI (like HTML or a special data format) sent to the client, without the component’s underlying JavaScript logic. This means you can do things like fetch data directly from a database or access the file system right inside your component, and none of that sensitive or heavy code ever leaves the server. The React team calls these “zero bundle size” components because their code never inflates the amount of JavaScript the user has to download.
Server Components vs. Client Components
The introduction of server components React creates a clear distinction between two roles.
- Server Components run on the server. They are perfect for fetching data and displaying content that doesn’t need to be interactive. They can’t use React hooks like
useStateoruseEffectbecause those rely on a browser environment. - Client Components are the traditional React components we all know. They run in the browser, handle user interactions (like button clicks and form inputs), manage state, and can use all the browser APIs. You explicitly mark a component as a client one when it needs to be interactive.
Think of it this way: Server Components build the non interactive “scaffolding” and content of your page, while Client Components are the interactive “widgets” you place within it.
When to Use a Server Component
You should lean on Server Components whenever a piece of your UI doesn’t require immediate client side interactivity. They are the new default in modern frameworks like Next.js for a reason.
Use a Server Component when you need to:
- Fetch data: Since they run on the server, they are physically closer to your data sources. You can use
async/awaitto fetch from a database or API directly inside the component, which is cleaner and faster than making client side API calls. If you’re building visually, browse WeWeb integrations to connect to sources like Airtable or Google Sheets without extra glue code. - Keep large dependencies off the client: If you need a heavy library (like a markdown parser or a date formatting utility) to render some content, using it in a Server Component means that library’s code never gets sent to the user’s browser. This is a massive win for performance. For example, a markdown parser like
marked(11 KB) and an HTML sanitizer (63 KB) add zero to the client bundle when used on the server. - Access server side resources securely: You can safely use secret API keys or access backend resources without worrying about exposing them to the client. For authentication and user management, consider Auth0.
In short, if a component’s job is just to display information, it’s a perfect candidate for a Server Component.
The Big Wins: Performance and Interactivity
The main driver behind server components React is performance. By rethinking where code runs, we can build significantly faster applications.
How Server Components Reduce Bundle Size
This is the most significant benefit. Every line of code and every dependency you use inside a Server Component stays on the server. It is never included in the JavaScript bundles that are downloaded by your users.
In a traditional React app, every component and library adds to the total bundle size, slowing down initial page loads. With Server Components, you can build huge, feature rich applications while keeping the initial client side footprint incredibly small. Early demonstrations of this architecture showed that some app bundles could be reduced by 30% or more just by moving non interactive logic to the server.
This means faster load times, especially for users on slower networks or less powerful devices, which directly impacts user experience and core web vitals like Largest Contentful Paint (LCP).
Adding Interactivity When You Need It
But what about interactions? A website isn’t just static content.
Server Components themselves are not interactive. To add functionality like a button click or a stateful form, you embed a Client Component within your Server Component.
You create a separate component file, mark it with a "use client" directive at the top, and then you can use all the familiar React hooks (useState, useEffect, etc.). Your Server Component can then render this interactive Client Component and even pass it data as props. This “sprinkling” of interactivity allows you to keep your client side JavaScript to an absolute minimum, only loading it for the specific parts of the page that truly need it.
How It Works in Next.js
Next.js (version 13 and later) has fully embraced this new model with its App Router. Understanding its mechanics is key to seeing the power of server components React in action.
The Default Behavior
In the Next.js App Router, all components are Server Components by default. You don’t have to do anything special. The framework assumes you want to render on the server for optimal performance. You only opt out when you need client side interactivity.
The use client Directive
To turn a Server Component into a Client Component, you simply add the string "use client" as the very first line of the file. This directive tells the build process, “Hey, this component (and anything it imports) needs to run in the browser, so please include it in the client JavaScript bundle.”
It’s a clear boundary that makes you intentionally decide what code gets shipped to the user, preventing accidental bloat.
Understanding the RSC Payload
When you navigate between pages in a Next.js app, the browser doesn’t fetch a full HTML document. Instead, it requests a React Server Component (RSC) Payload.
This payload is a compact, serialized representation of the rendered component tree. It’s not HTML; it’s more like a set of instructions that React uses on the client to update the UI. This special format, known as the “Flight” protocol, is highly optimized. It contains the rendered output from Server Components and the necessary props for any Client Components on the page. Because it’s just the “diff” of what needs to change, it’s much smaller than a full HTML page, making navigations incredibly fast.
The Role of Hydration
Hydration is the process of “waking up” a server rendered page in the browser. The server sends static HTML for a fast initial view. Then, the client side JavaScript loads and attaches all the event handlers and state, making the page fully interactive.
With server components React, hydration is much more efficient. Since only Client Components need to become interactive, React has less work to do. It can ignore the static parts rendered by Server Components and focus only on hydrating the interactive islands. React 18 further improves this with Selective Hydration, allowing parts of the page to become interactive even before the entire JavaScript bundle has loaded.
What Is a Subsequent Navigation?
The first time you load a Next.js page, you get a server rendered HTML document. A subsequent navigation is any page change that happens after that initial load (e.g., clicking a <Link>).
Instead of a full page refresh, the browser makes a background request to the server, which runs the Server Components for the new page and sends back an RSC Payload. The client side React runtime then uses this payload to update the view seamlessly, without losing any client side state (like text you’ve typed in an input). This gives you the performance benefits of a multi page app with the fluid user experience of a single page app.
Advanced Patterns and Data Flow
The server and client boundary introduces some new patterns for managing and passing data. If you prefer a visual approach with backend freedom, explore WeWeb’s no-code backend builder.
Passing Data from Server to Client Components
The most common way to get data from a Server Component to a Client Component is through props, just like you normally would.
// Page.server.jsx
import InteractiveChart from './InteractiveChart.client.jsx';
export default async function Dashboard() {
const analyticsData = await getAnalytics(); // Fetched on server
return <InteractiveChart data={analyticsData} />;
}
There’s one crucial rule: the props you pass must be serializable. This means you can pass strings, numbers, arrays, and plain objects, but not functions, class instances, or other complex types that can’t be turned into JSON text. The framework handles serializing the props into the RSC Payload for you. For example, you can fetch data from Airtable in a Server Component and pass the results into a chart Client Component.
Interleaving Server and Client Components
You can freely mix and match Server and Client Components in the same tree. This is called interleaving. A Server Component can render a Client Component, which can even render another component (though a Client Component cannot directly import and render a Server Component, as the server code isn’t available in the browser).
This granular control lets you optimize your application tree, pushing static content to the server while keeping interactive islands on the client, all working together seamlessly.
The Context Provider Pattern
React’s Context API is tricky with Server Components because they are stateless and rerender on each request. You cannot create and consume a context provider that holds state purely on the server.
The common pattern is to have your Context Provider be a Client Component. You can render it high up in your tree from a Server Component, passing it initial data via props. Any Client Components nested underneath it can then consume the context just like they normally would.
Sharing Data with React.cache
For sharing data between Server Components during a single request without prop drilling, React provides a cache function. You can wrap a data fetching function with cache() to memoize its result. If multiple components call the same cached function with the same arguments during a single render pass, the data will only be fetched once.
Next.js automatically does this for you with its built in fetch API, deduplicating identical requests within a render tree. This is a powerful optimization that prevents redundant database or API calls.
Async Server Components and Suspense
Server Components can be async functions, which radically simplifies data fetching. You can await a promise right inside your component’s body.
async function UserProfile({ id }) {
const user = await db.users.find(id); // Pauses render until data is ready
return <div>{user.name}</div>;
}
When paired with Suspense, this becomes even more powerful. By wrapping an async component in a <Suspense> boundary, you can tell React to show a fallback UI (like a loading spinner) while the data is being fetched. This allows the server to stream the rest ofthe page to the browser immediately, and then stream the content of the async component once it’s ready, preventing slow data fetches from blocking the entire page render.
Rendering Strategies Explained
The server components React model supports several different ways to render your pages, giving you flexibility to choose the best approach for your content.
Static Rendering (Build Time)
Static Rendering, or Static Site Generation (SSG), is when the HTML for a page is generated at build time. This is the fastest possible delivery method because the page is pre built and can be served directly from a CDN. It’s perfect for content that doesn’t change often, like blog posts, documentation, or marketing pages. If you’re new to SSG and RSC, check the step-by-step lessons in WeWeb Academy.
Dynamic Rendering (Request Time)
Dynamic Rendering, or Server Side Rendering (SSR), is when the HTML is generated on the server for every single request. This is necessary for pages with highly personalized or real time content, like a user dashboard or a social media feed. Each visitor gets a freshly rendered page with the most up to date information.
What is Streaming?
Streaming is an advanced technique where the server sends the page’s HTML to the browser in chunks as it becomes available. Paired with Suspense, this means the user can start seeing and interacting with the main parts of a page while slower, data heavy sections are still being prepared on the server. This dramatically improves the perceived load time.
Server Components Without a Server (Build Time)
This might sound confusing, but it simply refers to using server components React in a static rendering context. The “server” environment is the build process itself. The components run once during the build, fetch their data, and generate static HTML files. No live server is needed to serve the pages to users afterward.
Server Components With a Server (Request Time)
This refers to using server components React in a dynamic rendering context. A live server (like Node.js) is running and executes your components for each incoming user request, allowing for fully dynamic and personalized content.
Working with the Ecosystem
The new architecture also changes how we work with third party libraries and think about security.
Using Third Party Components
You can still use third party libraries, but you need to be mindful of where they run. If a component from a library uses useState, useEffect, or any browser specific APIs, it must be treated as a Client Component.
This usually means creating a simple “wrapper” component in your own project. In that file, you put "use client" at the top and then import and export the third party component. This ensures it’s correctly bundled for the browser.
Preventing Environment Poisoning
Environment poisoning is when server only code (like a secret key) accidentally leaks into the client bundle, or when client only code (like accessing the window object) tries to run on the server.
Frameworks like Next.js have strong safeguards to prevent this. For example:
- It will throw a build error if you try to use a browser API in a Server Component.
- By default, only environment variables prefixed with
NEXT_PUBLIC_are exposed to the browser, preventing secret keys from leaking. - You can use special packages like
server-onlyandclient-onlyto enforce that a module can only be imported in the correct environment.
Conclusion: A Paradigm Shift for the Better
The introduction of server components React is a fundamental shift toward building more performant, scalable, and maintainable web applications. By intelligently separating concerns between the server and the client, we can deliver faster initial loads, reduce the amount of JavaScript shipped to users, and simplify our data fetching logic.
While the concepts can seem complex, they are designed to solve real world performance bottlenecks. For those who want to harness this power without getting lost in the weeds, platforms are emerging to abstract away the complexity. A visual development tool like WeWeb can empower you to build production grade applications that are fast by default, leveraging the benefits of modern React architecture behind the scenes. See what’s possible in the WeWeb Showcase.
If you’re ready to build faster web apps, exploring tools that have embraced this new paradigm is the next logical step. You can start from a template and experience the performance gains firsthand.
Frequently Asked Questions (FAQ)
What is the main benefit of using server components in React?
The primary benefit is performance. By running on the server and not sending their JavaScript to the client, they drastically reduce the client side bundle size. This leads to faster page load times, a better user experience, and improved Core Web Vitals.
Are server components replacing client components?
No, they work together. Server Components are the new default for rendering static content and fetching data, while Client Components are used specifically for adding interactivity. You need both to build a complete application.
Can I use useState or useEffect in a Server Component?
No. Hooks like useState and useEffect depend on the browser environment to manage state and side effects. Since Server Components run only on the server, they cannot use these hooks. You must place any component that needs these hooks in a file marked with "use client".
How do server components react to improve SEO?
Because Server Components render to HTML on the server before being sent to the browser, search engine crawlers can immediately see and index the full content of the page. This is a significant improvement over traditional client side rendered apps, which sometimes present crawlers with a blank page that needs to execute JavaScript to show content.
Is it hard to learn the new server components model?
There is a learning curve, especially around understanding the server/client boundary and new data fetching patterns. However, the resulting code is often simpler and more direct. For those looking for an easier path, platforms like WeWeb adopt these modern principles for you, letting you build visually without managing the underlying architecture.
Do server components make my website more secure?
Yes, they can. Since data fetching and logic with sensitive information (like API keys) can be contained entirely within Server Components, that code never leaves your server. This reduces the risk of accidentally exposing secrets in your client side JavaScript bundle.
What is the difference between Server Components and SSR?
Server Side Rendering (SSR) is a technique for rendering a React app to HTML on the server for the initial page load. Server Components are a new type of component that enables this and much more. The RSC model extends beyond the initial load, allowing for fast client side navigations using the RSC payload and enabling “zero bundle size” components, which traditional SSR does not.
Can I use my favorite UI library with Server Components?
It depends on the library. If a component from the library is purely presentational and doesn’t use client side hooks, it may work as a Server Component. However, most interactive components (like date pickers, sliders, or modals) will need to be used within a Client Component wrapper. Many libraries are now updating to be compatible with the new model.

