SSR (Server-Side Rendering) — это технология рендеринга веб-страниц на сервере с отправкой готового HTML клиенту:
// Компонент рендерится на сервере
function HomePage({ posts }) {
return (
<div>
<h1>Блог</h1>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
);
}SSR — это как готовый обед, который подают в ресторане, а не ингредиенты для самостоятельного приготовления! Сервер заранее готовит HTML и отправляет его браузеру. 🍽️
// 1. Запрос приходит на сервер
app.get('/', async (req, res) => {
// 2. Получаем данные
const posts = await fetchPosts();
// 3. Рендерим компонент в HTML
const html = renderToString(
<HomePage posts={posts} />
);
// 4. Отправляем готовый HTML
res.send(`
<!DOCTYPE html>
<html>
<body>
<div id="root">${html}</div>
<script src="/bundle.js"></script>
</body>
</html>
`);
});// CSR - рендеринг на клиенте
function App() {
const [posts, setPosts] = useState([]);
useEffect(() => {
// Данные загружаются после рендера
fetchPosts().then(setPosts);
}, []);
return (
<div>
{posts.length ? (
posts.map(post => <Post key={post.id} {...post} />)
) : (
<div>Загрузка...</div>
)}
</div>
);
}
// SSR - данные уже есть
function App({ posts }) {
// Контент сразу готов
return (
<div>
{posts.map(post => (
<Post key={post.id} {...post} />
))}
</div>
);
}// На сервере
const html = renderToString(<App data={data} />);
// На клиенте - гидратация
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>Главная страница</h1>
{posts.map(post => (
<div key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</div>
))}
</div>
);
}
// Функция выполняется на сервере
export async function getServerSideProps() {
const posts = await fetch('https://api.example.com/posts')
.then(res => res.json());
return {
props: { posts }
};
}// Генерация во время сборки
export async function getStaticProps() {
const posts = await fetchPosts();
return {
props: { posts },
revalidate: 60 // Обновление каждые 60 секунд
};
}
// Динамические маршруты
export async function getStaticPaths() {
const posts = await fetchPosts();
return {
paths: posts.map(post => ({
params: { id: post.id.toString() }
})),
fallback: 'blocking'
};
}// SEO-дружественный компонент
function ProductPage({ product }) {
return (
<>
<Head>
<title>{product.name} - Магазин</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>Цена: {product.price}₽</span>
</main>
</>
);
}// 1. Полный SSR
export async function getServerSideProps(context) {
const data = await fetchUserData(context.req);
return { props: { data } };
}
// 2. Статическая генерация
export async function getStaticProps() {
const data = await fetchStaticData();
return {
props: { data },
revalidate: 3600 // ISR
};
}
// 3. Гибридный подход
function Page({ staticData }) {
const [dynamicData, setDynamicData] = useState(null);
useEffect(() => {
fetchDynamicData().then(setDynamicData);
}, []);
return (
<div>
<StaticContent data={staticData} />
{dynamicData && <DynamicContent data={dynamicData} />}
</div>
);
}// Кеширование
import { cache } from 'react';
const fetchPosts = cache(async () => {
const response = await fetch('/api/posts');
return response.json();
});
// Потоковый рендеринг
import { renderToPipeableStream } from 'react-dom/server';
app.get('/', (req, res) => {
const stream = renderToPipeableStream(
<App />,
{
onShellReady() {
res.setHeader('Content-Type', 'text/html');
stream.pipe(res);
}
}
);
});❌ Неправильно:
// Использование browser-only API
function Component() {
const width = window.innerWidth; // Ошибка на сервере
return <div>Ширина: {width}</div>;
}✅ Правильно:
function Component() {
const [width, setWidth] = useState(0);
useEffect(() => {
setWidth(window.innerWidth);
}, []);
return <div>Ширина: {width || 'Загрузка...'}</div>;
}SSR — мощная технология для улучшения производительности и SEO:
Выбирайте SSR для контентных сайтов, блогов и интернет-магазинов! 🎯