History API дає змогу змінювати адресу в рядку браузера і записи в історії переходів без завантаження нової сторінки. На ньому побудовані маршрутизатори SPA (Vue Router, React Router), wire:navigate у Livewire, фільтри каталогів, що відображаються в URL.
pushState - додати новий запис в історію:
history.pushState({ page: 2 }, '', '/jobs?page=2');
Адреса змінилася, кнопка «Назад» поверне на попередню, але запиту на сервер не було і сторінка не перезавантажилася. Що показати - вирішує ваш код.
replaceState - замінити поточний запис, не додаючи нового. Для змін, які не повинні засмічувати історію: введення в поле пошуку, сортування, позиція прокрутки.
popstate - подія, коли користувач переходить по історії кнопками «Назад»/«Вперед»:
window.addEventListener('popstate', (event) => {
renderPage(event.state?.page ?? 1); // відновити стан для цього запису
});
Важливо: pushState і replaceState не викликають popstate. Подія спрацьовує лише при навігації по історії. Тому після pushState оновлювати інтерфейс треба самостійно.
Об'єкт стану (перший аргумент) зберігається разом із записом історії і повертається в event.state. Він серіалізується (як structuredClone), має обмеження розміру - туди кладуть невеликі дані (номер сторінки, id), а не весь список товарів.
Що треба зробити серверу: якщо користувач оновить сторінку чи відкриє посилання /jobs?page=2 напряму, запит піде на сервер. Сервер мусить уміти віддати цю сторінку - інакше 404. Для SPA це «fallback» на index.html, у Laravel - звичайний маршрут, що рендерить сторінку з відповідним станом.
Типові вимоги до SPA-навігації, які легко забути:
- заголовок сторінки (
document.title) - змінюється вручну; - прокрутка: при переході вперед - на початок, при «Назад» - туди, де користувач був. Браузерне
history.scrollRestorationінколи доводиться вимикати й керувати самостійно; - фокус і доступність: зчитувачі екрана не знають, що «сторінка змінилася», - фокус переводять на заголовок нового вмісту;
- аналітика: перегляд сторінки треба відправляти вручну.
Navigation API - новіший інтерфейс із єдиною подією navigate для всіх переходів (посилання, форми, кнопки історії) і перехопленням через event.intercept(). Він простіший для маршрутизаторів, але підтримується ще не всіма браузерами.