top | item 45408222

(no title)

iamjackg | 5 months ago

I was pleasantly surprised by how responsive it was, and overjoyed when I clicked back and immediately came back to HN: no messy history. Genius idea!

discuss

order

mjmas|5 months ago

history.pushState vs history.replaceState

zaidhaan|5 months ago

One thing to note about these two APIs is that they affect how the session history (the back/forward stack) behaves, but the global browser history (entries shown in the History tab) is separate.

Most browsers record every change in the global history regardless of whether `history.pushState` or `history.replaceState` is used. The HTML Spec[0] is explicit about session history but does not define how global history should behave.

I can understand why the spec makes no mention of this -- global history is a user-facing UI feature, similar to address bar autocomplete, and it makes sense for browsers to control this behavior. That said, I'm always annoyed when I look into my history tab after visiting a page like this (e.g. Vercel Domains[1]), and see my global history flooded with entries for each individual keystroke I've made, all in the name of "user experience".

In this particular case, it's just a fun gimmick, but for everyday websites I'd much prefer if they just debounced the updates to the URL to avoid cluttering the global history.

[0]: https://html.spec.whatwg.org/#navigation-and-session-history

[1]: https://vercel.com/domains

dhsysusbsjsi|5 months ago

reading the source it looks like for some browsers that rate limit url updates, it has to use a different way that nukes your back button ability.

senfiaj|5 months ago

function drawWorld() { var hash = '#|' + gridString() + '|[score:' + currentScore() + ']';

  if (urlRevealed) {
    // Use the original game representation on the on-DOM view, as there are no
    // escaping issues there.
    $('#url').textContent = location.href.replace(/#.*$/, '') + hash;
  }

  // Modern browsers escape whitespace characters on the address bar URL for
  // security reasons. In case this browser does that, replace the empty Braille
  // character with a non-whitespace (and hopefully non-intrusive) symbol.
  if (whitespaceReplacementChar) {
    hash = hash.replace(/\u2800/g, whitespaceReplacementChar);
  }

  history.replaceState(null, null, hash);

  // Some browsers have a rate limit on history.replaceState() calls, resulting
  // in the URL not updating at all for a couple of seconds. In those cases,
  // location.hash is updated directly, which is unfortunate, as it causes a new
  // navigation entry to be created each time, effectively hijacking the user's
  // back button.
  if (decodeURIComponent(location.hash) !== hash) {
    console.warn(
      'history.replaceState() throttling detected. Using location.hash fallback'
    );
    location.hash = hash;
  }
}