Speeding up your app’s navigation with Turbolinks

Turbolinks 5

Turbolinks has been bundled with Rails and included in new applications by default since Rails 4. Rails 5 ships with Turbolinks 5, which is a rewrite of what’s now called Turbolinks Classic.

Although it ships with Rails, the new version of Turbolinks is a pure JavaScript library that can be used on any HTML page putting it in a <script> tag on the page, or including it into the app’s JavaScript bundle.

When included, Turbolinks will automatically find all links that point to the same domain, and attach a click event listener. Any clicks on those links will be intercepted. Instead of following the links like normal, it request the linked page in the background via JavaScript using XMLHttpRequest. Then, four things happen:

  1. A copy of the current page is stored in Turbolinks’ cache to be used later
  2. It replaces the current page’s <body> with the <body> from the XHR result
  3. It merges the current page’s <head> with the <head> from the XHR result
  4. It changes the URL in the browser using the History API

By merging the <head> tags, the browser doesn’t have to reload and rerender assets like CSS and JavaScript files that are present on both pages. This can speed up your app significantly, especially if you have a lot of assets that are reused on most of your pages.

In a fresh Rails 5 app with some views, you can see Turbolinks in action by navigating around by clicking links and pressing the back button. In your browser’s network tab, you’ll see requests for pages loaded through Turbolinks marked as “xhr”. Also, your assets won’t be reloaded for every request.

Caching and page previews

To speed up subsequent requests to the same page, Turbolinks maintains a cache of recently visited pages. This allows rendering the previous page immediately when pressing the back button, for example.

To speed up the perceived performance of slow pages, Turbolinks will show a preview of the page if it exists in the cache. After clicking the link, the cached version is shown while the fresh version loads.


Turbolinks reimplements some of your browser’s default features, so some things work differently with Turbolinks enabled than without.

turbolinks:load and <script> tags

Since the page isn’t refreshed after every link click, loading JavaScript on page load using window.onload or DOMContentLoaded doesn’t work anymore. To fix that, Turbolinks supplies the turbolinks:load event, which you can use instead:

document.addEventListener("turbolinks:load", function() { 
// ...

Browser loading states

When switching between pages, the browser won’t show the loading indicator in your browser because the request is executed in the background.

In an attempt to fix that, Turbolinks will show a blue bar (which can be styled with CSS) at the top of the page after 500 milliseconds to indicate that the page is loading.

Turbolinks 5 has come a long way since Turbolinks Classic, when Turbolinks seemed to be that thing you skipped when generating a new Rails app. Being a gracefully degrading pure JavaScript plugin that doesn’t depend on Rails now, it works out of the box for most apps, if you keep the caveats in mind.

In return, Turbolinks gives a nice speed boost and prevents your static assets from being reloaded on every page view, which saves some network requests. When generating a new Rails app, try keeping Turbolinks in to see what it does. On existing apps, give Turbolinks a try!

That concludes our overview of Turbolinks. Are you using Turbolinks in any of your apps? We’d love to hear from you! Also, we’re curious to how you liked this and previous articles in AppSignal Academy, or what you’d like to read about next at @AppSignal.

Originally published at blog.appsignal.com on May 23, 2018.




Error tracking and performance insights for Ruby and Elixir without the silly per-host pricing. From Amsterdam with love.

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

An Introduction to Server Side Rendering

Building Custom Data Visualizations With Datadog UI Apps

Advanced React Patterns Note

What are Web 3.0, Blockchain, NFT, and Defi?

JWT Authentication and Refresh Token to API Platform

This in JavaScript

What Is The Short-Circuit Operator in JavaScript? (&&, Logical AND)

Automate Testing of Amplitude Analytics Events with Cypress 🌲

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store


Error tracking and performance insights for Ruby and Elixir without the silly per-host pricing. From Amsterdam with love.

More from Medium

Detecting a rogue Nodejs function in production

How to add tests in CI pipeline using GitHub actions

PDKit: Project as Code

Clean Node.js Architecture —With NestJS and TypeScript