Отладка проблем с маршрутизацией

Universal Router строит маршрутизацию на основе цепочки правил и функций обработки. Ошибки в маршрутах чаще всего связаны с неправильным порядком определения маршрутов, конфликтами путей и неожиданным поведением функций action.

Для диагностики таких проблем важно использовать пошаговый анализ маршрута. Основная техника — это логирование объекта маршрута и промежуточных значений, передаваемых в функцию resolve.

const router = new UniversalRouter(routes, {
  resolveRoute(context, params) {
    console.log('Маршрут:', context.route.path);
    console.log('Параметры:', params);
    return context.route.action ? context.route.action(context, params) : null;
  }
});

Такое логирование позволяет точно определить, какой маршрут сработал и какие параметры были извлечены из URL. Особенно это важно при работе с динамическими сегментами (:id, :slug) и опциональными параметрами.


Работа с приоритетами маршрутов

Universal Router обрабатывает маршруты последовательно, от первого к последнему. Порядок маршрутов критически важен при наличии пересекающихся шаблонов:

const routes = [
  { path: '/users/:id', action: () => 'User Detail' },
  { path: '/users/new', action: () => 'New User' }
];

В этом примере /users/new никогда не сработает, так как /users/:id перехватывает запрос первым. Решение — менять порядок определения маршрутов:

const routes = [
  { path: '/users/new', action: () => 'New User' },
  { path: '/users/:id', action: () => 'User Detail' }
];

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


Отладка асинхронных действий

Функции action в Universal Router могут возвращать промисы, что приводит к асинхронной маршрутизации. Ошибки часто возникают из-за незавершённых промисов или необработанных исключений:

const routes = [
  {
    path: '/data/:id',
    async action({ params }) {
      const response = await fetch(`/api/data/${params.id}`);
      if (!response.ok) throw new Error('Ошибка загрузки данных');
      return response.json();
    }
  }
];

Для отладки важно:

  1. Ловить ошибки внутри action с помощью try/catch.
  2. Логировать каждый шаг асинхронной операции.
  3. Проверять правильность возврата значений из промиса, так как любое undefined может нарушить дальнейшую обработку.

Диагностика конфликтов маршрутов

Конфликты часто проявляются при использовании переопределений и вложенных маршрутов. Universal Router позволяет использовать children для вложенной маршрутизации:

const routes = [
  {
    path: '/dashboard',
    children: [
      { path: '', action: () => 'Dashboard Home' },
      { path: 'settings', action: () => 'Settings' }
    ]
  }
];

Ошибки могут возникать, если:

  • Вложенный путь начинается с / — он рассматривается как абсолютный и игнорирует родительский.
  • Родительский маршрут не определяет action — это допустимо, но может создать неожиданный результат, если отсутствует default путь.

Использование отладочных инструментов

Для системного анализа маршрутизации можно применять несколько методов:

  1. Логирование маршрутов: вывод объекта маршрута с path, name, action.
  2. Тестирование с URL: передавать разные строки URL в метод router.resolve(url) и сравнивать результат.
  3. Мокирование контекста: создавать объект context с минимальными свойствами (pathname, query) для локальной проверки action.

Пример мокирования:

const context = { pathname: '/users/123', query: {} };
router.resolve(context.pathname).then(result => console.log(result));

Обработка ошибок разрешения

Universal Router поддерживает глобальную обработку ошибок через catch на промисе resolve. Это особенно полезно для выявления необработанных маршрутов:

router.resolve('/unknown-path')
  .then(result => console.log(result))
  .catch(error => console.error('Ошибка маршрутизации:', error.message));

Типичные ошибки:

  • Route not found — путь не совпадает ни с одним маршрутом.
  • Исключения в action — нужно проверять и логировать.

Советы по системной отладке

  • Всегда проверять порядок маршрутов — динамические сегменты могут перехватывать более конкретные пути.
  • Разделять вложенные маршруты и убедиться, что дочерние пути не начинаются с /, если они должны быть относительными.
  • Асинхронные маршруты должны возвращать корректный результат и обрабатывать исключения.
  • Логировать контекст и параметры при каждом вызове resolve.
  • Использовать catch для глобальной обработки ошибок, чтобы видеть необработанные пути и исключения.

Эти методы позволяют выявлять и исправлять большинство проблем с маршрутизацией в Universal Router, обеспечивая предсказуемое поведение приложения.