Серверный рендеринг (SSR, Server-Side Rendering) — это процесс генерации HTML-кода на сервере вместо браузера. В контексте Preact, SSR позволяет улучшить производительность, ускорить первую отрисовку страницы и повысить SEO-оптимизацию. Preact изначально ориентирован на легковесность, поэтому SSR реализуется через отдельные модули и API, минимизируя накладные расходы.
Для серверного рендеринга Preact предоставляет функцию
renderToString из пакета
preact-render-to-string. Она принимает дерево компонентов
Preact и возвращает строку с готовым HTML.
import { h } from 'preact';
import renderToString from 'preact-render-to-string';
function App() {
return <div>Привет, Preact SSR!</div>;
}
const html = renderToString(<App />);
console.log(html); // <div>Привет, Preact SSR!</div>
Ключевой момент: renderToString
работает синхронно, генерируя статический HTML без выполнения эффектов,
завязанных на браузер, таких как useEffect.
useEffect и useLayoutEffect при SSRПри рендеринге на сервере важно понимать, что хуки
useEffect и useLayoutEffect не вызываются, так
как сервер не имеет DOM. Для инициализации состояния на сервере следует
использовать useState и передавать необходимые данные через
пропсы или контекст.
import { useState } from 'preact/hooks';
function Counter({ initial }) {
const [count] = useState(initial);
return <span>{count}</span>;
}
SSR в Preact часто используется вместе с Node.js-фреймворками, такими как Express или Fastify. Простейший пример интеграции с Express:
import express from 'express';
import { h } from 'preact';
import renderToString from 'preact-render-to-string';
import App from './App';
const server = express();
server.get('*', (req, res) => {
const html = renderToString(<App />);
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Preact SSR</title>
</head>
<body>
<div id="root">${html}</div>
<script src="/bundle.js"></script>
</body>
</html>
`);
});
server.listen(3000);
После генерации HTML на сервере необходимо «оживить» интерфейс на
клиенте, чтобы компоненты стали интерактивными. Для этого используется
функция hydrate из preact.
import { h, hydrate } from 'preact';
import App from './App';
hydrate(<App />, document.getElementById('root'));
Особенность: hydrate связывает уже
существующий HTML с Preact-компонентами без перерисовки всего дерева,
что ускоряет загрузку страницы.
Для динамических приложений данные, полученные на сервере, можно внедрять прямо в HTML через скрипты:
const data = { user: 'Alice' };
const html = renderToString(<App initialData={data} />);
res.send(`
<div id="root">${html}</div>
<script>window.__INITIAL_DATA__ = ${JSON.stringify(data)};</script>
<script src="/bundle.js"></script>
`);
На клиенте данные извлекаются и используются для гидратации состояния:
hydrate(<App initialData={window.__INITIAL_DATA__} />, document.getElementById('root'));
preact/compat позволяет применять динамический импорт и
разделять код на чанки.renderToString — серверный рендеринг должен быть
максимально легким, чтобы не блокировать поток запросов.Preact, в отличие от React, имеет меньший API и отсутствует встроенная поддержка некоторых сложных функций вроде Suspense на сервере. Поэтому подход к рендерингу компонентов и гидратации немного отличается, но базовые принципы остаются схожими:
renderToString → генерация HTML на сервереhydrate → интерактивность на клиентеДля SSR с маршрутизацией используется пакет
preact-router. На сервере важно рендерить компоненты,
соответствующие текущему маршруту:
import { Router } from 'preact-router';
import Home from './Home';
import About from './About';
function App({ url }) {
return (
<Router url={url}>
<Home path="/" />
<About path="/about" />
</Router>
);
}
На сервере url передается из запроса, чтобы отрендерить
корректный компонент.
Серверный рендеринг в Preact позволяет создавать быстрые, SEO-дружественные приложения с минимальным весом. Важнейшие аспекты — корректная работа хуков, передача данных с сервера, гидратация на клиенте и оптимизация производительности. Сочетание этих подходов делает Preact мощным инструментом для создания современных веб-приложений с SSR.