Серверный рендеринг (SSR) в Inferno обеспечивает предварительную генерацию HTML на сервере перед отправкой клиенту. Это повышает производительность, улучшает SEO и сокращает время до первого рендеринга (Time to First Paint). В сочетании с маршрутизацией SSR позволяет отображать разные страницы приложения в зависимости от URL ещё до загрузки JavaScript на клиенте.
Inferno поддерживает серверный рендеринг через пакет
inferno-server. Основной метод —
renderToString, который принимает React-подобный компонент
и возвращает строку HTML.
Пример базового рендеринга:
import { renderToString } from 'inferno-server';
import { createElement } from 'inferno';
const App = () => <div>Привет, Inferno SSR!</div>;
const html = renderToString(<App />);
console.log(html); // "<div>Привет, Inferno SSR!</div>"
Ключевые моменты:
renderToString используется для генерации HTML на
сервере.hydrate.Для маршрутизации на сервере используется пакет
inferno-router или более лёгкая альтернатива
inferno-router-component. В серверном контексте
маршрутизатор должен быть синхронизирован с URL запроса, чтобы вернуть
корректный HTML для каждой страницы.
Пример интеграции маршрутизации:
import { renderToString } from 'inferno-server';
import { createElement } from 'inferno';
import { Router, Route, Link, createMemoryHistory } from 'inferno-router';
const Home = () => <div>Главная</div>;
const About = () => <div>О нас</div>;
function render(url) {
const history = createMemoryHistory({ initialEntries: [url] });
const app = (
<Router history={history}>
<Route path="/" component={Home} exact />
<Route path="/about" component={About} />
</Router>
);
return renderToString(app);
}
console.log(render("/about")); // "<div>О нас</div>"
Ключевые моменты:
createMemoryHistory используется вместо
browserHistory, так как на сервере нет окна браузера.initialEntries определяет URL, который необходимо
отрендерить.После получения сгенерированного сервером HTML необходимо
«подхватить» его на клиенте. Для этого используется hydrate
вместо render:
import { hydrate } from 'inferno';
import { Router } from 'inferno-router';
import { createBrowserHistory } from 'history';
import App from './App';
const history = createBrowserHistory();
hydrate(
<Router history={history}>
<App />
</Router>,
document.getElementById('root')
);
Особенности:
hydrate сохраняет существующий DOM и присоединяет
события.Для полноценного SSR важно загружать данные на сервере перед
рендерингом. В Inferno это обычно реализуется через функции
getInitialProps или аналогичные подходы, которые возвращают
промис с данными.
Пример асинхронного рендеринга:
const fetchData = () => new Promise(resolve => setTimeout(() => resolve("Данные с сервера"), 100));
const DataPage = ({ data }) => <div>{data}</div>;
async function render(url) {
const data = await fetchData();
return renderToString(<DataPage data={data} />);
}
render("/data").then(html => console.log(html)); // "<div>Данные с сервера</div>"
Ключевые моменты:
async/await.SSR с маршрутизацией должен учитывать сценарии, когда страница не найдена или требуется редирект:
import { Redirect } from 'inferno-router';
function App({ url }) {
if (url === "/old-page") {
return <Redirect to="/new-page" />;
}
return <div>Страница</div>;
}
const html = renderToString(<App url="/old-page" />);
Особенности:
Redirect позволяет серверу возвращать правильный статус
и заголовок Location.* или
специальную компоненту NotFound.Чаще всего SSR на Inferno реализуется через Node.js и Express. Пример базового сервера:
import express from 'express';
import { renderToString } from 'inferno-server';
import { createMemoryHistory } from 'history';
import { Router, Route } from 'inferno-router';
import App from './App';
const server = express();
server.get('*', (req, res) => {
const history = createMemoryHistory({ initialEntries: [req.url] });
const html = renderToString(
<Router history={history}>
<App />
</Router>
);
res.send(`<!DOCTYPE html><html><body><div id="root">${html}</div><script src="/bundle.js"></script></body></html>`);
});
server.listen(3000);
Ключевые моменты:
*) и
передают URL в маршрутизатор Inferno.hydrate.async/await для снижения времени TTFB.Сочетание серверного рендеринга и маршрутизации в Inferno позволяет создавать быстрые, SEO-оптимизированные веб-приложения с предсказуемым рендерингом и точным соответствием между серверной и клиентской частью.