Categories

Single-Page Apps and HTML5 pushState

Posted on: August 3, 2015 by Dimitar Ivanov

Single-page apps and websites become more and more popular each day. Before building such an application, let's define how these apps should looks like and behave:

  • cross-browser support
  • bookmarkable links
  • working browser' Back/Forward buttons
  • seo-friendly links
  • crawlable application
  • works with disabled javascript

In my previous post (Crawlable AJAX Applications) I discussed how to get your ajax-driven app indexed by search engine crawlers and spiders using the hash-bang method. Now I intend to extend that topic by covering the HTML5 History pushState method.

History API

Open your browser' console and type window.history or simply history. In modern browsers you should see the following:

HTML5 History API
Figure 1. HTML5 History API

pushState

Pushes the given state onto the session history, with the given title, and, optionally, the given URL.

Syntax:
history.pushState(state, title, url);

Parameters:

state
A state object is an object representing a user interface state. When user navigates to a new state the popstate event is fired, and the state property of the event is equal to the history state object.
title
(currently ignored) A title for the state.
url
(optional) URL for the state. Both absolute and relative url's are accepted.
<script>
history.pushState(null, null, 'new-page.html');
// or
history.pushState({url: 'new-page.html'}, 'New Page');
// or
history.pushState({url: 'new-page.html', page: 2}, 'New Page', 'new-page.html');
</script>

popstate event

The popstate event is fired every time the current history entry changes. That happens when the user click on browser's Back/Forward buttons or programmatically by calling the history.back(), hitory.forward(), history.go() methods.

<script>
// jQuery
$(window).on('popstate', function (e) {
    var state = e.originalEvent.state;
    if (state !== null) {
        //load content with ajax
    }
});

// Vanilla javascript
window.addEventListener('popstate', function (e) {
    var state = e.state;
    if (state !== null) {
        //load content with ajax
    }
});
</script>

Working example

The next example demonstrates how the real single page app should looks like. See our working pushState demo. Source code is available on this GitHub repo.

<script>
$(function () {
    var load = function (url) {
        $.get(url).done(function (data) {
            $("#content").html(data);
        })
    };

    $(document).on('click', 'a', function (e) {
        e.preventDefault();

        var $this = $(this),
            url = $this.attr("href"),
            title = $this.text();

        history.pushState({
            url: url,
            title: title
        }, title, url);

        document.title = title;

        load(url);
    });

    $(window).on('popstate', function (e) {
        var state = e.originalEvent.state;
        if (state !== null) {
            document.title = state.title;
            load(state.url);
        } else {
            document.title = 'World Regions';
            $("#content").empty();
        }
    });
});
</script>

<a href="africa">Africa</a>
<a href="asia">Asia</a>
<a href="europe">Europe</a>
<a href="north-america">North America</a>
<a href="oceania">Oceania</a>
<a href="south-america">South America</a>
		
<div id="content"></div>

Single-page app SEO

You should differentiate the requests to the server and send proper content to the browser. For example: when request is made through XMLHttpRequest (AJAX requests) the response should contain only the requested content (specific portion of webpage). For regular requests you must sends whole webpage, e.g. html, head, body + page content.

Why pushState instead of hash-bangs

  • Clean URL's that doesn't broke the RFC 3986
  • Works even without javascript
  • Less care about crawling and indexing

In conclusion, since modern browsers are widely used, you should consider using the HTML5 pushState for building your killing single-page applications, and use #! hash-bang method if you intend to support old browsers. In fact, Facebook uses a dual approach - hash bangs for IE9 and pushState for modern browsers.

Browser compatibility

Chrome 5+, Firefox 4+, IE 10+, Safari 6+, Opera 11.5+

Make your website more secure by using the HTTP Headers for Wordpress, and never face a cross-origin issue again. Oh yes, it's FREE.
See also
References
Share this post

Share this post, then leave me a comment below with your thoughts about single page applications. Thanks so much for reading!


0 Comments

Comments are closed