Skip to main content

18 How to Upgrade to Turbolinks 5

Episode 107 · February 25, 2016

Learn how to upgrade your Turbolinks 2.5 or 3.0 app to the newest Turbolinks 5

Turbolinks Javascript Frontend


Transcripts

I thought it would be fun to take a look at the preview of Turbolinks 5.0. Turbolinks is actually going through a lot of different changes lately, and what you're used to as Turbolinks is being deprecated. 2.5 and 3 are the latest version that you're probably familiar with, and these are considered now Turbolinks classics. All of the Turbolinks repositories are now separated out into a turbolinks GitHub organization. They're organized there separate from rails, and the reason for that is because turbolinks really can apply to any application, it doesn't have to be a rails application. The classic version that you're used to is of course intercepting all these links, but it's also kind of been rewritten from the ground up, so version 5 also is adding things like an iOS and Android wrapper, so you'll be able to use turbolinks to embed your websites into mobile apps really easily and maintain those without having to build all kinds of native stuff. That's going to be really cool. Turbolinks classic, you're probably used to version 2.5 that comes with rails. There's a version 3 that you would probably have to upgrade to manually, but that included things like partial replacement, which means that you could say: When I click this link, let's only update this portion of the page. While that was cool and pretty useful, it's also trivial benefits over full page replacement. What we're seeing with turbolinks 5 is that they've gotten rid of this partial replacement, which they just added, mainly for the purpose of simplifying the library. I doesn't need to be that complicated, and the benefits that you get, a partial replacement is very minimal, so they decided to ditch it and keep the library simpler, which I thought was great. turbolinks has migrated into an official repository called turbolinks, there's the rails engine for the turbolinks integration, and that's at turbolinks rails, and then there's the turbolinks source gem, which is the JavaScript for turbolinks as a ruby gem. If you use the rails repository, that will include the source gem which contains the JavaScript which contains the compiled code from the original turbolinks repository. Let's go take a look at a rails application, how you would upgrade this to the latest version just because.

I have a little piece of JavaScript here that I've added to a regular old rails scaffold. I've made a scaffold, brand new rails app. You have a title and a body on pages, and then when you type in the title, the character counter goes up. Let's take a look at the code for that. I've written a pages.coffee file, and anytime the page loads, let's anytime that a user types in the title field, and then let's update the character count, and when the page loads the first time, let's also force trigger the key up event to make sure that this always has text in it. You'll see when there's zero characters that that has been rendered through the JavaScript. When we click back, and we go to new page, you'll see that it didn't run, and that is because we don't have the jQuery turbolink shim in there, and the reason for that, if you're not familiar is that there's a library called jQuery turbolinks that converts the jQuery page load events to work with the turbolinks page load events, because the turbolinks ones are kind of fake, because all these pages that you're seeing us navigate to are actually somewhat fake. They're AJAX requests, and html 5 push state in the url in order to make the loading and rendering the pages much faster, turbolinks basically cheats how browsers work, which is a really really smart and slick way of doing things. Personally, I like it, you do have to understand a lot of how the JavaScript stuff works, but I think it's worthwhile to learn, especially for the speed benefits. Considering how simple turbolinks can be.

Let's actually go ahead and fix this JavaScript bug, which I have done intentionally, we're going to use the jQuery turbolinks shim in order to do that, which I know that a lot of people use, so it's probably in your own application, and then we're going to upgrade to turbolinks 5, and make sure that the jQuery turbolinks shim still works in version 5. Let's jump into our Gemfile in our application and install the jQuery turbolinks gem. Let's just grab the latest version from rubygems and install that. We will run bundle to install it, and then we'll go to our application.js file and add that in. You say: //require jquery-turbolinks in order to do that. You want to do this before turbolinks runs, and this will basically just do everything that you need in order to get your normal jQuery code rerunning on every page. This code will be rerun every time, whereas it wouldn't if it didn't have the jQuery turbolinks. Let's refresh this page, we'll see it of course works the first time, but that always works with turbolinks, and it's the second time that it doesn't normally work, but it does. That jQuery turbolinks gem basically adds this jQuery turbolinks file. There's a really short amount of code that basically says: This load and fetch events, we need to integrate with jQuery and make sure that they rerun along turbolinks. This is great, but we have to see if it's also going to be compatible with the new turbolinks 5.0. There's a beta version of the gem out there, which you can grab, you can install that into your application by overriding your gem turbolinks line, and specifying that it needs to be the beta version of 5.0 or higher, and if you can go back to your terminal, and run bundle to install that, and just to note here, I originally had this line in, but for whatever reason, that wasn't working, and I had to change it to use that format for the version number, and then running bundle update turbolinks installed that correctly for me, so I'm not sure if that was a bundle bug or there was something wrong with the gemfile line here, but either way, this will work and this will also set you up so that you can get the release candidate versions and the final 5.0 versions as well. Once you have the gem installed, you can basically go back to your rails application, restart your server, and then go back to your rails application, and you'll see that turbolinks should automatically be working, if you click on the network tab in Chrome or Firefox and Safari also has inspectors like this, when you click the links, you should see that you're getting XHR requests. These are the turbolinks initiated requests, so everytime you click these links, you can know for sure that turbolinks is the one making those requests, and it is as you can see here. We notice now that our JavaScript didn't run in the second time, which means that things have changed with turbolinks 5, and they have. There's quite a bit of changes under the hood, but one of those is that the events that happened in turbolinks 5 are different names than the ones that have existed in classic version.

