Отладка в браузере

Universal Router в JavaScript позволяет строить маршрутизацию без привязки к конкретному фреймворку, что делает отладку особенно важной при работе с чистым JS или гибридными приложениями. Первым шагом является явное логирование всех этапов маршрутизации. Для этого в момент инициализации маршрутизатора рекомендуется добавить промежуточную функцию, которая будет перехватывать каждый запрос и выводить информацию о совпадениях маршрутов, параметрах и результате разрешения:

import UniversalRouter from 'universal-router';

const routes = [
  { path: '/', action: () => 'Home' },
  { path: '/about', action: () => 'About' },
  { path: '/users/:id', action: ({ params }) => `User ${params.id}` },
];

const router = new UniversalRouter(routes, {
  context: {},
  resolveRoute(context, params) {
    console.log('Запрос маршрута:', context.pathname);
    console.log('Параметры:', params);
    return context.route.action(context, params);
  }
});

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


Использование history для имитации переходов

Для полноценной отладки важно отслеживать переходы между маршрутами без перезагрузки страницы. В браузере это удобно делать через объект history:

function navigate(path) {
  history.pushState({}, '', path);
  router.resolve({ pathname: path }).then(result => {
    console.log('Результат маршрута:', result);
  });
}

window.addEventListener('popstate', () => {
  router.resolve({ pathname: location.pathname }).then(result => {
    console.log('Попытка разрешения при back/forward:', result);
  });
});

Метод pushState позволяет симулировать переходы, а событие popstate помогает отлавливать изменения URL при нажатии кнопок браузера. Это особенно полезно для проверки динамических параметров и работы вложенных маршрутов.


Встроенное логирование маршрутов

Universal Router позволяет создавать цепочку middleware через переопределение метода resolveRoute. Можно добавить детализированное логирование времени выполнения каждого маршрута:

async function timedResolveRoute(context, params) {
  const start = performance.now();
  const result = await context.route.action(context, params);
  const end = performance.now();
  console.log(`Маршрут ${context.route.path} выполнен за ${(end - start).toFixed(2)}ms`);
  return result;
}

const routerWithTiming = new UniversalRouter(routes, { resolveRoute: timedResolveRoute });

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


Отладка вложенных маршрутов

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

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

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

async function debugNestedRoute(route, pathname) {
  console.log('Проверка маршрута:', route.path);
  if (route.children) {
    for (const child of route.children) {
      await debugNestedRoute(child, pathname);
    }
  }
}

Это помогает понять, какой именно уровень маршрута срабатывает при конкретном URL, и выявить конфликты между маршрутами с похожими путями.


Отладка параметров и query-параметров

Universal Router автоматически извлекает параметры из пути, но для детальной отладки часто нужно видеть полные query-параметры. Их можно извлечь через объект URLSearchParams и объединить с параметрами маршрута:

router.resolve({ pathname: '/users/42?tab=profile' }).then(result => {
  const urlParams = new URLSearchParams(window.location.search);
  const query = Object.fromEntries(urlParams.entries());
  console.log('Параметры маршрута:', result.params);
  console.log('Query-параметры:', query);
});

Это позволяет отследить как динамические сегменты пути (:id), так и строку запроса, что особенно важно при сложных интерфейсах с фильтрацией и сортировкой.


Интеграция с DevTools

Для более комплексной отладки удобно использовать инструменты браузера:

  • Вкладка Network — проверка загрузки ресурсов при асинхронных действиях маршрутов.
  • Вкладка Console — вывод промежуточных данных о параметрах, результатах action и времени выполнения.
  • Breakpoints в файлах маршрутов — установка остановки в точке вызова action или resolveRoute позволяет пошагово проследить логику разрешения.

Дополнительно можно создать глобальный middleware, который будет логировать каждый переход и автоматически показывать стек вызовов через console.trace().


Симуляция ошибок маршрутизации

Для проверки устойчивости маршрутов стоит намеренно создавать некорректные URL или выбрасывать исключения в action:

const errorRoutes = [
  { path: '/fail', action: () => { throw new Error('Искусственная ошибка'); } }
];

const routerWithErrorHandling = new UniversalRouter(errorRoutes);

routerWithErrorHandling.resolve({ pathname: '/fail' })
  .catch(err => console.error('Обработка ошибки маршрута:', err.message));

Это помогает убедиться, что приложение корректно обрабатывает исключения и не блокирует пользовательский интерфейс при сбоях.


Выводы по отладке в браузере

Эффективная отладка Universal Router строится на комбинации логирования параметров и маршрутов, контроля переходов через history, мониторинга времени выполнения и обработки ошибок. Использование встроенных DevTools и симуляция различных сценариев позволяет выявлять и исправлять ошибки до интеграции с фронтенд-фреймворками или бэкендом.