Streaming SSR (Server-Side Rendering с потоковой выдачей) в TanStack Router позволяет серверу отправлять HTML-контент клиенту постепенно по мере его готовности, снижая время до первого отображения и улучшая пользовательский опыт. В отличие от классического SSR, где весь HTML формируется перед отправкой, потоковая отрисовка отдает части страницы сразу после их готовности, позволяя браузеру рендерить их по мере поступления.
Роуты как асинхронные узлы TanStack Router организует маршрутизацию через дерево маршрутов, где каждый маршрут может иметь асинхронные загрузчики данных. При потоковом SSR каждый узел дерева рендерится сразу после завершения загрузки своих данных, без ожидания завершения всех дочерних маршрутов.
Suspense и отложенная загрузка Использование React Suspense совместно с TanStack Router позволяет рендерить placeholder-элементы для участков страницы, которые ещё не готовы. После загрузки данных Suspense автоматически заменяет их на реальный контент.
Потоковая передача HTML Серверная функция
renderToPipeableStream (или аналог в используемом
фреймворке) формирует поток HTML. TanStack Router интегрируется с этим
процессом через метод router.render(), который возвращает
React-элементы с уже подключенными асинхронными загрузчиками. Эти
элементы могут быть переданы в поток и отправлены клиенту по мере
готовности.
Определение маршрутов Каждый маршрут
определяется с возможностью асинхронной загрузки данных через
loader:
import { createRouter } from '@tanstack/router';
const router = createRouter({
routes: [
{
path: '/',
component: HomePage,
loader: async () => {
return fetch('/api/home').then(res => res.json());
},
},
{
path: '/profile/:id',
component: ProfilePage,
loader: async ({ params }) => {
return fetch(`/api/user/${params.id}`).then(res => res.json());
},
},
],
});
Асинхронный loader для каждого маршрута позволяет
рендерить части страницы сразу после готовности данных.
Серверная функция для потоковой выдачи Потоковый SSR предполагает использование потокового API фреймворка:
import { renderToPipeableStream } from 'react-dom/server';
import express from 'express';
import { RouterProvider } from '@tanstack/router';
const app = express();
app.get('*', (req, res) => {
const stream = renderToPipeableStream(
<RouterProvider router={router} initialLocation={req.url} />,
{
onShellReady() {
res.setHeader('Content-Type', 'text/html');
stream.pipe(res);
},
onAllReady() {
// Можно выполнить дополнительные действия после полного рендера
},
onError(err) {
console.error(err);
},
}
);
});
Ключевой момент: onShellReady позволяет
отправить клиенту основу страницы как можно раньше, а отдельные маршруты
будут подгружаться по мере готовности.
Prefetching TanStack Router поддерживает предзагрузку данных для маршрутов, которые могут быть посещены следующим шагом. В потоковом SSR это помогает заранее инициировать асинхронные запросы, сокращая время ожидания рендера дочерних маршрутов.
Deferred data Можно использовать
defer-объекты для передачи данных, которые могут
загружаться после отправки основного контента:
import { defer } from '@tanstack/router';
const loader = async () => {
return defer({
mainData: fetch('/api/main').then(res => res.json()),
extraData: fetch('/api/extra').then(res => res.json()),
});
};
Потоковый SSR будет рендерить mainData сразу, а
extraData загрузится позже без блокировки
отрисовки.
Suspense Позволяет рендерить fallback-контент до готовности данных:
import { Suspense } from 'react';
<Suspense fallback={<div>Загрузка...</div>}>
<RouteComponent />
</Suspense>ErrorBoundary Обрабатывает ошибки асинхронных загрузчиков без прерывания потока SSR:
import { ErrorBoundary } from '@tanstack/router';
<ErrorBoundary fallback={<div>Произошла ошибка</div>}>
<Suspense fallback={<div>Загрузка...</div>}>
<RouteComponent />
</Suspense>
</ErrorBoundary>Streaming SSR превращает серверный рендеринг в динамичный процесс, где браузер начинает отображать содержимое сразу, а TanStack Router обеспечивает корректное управление асинхронными маршрутами и данными, делая приложения быстрыми и отзывчивыми.