Last Updated: November 18, 2020
·
31.89K
· rstacruz

Faster page loads with Turbolinks

Rails released their [Turbolinks] gem, which is a small JavaScript snippet that loads your pages via AJAX. The net result is an app that feels more responsive.

Here's a guide to Turbolinks's caveats that I gathered from experience.


Load order

You need to have this load order below:

  • jQuery
  • [jQuery.turbolinks]
  • ...other scripts go here...
  • [Turbolinks]

The reason for jQuery.turbolinks being before all scripts is so to let it hijack the $(function() { ... }) call that your other scripts will use.

Turbolinks then needs to be at the end because it has to be the last to install the click handler, so not to interfere with other scripts.


Scripts in head

You may be putting your scripts at the end of the <body> tag. If you're using Turbolinks, move them back to <head>. The reason for this is that Turbolinks works by swapping out the <body> when changing pages, and doing so will re-execute all your third-party scripts (imagine jQuery being re-evaluated), which may not be what you want.


head scripts must NOT change

Always go by the assumption that all Turbolinks-enabled pages should have the <head> contents. If any page doesn't fit this standard, either refactor it or opt it out of turbolinks (<a href='...' data-no-turbolink>).


Loading spinner

You WILL need a loading indicator! This should be pretty easy to do:

$(document).on('page:fetch', function() {
  $(".loading-indicator").show();
});
$(document).on('page:change', function() {
  $(".loading-indicator").hide();
});

Every Turbolinks site will need this, otherwise it will feel very weird that clicking a link will seem to do nothing.


Google analytics integration

If you put your Google analytics script in your <head> (like Google recommends), it will only fire once and not fire again when changing pages via Turbolinks.

You need to manually fire the trackPageview on every page load:

<body>
   <script>_gaq.push(['_trackPageview']);</script>
   ...the rest of the body here...
</body>

...also, be sure to modify the Analytics snippet not to do '_trackPageview' automatically.

Some people recommend placing it in a page:change handler, which I think is a very naive solution that should be avoided, since it means that older browsers will not record visits to Analytics.


Using turbolinks outside Rails

Turbolinks is simply two things:

  • [A JavaScript script][turbolinks.coffee]
  • [A small server-side shim][turbolinks.rb] to use X-XHR-Referer as the Referrer

You can use the JavaScript script on your non-Rails project, just be aware of the Referrer caveat.


jQuery integration

First of all, you're most likely using jQuery. Go check out [jQuery.turbolinks], which hijacks all $(function() { ... }) calls to load every time the page loads via Turbolinks.

[Turbolinks]: https://github.com/rails/turbolinks
[jQuery.turbolinks]: https://github.com/kossnocorp/jquery.turbolinks
[turbolinks.coffee]: https://github.com/rails/turbolinks/blob/master/lib/assets/javascripts/turbolinks.js.coffee
[turbolinks.rb]: https://github.com/rails/turbolinks/blob/master/lib/turbolinks.rb

4 Responses
Add your response

Thanks for the tips!

Your tip regarding turbolinks and Google Analytics is particularly appreciated; is this the best way to do it? It's difficult to test; does this fire every time a new page is loaded via turbolinks, without having to bind to the page:change handler? I see that solution a lot, but your is more elegant and better if it includes the older browsers... I just don't know how to be 100% sure any one solution works 100% of the time.

Turbolinks is awesome, but also a real pain sometimes.

over 1 year ago ·

Thank you for being the only person with a sane solution to using Google Analytics with Turbolinks! The only thing I had to add was a callback on the page:restore event to track the pageview, since the inline script tag isn't re-evaluated when the page is restored from the Turbolinks cache.

See the issue I opened with the Turbolinks-compatibility project for an example of the callback: https://github.com/reed/turbolinks-compatibility/issues/19#issuecomment-29759877

Thanks again!

over 1 year ago ·

Following up here with my own solution. I wanted to find a way to support old browsers, but not have to put script tags in the body.

https://gist.github.com/jonwolfe/7897610

over 1 year ago ·

When viewing Turbolinks enabled links from website cache in google cache, i.e. cache:<webpage link> it just keeps refreshing the page but doesn't load the page and lead to open the website as other site's link does. Is this okay from SEO perspective?

over 1 year ago ·