David Heinemeier Hansson, creator of Ruby on Rails, recently announced on Twitter that a feature called Turbolinks will ship as default-on in the Gemfile of Ruby on Rails 4.0. Turbolinks is already powering the mobile website of Basecamp.
Someone at Hacker News posted a link to the Turbolinks repository on Github and titled it:
Turbolinks for Rails (like pjax)
So what is PJAX and what does Turbolinks do differently?
forward() methods then allow you to navigate through the pushed session history. This way
pushState can be used to store the navigation history of the current page and dynamically switch backwards on forwards through different states without reloading the whole page.
PJAX is a portmanteau of the terms
The above sketch shows how PJAX works in practice. First (1) a normal GET request is sent to the server, which returns a complete page (2). All consecutive requests (3) triggered by clicking on a link will only fetch part of a page (4).
On the client-side you define the container (
#main in this case) that should be replaced when a link to
/authors is clicked.
PJAX also requires the server-side application to only return the selected part of the page. For this reason PJAX adds a HTTP header called
X-PJAX to the request, to let the web-application know that the request is coming from PJAX. In Rails you can simply check for that header and set
render :layout => false.
There are other ways of using PJAX in Rails, most of which have been described by Ryan Bates in Railscasts Episode #294. PJAX has its downsides in that you carefully have to think about which parts of a page to replace.
Turbolinks also uses
pushState, but instead of replacing only parts a page it loads a complete website from the server and replaces the
<body> in the currently loaded DOM. By default it applies this to all links on a page. So unlike PJAX you don't have to mark links and containers to support in place reloading, Turbolinks will handle that for you.
Right now, Turbolinks is in a very early stage of development, but as mentioned before, already in use at Basecamp. To use it in your Ruby (Sinatra, Rails, ..) project simply add the turbolinks gem to you app:
Do not forget to run
bundle install after editing the Gemfile to install the gem. You will then need to add the
turbolinks.js.coffee file to the asset pipeline by adding a line in
From now on all requests made by a browser that supports
pushState will be handled by
turbolinks. Browsers that have no support for
pushState will still work, as they just fallback to the default link action. You can check if everything is working by opening the developer tools in your browser (hit F12 in Chrome) and opening the Network tab. You should see that
turbolink.js is handling the requests when you click on a link.
If you want to manually exclude links from being handled by Turbolinks you can add the
data-no-turbolink attribute to the link tag:
This will tell Turbolinks to ignore this link. You can apply this attribute to any container up to
<body> and Turbolinks will ignore all links inside that container. One problem arises when you use
document.ready into a seperate function and bind it to both
document.ready and the
Note: Turbolinks is written in CoffeeScript and will therefore require the
coffee -c turbolinks.js.coffee which will compile the file to
The user JuDue asked an interesting question on Hacker News:
[..] the inevitable vs PJAX conversation (ie: is it flexible enough? Does it need to be?)
As so often the answer is: It depends. Turbolinks definitely improved client-side page loading. The problem is, that the server still has to render the complete website. If that is a bottleneck in your application then Turbolinks will not help. PJAX on the other side can certainlysolve this by rendering only those parts of a website that really need to be updated, but at the cost of additional work when developing the application.
As for flexibility, it highly depends on your needs. If you only have a few links where you want to exclude Turbolinks then it should be no problem. If you serve large websites with a lot of page content you might want to stick to PJAX to update only small parts of your page and keep the network traffic to a minimum.