SSR (Server-Side Rendering) is a technology for rendering web pages on the server with sending ready HTML to the client:
// Component renders on server
function HomePage({ posts }) {
return (
<div>
<h1>Blog</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
);
}SSR is like a ready meal served in a restaurant, not ingredients for self-cooking! The server prepares HTML in advance and sends it to the browser. 🍽️
// 1. Request comes to server
app.get('/', async (req, res) => {
// 2. Fetch data
const posts = await fetchPosts();
// 3. Render component to HTML
const html = renderToString(
<HomePage posts={posts} />
);
// 4. Send ready HTML
res.send(`
<!DOCTYPE html>
<html>
<body>
<div id="root">${html}</div>
<script src="/bundle.js"></script>
</body>
</html>
`);
});// CSR - client-side rendering
function App() {
const [posts, setPosts] = useState([]);
useEffect(() => {
// Data loads after render
fetchPosts().then(setPosts);
}, []);
return (
<div>
{posts.length ? (
posts.map(post => <Post key={post.id} {...post} />)
) : (
<div>Loading...</div>
)}
</div>
);
}
// SSR - data is already available
function App({ posts }) {
// Content is ready immediately
return (
<div>
{posts.map(post => (
<Post key={post.id} {...post} />
))}
</div>
);
}// On server
const html = renderToString(<App data={data} />);
// On client - hydration
import { hydrateRoot } from 'react-dom/client';
hydrateRoot(
document.getElementById('root'),
<App data={window.__INITIAL_DATA__} />
);// pages/index.js
export default function Home({ posts }) {
return (
<div>
<h1>Home Page</h1>
{posts.map(post => (
<div key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</div>
))}
</div>
);
}
// Function runs on server
export async function getServerSideProps() {
const posts = await fetch('https://api.example.com/posts')
.then(res => res.json());
return {
props: { posts }
};
}// Generation at build time
export async function getStaticProps() {
const posts = await fetchPosts();
return {
props: { posts },
revalidate: 60 // Update every 60 seconds
};
}
// Dynamic routes
export async function getStaticPaths() {
const posts = await fetchPosts();
return {
paths: posts.map(post => ({
params: { id: post.id.toString() }
})),
fallback: 'blocking'
};
}// SEO-friendly component
function ProductPage({ product }) {
return (
<>
<Head>
<title>{product.name} - Store</title>
<meta name="description" content={product.description} />
<meta property="og:title" content={product.name} />
<meta property="og:image" content={product.image} />
</Head>
<main>
<h1>{product.name}</h1>
<img src={product.image} alt={product.name} />
<p>{product.description}</p>
<span>Price: ${product.price}</span>
</main>
</>
);
}// 1. Full SSR
export async function getServerSideProps(context) {
const data = await fetchUserData(context.req);
return { props: { data } };
}
// 2. Static generation
export async function getStaticProps() {
const data = await fetchStaticData();
return {
props: { data },
revalidate: 3600 // ISR
};
}
// 3. Hybrid approach
function Page({ staticData }) {
const [dynamicData, setDynamicData] = useState(null);
useEffect(() => {
fetchDynamicData().then(setDynamicData);
}, []);
return (
<div>
<StaticContent data={staticData} />
{dynamicData && <DynamicContent data={dynamicData} />}
</div>
);
}// Caching
import { cache } from 'react';
const fetchPosts = cache(async () => {
const response = await fetch('/api/posts');
return response.json();
});
// Streaming rendering
import { renderToPipeableStream } from 'react-dom/server';
app.get('/', (req, res) => {
const stream = renderToPipeableStream(
<App />,
{
onShellReady() {
res.setHeader('Content-Type', 'text/html');
stream.pipe(res);
}
}
);
});❌ Wrong:
// Using browser-only API
function Component() {
const width = window.innerWidth; // Error on server
return <div>Width: {width}</div>;
}✅ Correct:
function Component() {
const [width, setWidth] = useState(0);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return <div>Width: {width || 'Loading...'}</div>;
}SSR is a powerful technology for improving performance and SEO:
Choose SSR for content sites, blogs and e-commerce! 🎯