Обработка навигации на сервере

TanStack Router предоставляет гибкую архитектуру для управления маршрутизацией как на клиенте, так и на сервере. Серверная навигация становится особенно актуальной в приложениях с SSR (Server-Side Rendering) и при построении изоморфных приложений, где один и тот же маршрут должен корректно обрабатываться как на сервере, так и в браузере.

Конфигурация маршрутов для серверной навигации

На сервере маршруты определяются аналогично клиентской стороне с использованием объекта createRouter. Ключевым отличием является необходимость подготовки данных до рендеринга страницы, что обеспечивает корректное формирование HTML с уже загруженным контентом.

import { createRouter, createRouteConfig } from '@tanstack/router';
import express from 'express';
import { renderToString } from 'react-dom/server';
import App from './App';

const routeConfig = createRouteConfig()
  .createRoute({
    path: '/',
    component: App,
    loader: async () => {
      const data = await fetchDataForHome();
      return data;
    },
  });

const router = createRouter({ routeConfig });

Ключевой момент: функция loader на сервере вызывается до рендеринга, что позволяет серверу предоставлять готовые данные вместе с HTML, минимизируя количество клиентских запросов после загрузки страницы.

Работа с серверными запросами и параметрами

Маршруты на сервере могут принимать динамические сегменты пути и query-параметры. TanStack Router предоставляет объект context для передачи информации о запросе:

const routeConfig = createRouteConfig()
  .createRoute({
    path: '/users/:id',
    loader: async ({ params, request }) => {
      const { id } = params;
      const userData = await fetchUserById(id);
      return userData;
    },
  });

params содержит значения динамических сегментов, а request — экземпляр запроса, что позволяет учитывать заголовки, cookies или query-параметры при генерации контента.

Предзагрузка данных и управление состоянием

TanStack Router интегрируется с React Query и другими библиотеками управления состоянием для организации серверного рендеринга с предзагрузкой данных. Использование loader в комбинации с React Query позволяет кешировать данные на сервере и передавать их на клиент:

import { QueryClient, dehydrate } from '@tanstack/react-query';

const queryClient = new QueryClient();

const routeConfig = createRouteConfig()
  .createRoute({
    path: '/posts',
    loader: async () => {
      await queryClient.prefetchQuery(['posts'], fetchPosts);
      return dehydrate(queryClient);
    },
  });

Такой подход гарантирует, что клиент получит полностью подготовленное состояние, что ускоряет рендеринг и уменьшает количество сетевых запросов после загрузки страницы.

Управление редиректами на сервере

TanStack Router поддерживает серверные редиректы через специальное исключение redirect. Вызов редиректа в loader позволяет перенаправить пользователя до того, как страница будет сгенерирована:

import { redirect } from '@tanstack/router';

const routeConfig = createRouteConfig()
  .createRoute({
    path: '/protected',
    loader: async ({ request }) => {
      const isAuthenticated = checkAuth(request);
      if (!isAuthenticated) {
        throw redirect('/login');
      }
      return null;
    },
  });

Важно: на сервере редирект должен быть обработан соответствующим образом в маршрутизаторе Express, Fastify или любом другом серверном фреймворке, чтобы корректно вернуть статус 302 и заголовок Location.

Обработка ошибок на сервере

Для серверной навигации TanStack Router позволяет централизованно обрабатывать ошибки через errorBoundary или перехват исключений в loader:

const routeConfig = createRouteConfig()
  .createRoute({
    path: '/dashboard',
    loader: async () => {
      try {
        const data = await fetchDashboardData();
        return data;
      } catch (error) {
        throw new Error('Ошибка загрузки данных для Dashboard');
      }
    },
    errorComponent: DashboardError,
  });

Серверный рендеринг передает состояние ошибки в компонент errorComponent, что обеспечивает единый способ отображения ошибок как на сервере, так и на клиенте.

Интеграция с SSR-фреймворками

TanStack Router легко интегрируется с популярными SSR-фреймворками, включая Next.js и Remix. В таких сценариях важно правильно передавать маршрутизатор и данные через контекст сервера:

app.get('*', async (req, res) => {
  const context = { request: req };
  const initialData = await router.load({ url: req.url, context });
  const html = renderToString();
  res.send(`${html}`);
});

Такой подход обеспечивает корректную маршрутизацию, предзагрузку данных и обработку редиректов на уровне сервера.

Особенности кэширования и производительности

Для больших приложений серверная навигация требует внимания к производительности. TanStack Router позволяет кэшировать результаты loader с помощью React Query или собственного механизма мемоизации, снижая нагрузку на сервер и ускоряя генерацию страниц.