They actually wrote this shim, which you can take advantage of, and make the same old events map to the new events of turbolinks 5.0. It's really just three lines of coffeescript that allow you to easier upgrade to turbolinks 5, and that means that we also don't have to make any updates to any of the gems like jQuery turbolinks in order to use those with version 5. This makes for an easy upgrade path. The problem is this turbolinks compatibility.coffee file is not included in the gem, so you're going to need to copy the code for this, and then put it inside your javascripts file. We can do that by saying app/assets/javascripts/turbolinks-compatibility.coffee, paste that in, and then let's go to our application.js and make sure that we //require turbolinks.compatibility. You want to do it after turbolinks because you're referencing the turbolinks object here. On the first line, you're referencing turbolinks, so if you don't do that ahead of time, you'll see an error in your JavaScript console when you reload the page. We can reload our page here, and if we click back a new page again, that means that our JavaScript is working again. That's really all you have to do to upgrade to turbolinks 5, so if you're interested in keeping up with that, maybe on a side project or something. I wouldn't recommend using turbolinks 5 for any production applications just yet unless you want to go work on turbolinks, which would be fantastic, but that is really all you have to do in order to upgrade the turbolinks 5. Update the gem, and then add in this compatibility file, and you should be good to go.

That's really it for upgrading to turbolinks 5 from version 2.5. If you're on version 3, of course I didn't mention that if you do use partial replacements, you're going to want to change that code so that it doesn't do that. The reason for that is because the turbolinks 5 gem doesn't support that, and we'll get marginal benefits from it anyways, so it should simplify and standardize your code a lot better to remove that.

Last but not least is this Android and iOS wrappers, hopefully they will get released soon, they're still not out yet, but I plan on doing an episode shortly after they get released, because that is going to be kind of the killer feature of this, being able to do all of this together. It wasn't the most complicated episode, but at the same time, it's pretty impressive that an upgrade from turbolinks 2.5 to 5.0 is just going to simply be including this compatibility file for the time being, and I'm sure we'll see jQuery.turbolinks get upgraded to use these new events, but until then you don't even have to worry about that, and you should be fine operating with the compatibility file until then.

That's it for this episode, and I will talk to you next week. Peace v

Discussion


Gravatar

Hi Chris, great episode! You can also skip the extra gem(s) and compatibility files by simply changing code. Doing something like:

Old Turbolinks Classic:
$(document).on "ready page:load", ->
# CoffeeScript code

Turbolinks 5:
$(document).on "turbolinks:load", ->
# CoffeeScript code

https://github.com/turbolin...


Gravatar

Thanks for the great video Chris!

I keep getting an error though:

"couldn't find file 'compatibility' with type 'application/javascript'"

I think some things have changed since your video, like the compatibility file name, but other than that, I followed your video exactly.

The error is being raised in my application.html.erb. Also, I'm using turbolinks-source 5.0.0.beta2

Any thoughts?

Thanks,

Nick

Gravatar

The turbolinks/compatibility.coffee file doesn't ship with the gem unfortunately (at least not right now). You'll have to copy it into your Rails app from the original repo. I've got a link to it in the resources section above, but here's the link as well: https://github.com/turbolin... Paste that into your Rails app and just require the file like normal and you should be set.

Gravatar

Wow, thanks for the quick response!

I do have the compatibility file in my app/assets/javascripts directory and I'm requiring it my application.js file after the turbolinks require.

Do you think something has changed from beta1 one to beta2 that's causing the problem?

Gravatar

I don't believe so. It sounds like the normal error you get when trying to require a file that doesn't exist, although you have created it locally it sounds like. Possibly a typo in your filename?

Gravatar

Oh man! In an effort to avoid any spelling errors I copied and pasted the file name from the repo. The only problem is I copied an extra space at the end of the name so the file names didn't match up and I couldn't see it until I highlighted the file name! DOH!

Thanks for your help Chris! You're the man!

Gravatar

Ha, wow that's a subtle one. You'd think that it would automatically strip out spaces at the end of the filename by 2016. ;)


Gravatar

Hey chris, I'd like to build up product associations in the products edit view using modals. ie generating a specs table.

When i submit a form to the create action it re renders and closes the modal. adding data-turbolinks-permanent doesn't seem to solve the problem as the new specs won't show up

This form would be rather long for one page, is it possible to accomplish what I'm trying to do with turbolinks 5 or should I look to do something like breaking the form out into separate pages?

Cheers

Gravatar

It sounds like potentially what you want is the "remote: true" AJAX requests so that you can handle things on your own. Turbolinks won't really do anything here because the form is going to submit a POST and Turbolinks can only really handle GET requests. That's the main reason it's not going to be a good solution for your problem. I think using a JS response to the form submit should give you a lot more flexibility to do what you want there.


Gravatar

Thanks! You helped me a lot!


Gravatar

Hey Chris, I've been having trouble with turbo links. I'm not planning to upgrade my turbolinks and I have the jquery.turbolinks gem installed. The problem is that on first load my subscriptions_new submit button won't fire. It fires once I reload the page and everything works fine then. Any suggestions?


Gravatar

too bad the jquery.turbolinks gem doesn't work with Rails 5. any suggestions from implementing Turbolinks 5 with Rails 5 and Jquery?

Gravatar

Have you found a solution to this? I am having this issue currently.


Gravatar

Never mind. Comment removed.


Gravatar

Having issue with Rails 5 and Turbolinks. I have added the jquery-turbolinks gem and still having issues.

`application.js`

```

//= require jquery

//= require jquery.turbolinks

//= require jquery_ujs

//= require tether

//= require bootstrap-sprockets

//= require bootstrap-datepicker/core

//= require_tree .

//= require turbolinks
```


Login or create an account to join the conversation.