DEV Community

loading...

Migrate an existing app to Turbolinks

Giorgos Tsiftsis
・3 min read

A few months ago we decided at Tefter to use Turbolinks with our main Ruby on Rails app, so we can take advantage of its features for better SPA look & feel and faster page loading - at least from the user perspective. Back then we had some Javascript files and we relied heavily on jQuery.

About Tefter

Tefter logo

Before going into more detail about the specifics of the migration, let's talk about Tefter first. It's a tool aiming to optimize your web surfing routine, a combination of personal search-engine, a social bookmarking tool, and a place to archive stuff to read later and write notes. One would interact with Tefter through the Web app, the browser extension, the mobile, and the desktop apps or Slack!

Installation

The main repo has a ton of documentation that explains everything. Also, this post from the Hobeybadger team help us a lot at the beginning of the migration.

In our Gemfile we added:

gem 'turbolinks'

And installed it with Yarn:

yarn add turbolinks

Then in our packs/application.js file we import and start Turbolinks:

import Turbolinks from "turbolinks"
Turbolinks.start()

Migration

The steps we did for migration to work were the following:

  • We changed all document.ready with turbolinks:load events.
// Old
$(document).ready(function() { ...

// New
$(document).on('turbolinks:load', function() { ...
  • And all DOMContentLoaded events with turbolinks:load

  • We moved all logic from window.onload events to turbolinks:load

  • We did the same with window.resize events.

  • We made sure to clear Turbolinks cache before ajax requests

// Clear Turbolinks cache before ajax requests
document.addEventListener('ajax:before [data-remote]', () => {
  Turbolinks.clearCache();
});
  • We disabled Turbolinks for Facebook, Google, Slack, and Github omni-oauth sign up pages.

  • We disabled Turbolinks from other 3rd parties calls like Pocket authorization and Slack installation.

  • We noticed that we had problems with rendering some Javascript components like modals or tooltips (we use for example Micromodal and tippy). For those cases, we explicitly opted out from Turbolinks:

<div class="modal" data-turbolinks="false">

or

<%= link_to '#', class: 'tippy', data: { turbolinks: false } do %>
  • We experienced some rendering issues with views with different layouts. We should investigate these issues further but because there was only a simple case (our Readable view) we decided to opt out Turbolinks from it.

  • We had some hard times dealing with event listeners loaded inside turbolinks:load functions. We ended up using Stimulus and handle them inside connect() functions

  • In one case we wanted to make an ajax call and we discovered that we should add the security token.

$.ajax({
        url: someUrl,
        method: 'POST',
        beforeSend: function(xhr) { 
                     xhr.setRequestHeader('X-CSRF-Token', 
                     $('meta[name="csrf-token"]').attr('content'))
                    },
  • We found some inconsistencies when we use turbolinks:onload and async javascript loading. We switched to defer.

Feelings

We have a small JavaScript codebase but the overall migration and bug fixing took us some time mainly due to our inexperiences with the Turbolinks architecture and its expectations. Overall the sign is positive. If you have an existing codebase be patient, there will be plenty of small bugs. Fortunately, one should get quickly familiar with solving them.

What you should consider next

Discussion (0)