Исправляем проблему с history.replaceState() в Chrome
Быстрый ответ
Для модификации URL-адреса в браузере и соответствующего состояния без необходимости перезагружать страницу и создавать новую запись в истории браузера, воспользуйтесь методом history.replaceState(). Этот метод отлично подходит для AJAX-навигации в single-page приложениях.
Логика работы:
// URL изменяется на "updated-page.html", но страница при этом не перезагружается
history.replaceState({ detail: 'update' }, '', 'updated-page.html');
Суть: URL-адрес обновляется до updated-page.html, весь контент страницы остаётся без изменений. Объект состояния ({ detail: 'update' }) используется для отслеживания изменений в рамках текущей веб-страницы.
Важно помнить, что history.replaceState() не влияет на заголовок документа. Для его изменения необходимо отдельно прописать значение document.title:
Пример обновления заголовка:
// Теперь переименуем заголовок
document.title = 'Обновленный заголовок страницы';
history.replaceState({ detail: 'update' }, 'Обновленный заголовок страницы', 'updated-page.html');

Навигация по браузерному ландшафту
Каждый браузер имеет свои специфические характеристики, и они не всегда корректно обрабатывают параметр title для replaceState() и pushState(). В лучшем понимании этих тонкостей понадобится кое-какое время.
Выживание среди браузерных различий
Протестируйте свой код во всех популярных браузерах до релиза проекта, чтобы предотвратить неприятные сюрпризы. Имейте в виду, что поведение replaceState() может различаться в разных браузерах, например, Chrome или Opera.
Изменение заголовка документа
Когда осуществляется изменение заголовка документа, делаем это таким образом:
// Тсс, нас тут нет
document.getElementsByTagName('title')[0].innerHTML = 'новый заголовок';
Отслеживание изменений в навигации
Используйте событие window.onpopstate, чтобы отследить изменения в навигации истории браузера:
// О, кто-то нажал кнопку "назад"?
window.onpopstate = function(event) {
  if (event.state) {
    updateContent(event.state.detail);
  }
};
function updateContent(detail) {
  // Здесь размещаем логику для обновления контента
}
Обход препятствий AJAX
replaceState() в сочетании с AJAX позволяет получать и показывать новый контент, не вовлекая пользователя в ожидание перезагрузки страницы.
// Это время удивить пользователя новым контентом
function loadContent(url) {
  // Получаем контент, а затем обновляем URL без перезагрузки страницы
  fetch(url)
    .then(response => response.text())
    .then(html => {
      document.getElementById('content').innerHTML = html;
      history.replaceState({ content: html }, '', url);
    });
}
Если вы используете jQuery, это облегчает управление AJAX-контентом и взаимодействие с pushState и popstate.
Визуализация
Представьте history.replaceState() как хитроумного ассистента 🕵️♂️, который сценарий книги меняет так, не вызывая подозрений:
До использования ReplaceState: 📖 [Страница 1 – Вступление, Страница 2 – Развитие сюжета, Страница 3 – Кульминация]
Возвращается наш смекалистый помощник:
history.replaceState({page: 2}, "Заголовок", "/page-2");
После применения ReplaceState: 📖 [Страница 1 – Вступление, Страница 2 – Впечатляющий поворот сюжета!, Страница 3 – Кульминация]
Прочие даже не заподозрят, что что-то изменилось, история продолжает течь своим чередом.
Полезные материалы
- Метод History: replaceState() – Web API | MDN — подробное описание метода replaceState().
- Использование HTML5 History API | CSS-Tricks — руководство по работе с HTML5 History API.
- GitHub – devote/HTML5-History-API — повышение совместимости History API в браузерах, которые его не поддерживают изначально.
- javascript – Как изменить URL без перезагрузки страницы? – Stack Overflow — обсуждения на Stack Overflow по вопросу изменения URL без перезагрузки страницы.
- Якоря заголовков Markdown на GitHub · GitHub — использование history.replaceState()на практике.


