moex-vibe/apps/docs/docs/adr/ADR-018-tanstack-router.md

4.1 KiB
Raw Blame History

ADR-018: TanStack Router как основной роутер

Дата: 2026-06-23 Статус: Принято Автор: AI Agent (codex/frontend-infrastructure-tooling)

Контекст

Проект использует react-router-dom v6 для клиентской маршрутизации. Текущая реализация:

  • Все страницы импортируются статически в AppRoutes.tsx
  • Нет lazy loading (code splitting) — каждая навигация грузит весь бандл
  • Параметры роутов (useParams) и search params (useSearchParams) не типизированы
  • Нет встроенной валидации search params
  • Проект уже использует TanStack Query — потенциальная синергия с TanStack Router

Требуется:

  • Route-level code splitting для оптимизации бандла
  • Типобезопасность параметров и search params
  • Интеграция с существующим TanStack Query (prefetching через loaders)

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

react-router-dom v6 + React.lazy

  • Минимальные изменения — обернуть каждый импорт в React.lazy + <Suspense>
  • Не решает проблему типизации
  • Нет prefetching / loaders
  • React.lazy boilerplate на каждый роут

TanStack Router

  • Полная типобезопасность через генерацию RouteTree
  • Search params с Zod-схемами
  • Code splitting built-in — каждый роут ленивый по умолчанию
  • Loaders для prefetching + интеграция с TanStack Query
  • Pending/Error/NotFound boundaries на уровне роута
  • Размер: ~3-4KB gzip (меньше react-router-dom)
  • Требует переписывания всех роутов и навигации

Решение

Мигрировать на TanStack Router.

Причины:

  1. Типобезопасность — RouteTree generation исключает опечатки в путях и невалидные search params
  2. Code splitting без boilerplate — built-in lazy, не нужен React.lazy
  3. Синергия с TanStack Query — уже используется в проекте; loaders дают prefetching данных до рендера компонента
  4. Zod — уже используется для валидации форм; Router использует Zod для search params
  5. Search params — типизированная валидация вместо строковых useSearchParams
  6. Меньший размер — 3-4KB vs 8KB react-router-dom

Последствия

Положительные

  • Каждая страница — отдельный chunk, грузится по требованию
  • Search params валидируются Zod-схемами (screener, broker-operations)
  • Loaders предзагружают данные, уменьшая время до первого контента
  • Guard'ы (ProtectedRoute) реализуются через beforeLoad, единый подход

Риски

  • Переписывание всех роутов, компонентов навигации (Link, useNavigate) и тестов
  • MemoryRouter в тестах заменяется на createMemoryRouter из TanStack Router
  • Файловая структура роутов меняется — src/app/routes/ с Route Tree generation
  • Learning curve для команды

Миграция

  • Каждый роут переносится по одному
  • Старый AppRoutes.tsx сохраняется до полного прохождения тестов
  • react-router-dom удаляется только после верификации

Связанные документы

  • docs/research/frontend-infrastructure-tooling/react-router-vs-tanstack-router.md
  • docs/features/frontend-infrastructure-tooling/plan.md (Phase 6)