PJAX TURBOLINKS SPA Hacks
First there was PJAX
On February 26, 2011, Chris Wanstrath, the co-founder of Github made an initial commit to jquery-pjax, — “A jQuery plugin that uses AJAX and
pushState to deliver a fast browsing experience with real permalinks, page titles, and a working back button.“
The idea is that whenever a user clicks a link, the plugin takes control, fetches all the required assets, and updates the page with the new resources. It's like using
diff on the web.
This was the first serious attempt to turn a website to a single-page application. Unfortunately, this project was eventually abandoned.
Then came Turbolinks
It ditched jQuery, integrated to Ruby On Rails, and is actively maintained. Slowly it's active usage surpassed PJAX.
The SPA takeover
In the past six years, the rise of single-page applications has been incredible, but only with “real” desktop-like applications. The original idea of pjax, to turn your content-heavy website to a single-page app, became a thing only for a hobbyist.
This article brings this extremely powerful technique back to the forefront and introduces some new tricks to make page loading even faster.
This website is a live demonstration of this power. Please click any of the links to get a sense of the speed — even when the pages are loaded directly from a $5.00 server in Falkenstein (a 3,388 people village in Bavaria, Germany) and without using a content delivery network.
Taking things further
The basic idea in PJAX and Turbolinks is to load assets with
XMLHttpRequest and change the URL with
history.pushState. Put the library in place, and you should get fast page loads out of the box. However, you can take things further.
CSS speed bump
When we switch pages we load all the required stylesheets on the background and insert them on the page. We saw a big speed increase on speed when taking advantage of the
disabled property of a
link tag. Instead of removing the undeeded stylesheets, we set them disabled instead. Coupled with aggressive caching all the successive page switches now take less than 10 milliseconds to execute. This is so quick that it feels almost wrong: the web is not supposed to be this fast.
Whenever a visitor hovers a link on a desktop browser we fetch the corresponding page into memory so when the click event happens we already have the page available. This shaves off a few more milliseconds.
The bulk content of this website is statically served by Nginx. However, this website is far from static. You can, for example, post comments, suggest new features, join mailing lists and try the product demo. These dynamic components are handled by a cluster of Node servers behind Nginx.
Custom page lifecycle
All the components listen to a set of custom events when a page is initialized. They are fired in the following order:
route— when the URL changes and the page HTML is rendered
metadata— when page metadata via “front matter” is available
data— when backend data is loaded and before the components are mounted
load— when all the assets are loaded and components are mounted
unload— when the page is unloaded and the components are unmounted
We know it's a bit weird that fonts make the biggest impact on page load, but we try to optimize our site for maximum readability. The dynamic parts and search engine optimization comes second.
Is it worth the effort
This was not a small job, but was it worth the effort? Should we take this even further? Maybe start using CDN or leave out all the custom fonts?
We built Volument to answer these tricky questions. We wanted to know if our work does more good than harm. For every tweak we do, we want to see in detail how it impacted the first-time user experience, return intensity and conversions. Something like this: