Полифиллы для History API

History API в браузерах позволяет управлять историей навигации без полной перезагрузки страницы. Основные методы включают:

  • history.pushState(state, title, url) — добавляет новый элемент в историю браузера.
  • history.replaceState(state, title, url) — заменяет текущий элемент истории.
  • window.onpopstate — событие, срабатывающее при навигации назад или вперёд.

Однако поддержка History API в старых браузерах (например, Internet Explorer 9 и ниже, старые версии Android Browser и Safari) ограничена. Эти ограничения проявляются в невозможности корректно использовать pushState, replaceState и обработку события popstate. В таких случаях возникают проблемы с корректной навигацией в одностраничных приложениях (SPA), где переход между “страницами” осуществляется динамически.

Роль полифиллов

Полифиллы решают проблему отсутствия или неполной реализации History API в старых браузерах. Основные задачи полифилла:

  • Эмуляция методов pushState и replaceState.
  • Генерация событий popstate при изменении URL.
  • Поддержка работы с хешами (#) как альтернативой History API.

Полифиллы не способны полностью воспроизвести поведение современного History API, но обеспечивают совместимость, позволяя SPA корректно работать в устаревших браузерах.

Полифиллы и Page.js

Page.js — это библиотека маршрутизации для SPA, которая использует History API для навигации без перезагрузки страницы. В современных браузерах Page.js использует pushState и событие popstate для управления маршрутами.

В старых браузерах, где History API недоступен, Page.js может быть сконфигурирован на работу через хеш-историю. При этом URL изменяется через window.location.hash, а маршруты отслеживаются через событие hashchange. Пример конфигурации:

page({
  hashbang: true
});

Опция hashbang: true заставляет Page.js использовать хеши вместо History API. Это обеспечивает совместимость с браузерами, не поддерживающими pushState.

Пример полифилла для pushState

Один из распространённых подходов — создание условного полифилла, который проверяет поддержку History API и заменяет методы при необходимости:

if (!window.history.pushState) {
  window.history.pushState = function(state, title, url) {
    window.location.hash = url;
  };
  
  window.history.replaceState = function(state, title, url) {
    var hashIndex = window.location.href.indexOf('#');
    window.location.href = window.location.href.substring(0, hashIndex) + '#' + url;
  };

  window.onpopst ate = function(event) {
    var hash = window.location.hash.replace('#', '');
    // Логика маршрутизации через Page.js или аналог
    page(hash);
  };
}

В этом примере:

  • pushState заменяется на изменение хеша URL.
  • replaceState корректирует текущий URL без добавления нового элемента в историю.
  • onpopstate вызывается при изменении хеша, имитируя стандартное событие popstate.

Интеграция с Page.js

При использовании Page.js полифилл подключается перед инициализацией маршрутов:

// Подключение полифилла
// ...

// Настройка маршрутов
page('/', () => {
  console.log('Главная страница');
});

page('/about', () => {
  console.log('Страница о нас');
});

// Инициализация Page.js
page({ hashbang: !history.pushState });

Таким образом, Page.js автоматически выбирает подходящий механизм навигации: History API или хеши.

Рекомендации по разработке

  • Проверка поддержки History API должна выполняться до подключения Page.js, чтобы выбрать корректный режим работы.
  • Для старых браузеров необходимо обеспечить корректное отображение URL и обработку событий popstate/hashchange.
  • Полифиллы не решают всех проблем совместимости (например, анимации переходов между страницами могут вести себя иначе).

Примеры известных полифиллов

  1. history.js — расширенный полифилл, поддерживающий pushState, replaceState и popstate в старых браузерах.
  2. es5-shim + hashchange — комбинация для эмуляции методов History API через хеши и события hashchange.
  3. Page.js internal fallback — встроенный механизм, который использует хеши при отсутствии pushState.

Использование полифиллов совместно с Page.js обеспечивает максимальную совместимость SPA и позволяет старым браузерам корректно обрабатывать маршруты и навигацию без полной перезагрузки страницы.