I was looking for something simple, like a tiny module, that would do one thing and one only with the browser's history.

I was looking for a way to intercept a generic page click, a way capable of letting me organize my Web Apps through Ajax, or fetch calls.

Missing in History (API)

The mechanism behind the History API is simple, yet powerful, but it has a little hidden gotcha:

Note that just calling history.pushState() or history.replaceState() won't trigger a popstate event.

Accordingly, we can always listen to changes when these come from a previous state.

This also means every time we invoke a pushState, an action 99% of time used to load some content from the client in order to update only what's needed instead of reloading the whole new page, we need a smart mechanism to react to such state change.

Moreover, we most likely don't ever want to listen to anchors on the page, clicked just to scroll elements into the view, and not to trigger a page load action.

In these cases, the triggered popstate would be more than unnecessary because we simply just don't care.

The onpushstate solution.

This tiny library seamlessly brings the following features to any page:

Feel free to open your browser console and verify all logs.

You can always use the history object and its current .state property to understand where does it come from, comparing it with the always available location.

// you can compare these two object
const curr = new URL(location);
const prev = new URL(history.state);
      

Compatibility

This library is compatible with all modern browsers.

Older browsers might need one or more polyfill upfront for:

To test your target browser either try this page or include this library via unpkg.

<script
  src="//unpkg.com/onpushstate@latest/min.js"
></script>