Серверный рендеринг (Server-Side Rendering, SSR) в Riot.js обеспечивает генерацию HTML на стороне сервера, что ускоряет первоначальную загрузку страницы, улучшает SEO и позволяет управлять контентом до того, как он попадёт в браузер. Основная идея заключается в том, чтобы компонент создавал HTML не только в клиентском окружении, но и на сервере, после чего результат отправлялся пользователю как готовый документ.
render(),
который возвращает HTML-строку на основе компонента:import riot from 'riot';
import MyComponent from './components/my-component.riot';
const html = riot.render(MyComponent, { title: 'Пример' });
console.log(html);
Важно передавать данные через объект props, чтобы компонент был полностью управляемым и повторяемым на сервере и клиенте.
document или window приведёт к ошибкам при
серверном рендеринге. Для таких случаев применяют проверки типа:if (typeof window !== 'undefined') {
// Клиентская логика
}
mount() для гидратации:import riot from 'riot';
import MyComponent from './components/my-component.riot';
riot.mount('my-component', { title: 'Пример' });
Гидратация позволяет использовать тот же компонентный код как на сервере, так и на клиенте, сохраняя состояние и обработчики событий.
Эффективный SSR невозможен без корректного управления состоянием. Чаще всего используют подход «сервер формирует начальное состояние, клиент продолжает работу с ним». Структура данных передается через глобальный объект или инлайновый скрипт в HTML:
<script>
window.__INITIAL_STATE__ = { title: 'Пример' };
</script>
На клиенте состояние считывается и передается компонентам при монтировании.
Для серверного рендеринга важно корректно работать с асинхронными источниками данных, например, с API. В Riot.js это достигается через промисы или async/await при подготовке props на сервере:
async function renderPage() {
const data = await fetchData();
const html = riot.render(MyComponent, data);
return html;
}
Асинхронная подготовка данных позволяет формировать полный HTML с учётом всех зависимостей перед отправкой клиенту.
riot.render().На практике часто используют Express.js для организации SSR. Пример базовой структуры:
import express from 'express';
import riot from 'riot';
import MyComponent from './components/my-component.riot';
const app = express();
app.get('/', async (req, res) => {
const data = await fetchData();
const html = riot.render(MyComponent, data);
res.send(`
<!DOCTYPE html>
<html>
<head><title>${data.title}</title></head>
<body>
<my-component>${html}</my-component>
<script src="/bundle.js"></script>
<script>
window.__INITIAL_STATE__ = ${JSON.stringify(data)};
</script>
</body>
</html>
`);
});
app.listen(3000);
Такой подход позволяет полностью контролировать генерацию HTML и подготовку данных до того, как пользователь откроет страницу.
Соблюдение принципов SSR требует строгого разделения клиентской и серверной логики, правильного управления состоянием и подготовки асинхронных данных. Riot.js предоставляет для этого компактный и гибкий набор инструментов, позволяя создавать лёгкие, быстрые и SEO-дружественные приложения.