Отличия от history API

History API предоставляет низкоуровневый интерфейс для управления историей браузера: pushState, replaceState, popstate. Это императивный инструмент, где разработчик самостоятельно описывает, когда и как изменять состояние истории, отслеживать изменения URL и синхронизировать их с интерфейсом.

Navigo, напротив, реализует декларативный подход. Вместо явного управления историей создаётся карта маршрутов:

const router = new Navigo('/');

router
  .on('/about', () => { /* ... */ })
  .on('/users/:id', (params) => { /* ... */ })
  .resolve();

Здесь разработчик описывает соответствие URL → обработчик, а библиотека берёт на себя:

  • парсинг адресной строки
  • извлечение параметров
  • подписку на изменения истории
  • вызов нужных обработчиков

Работа с URL: ручной разбор против встроенного механизма

При использовании History API приходится вручную:

  • анализировать location.pathname
  • выделять сегменты URL
  • обрабатывать query-параметры
  • поддерживать регулярные выражения для динамических маршрутов

Пример:

window.addEventListener('popstate', () => {
  const path = location.pathname;
  if (path.startsWith('/users/')) {
    const id = path.split('/')[2];
    // обработка
  }
});

В Navigo это реализовано на уровне библиотеки:

router.on('/users/:id', ({ data }) => {
  console.log(data.id);
});

Ключевое отличие:

  • History API — полная свобода и ответственность
  • Navigo — встроенный парсер маршрутов и параметров

Обработка событий: popstate vs абстракция

History API требует явной подписки на событие popstate:

window.addEventListener('popstate', handler);

Также необходимо учитывать:

  • начальную загрузку страницы
  • переходы вперёд/назад
  • синхронизацию состояния приложения

Navigo инкапсулирует эту логику:

router.resolve();

Внутри:

  • подписка на popstate
  • вызов соответствующего обработчика
  • учёт начального URL

Разница:

  • History API — ручное управление жизненным циклом
  • Navigo — автоматическое управление событиями

Управление переходами

С History API переходы инициируются напрямую:

history.pushState({}, '', '/about');
renderPage('/about');

Разработчик обязан:

  • изменить URL
  • вручную вызвать перерисовку интерфейса

В Navigo переходы централизованы:

router.navigate('/about');

Библиотека:

  • обновляет URL
  • вызывает обработчик маршрута
  • обеспечивает консистентность состояния

Поддержка динамических маршрутов

В History API динамические маршруты реализуются вручную через:

  • строковые операции
  • регулярные выражения
const match = location.pathname.match(/^\/users\/(\d+)$/);
if (match) {
  const id = match[1];
}

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

router.on('/users/:id', ({ data }) => {
  console.log(data.id);
});

Поддерживаются:

  • параметры (:id)
  • wildcard (*)
  • вложенные маршруты

Middleware и hooks

History API не содержит встроенной концепции middleware. Любая логика:

  • авторизация
  • логирование
  • проверка прав доступа

реализуется вручную.

Navigo поддерживает middleware-подобные механизмы:

router.on('/admin', {
  uses: [authMiddleware],
  as: 'admin'
});

Это позволяет:

  • централизовать проверку доступа
  • переиспользовать логику
  • структурировать код

Обработка ошибок и fallback

При работе с History API необходимо вручную:

  • определять, существует ли маршрут
  • обрабатывать 404
if (!routeFound) {
  renderNotFound();
}

В Navigo предусмотрен fallback:

router.notFound(() => {
  // обработка 404
});

Управление базовым URL

History API не предоставляет встроенного механизма для работы с базовым путём приложения. Это особенно важно при размещении SPA не в корне сайта.

В Navigo можно задать базовый путь:

const router = new Navigo('/app');

Библиотека автоматически учитывает этот префикс при:

  • разборе URL
  • навигации
  • генерации ссылок

Работа с ссылками

При использовании History API необходимо:

  • перехватывать клики по <a>
  • предотвращать стандартное поведение
  • вручную вызывать pushState
document.addEventListener('click', (e) => {
  if (e.target.matches('a')) {
    e.preventDefault();
    history.pushState({}, '', e.target.href);
    handleRoute();
  }
});

В Navigo есть встроенная обработка ссылок:

router.updatePageLinks();

После вызова:

  • все ссылки автоматически перехватываются
  • переходы обрабатываются роутером

Масштабируемость и читаемость

History API:

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

Navigo:

  • предоставляет структурированную модель маршрутов
  • облегчает поддержку большого количества путей
  • снижает количество повторяющегося кода

Производительность и контроль

History API:

  • максимальный контроль
  • отсутствие лишних абстракций
  • минимальные накладные расходы

Navigo:

  • небольшая прослойка абстракции
  • удобство ценой минимального overhead
  • оптимизирован для типичных SPA-сценариев

Итоговое сравнение ключевых аспектов

Аспект History API Navigo
Уровень абстракции Низкий Высокий
Маршрутизация Ручная Декларативная
Парсинг URL Вручную Встроенный
Обработка событий popstate Автоматическая
Динамические маршруты Через regex Через синтаксис :param
Middleware Нет Есть
404 обработка Вручную Через notFound()
Работа со ссылками Вручную updatePageLinks()
Масштабируемость Ограничена архитектурой Высокая

Когда оправдано использование History API напрямую

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

Когда предпочтителен Navigo

  • SPA с множеством маршрутов
  • необходимость в динамических параметрах
  • желание упростить код и сократить boilerplate
  • работа в команде, где важна читаемость и поддерживаемость