Good tutorial for using HTML5 History API (Pushstate?) [closed]

I am looking into using the HTML5 History API to resolve deep linking problems with AJAX loaded content, but I am struggling to get off the ground. Does any one know of any good resources?

I want to use this as it seems a great way to allow to the possibility of those being sent the links may not have JS turned on. Many solutions fail when someone with JS sends a link to someone without.

My initial research seems to point to a History API within JS, and the pushState method.



For a great tutorial the Mozilla Developer Network page on this functionality is all you'll need:

Unfortunately, the HTML5 History API is implemented differently in all the HTML5 browsers (making it inconsistent and buggy) and has no fallback for HTML4 browsers. Fortunately, History.js provides cross-compatibility for the HTML5 browsers (ensuring all the HTML5 browsers work as expected) and optionally provides a hash-fallback for HTML4 browsers (including maintained support for data, titles, pushState and replaceState functionality).

You can read more about History.js here:

For an article about Hashbangs VS Hashes VS HTML5 History API, see here:


I benefited a lot from 'Dive into HTML 5'. The explanation and demo are easier and to the point. History chapter - and history demo -


Keep in mind while using HTML5 pushstate if a user copies or bookmarks a deep link and visits it again, then that will be a direct server hit which will 404 so you need to be ready for it and even a pushstate js library won't help you. The easiest solution is to add a rewrite rule to your Nginx or Apache server like so:

Apache (in your vhost if you're using one):

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]


rewrite ^(.+)$ /index.html last;

The HTML5 history spec is quirky.

history.pushState() doesn't dispatch a popstate event or load a new page by itself. It was only meant to push state into history. This is an "undo" feature for single page applications. You have to manually dispatch a popstate event or use history.go() to navigate to the new state. The idea is that a router can listen to popstate events and do the navigation for you.

Some things to note:

  • history.pushState() and history.replaceState() don't dispatch popstate events.
  • history.back(), history.forward(), and the browser's back and forward buttons do dispatch popstate events.
  • history.go() and history.go(0) do a full page reload and don't dispatch popstate events.
  • history.go(-1) (back 1 page) and history.go(1) (forward 1 page) do dispatch popstate events.

You can use the history API like this to push a new state AND dispatch a popstate event.

history.pushState({message:'New State!'}, 'New Title', '/link'); window.dispatchEvent(new PopStateEvent('popstate', { bubbles: false, cancelable: false, state: history.state }));

Then listen for popstate events with a router.


You could try Davis.js, it gives you routing in your JavaScript using pushState when available and without JavaScript it allows your server side code to handle the requests.


Here is a great screen-cast on the topic by Ryan Bates of railscasts. At the end he simply disables the ajax functionality if the history.pushState method is not available:


You may want to take a look at this jQuery plugin. They have lots of examples on their site.


I've written a very simple router abstraction on top of History.js, called StateRouter.js. It's in very early stages of development, but I am using it as the routing solution in a single-page application I'm writing. Like you, I found History.js very hard to grasp, especially as I'm quite new to JavaScript, until I understood that you really need (or should have) a routing abstraction on top of it, as it solves a low-level problem.

This simple example code should demonstrate how it's used:

var router = new staterouter.Router();
// Configure routes
  .route('/', getHome)
  .route('/persons', getPersons)
  .route('/persons/:id', getPerson);
// Perform routing of the current state

Here's a little fiddle I've concocted in order to demonstrate its usage.


if jQuery is available, you could use jQuery BBQ


Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.