Rails 4 comes with some exciting features like Turbolinks and Streaming. Turbolinks is one of most exciting feature which Rails 4 provides. It helps us increase the speed of loading Rails applications.
Turbolinks is built using same concept as that of PJAX but unlike PJAX, it does not require custom response from web server. Turbolinks performs an AJAX request to server and replaces the body and title tag from the current web page. In doing so, the page does not have load all assets again, hence you will see the performance increase to your page loads.
There are step that you need to follow in order to keep running your websites smoothly. A word of caution: There may be some cases of Javascript code and some Jquery plugins that stop working once you enable turbolinks in you rails app!
I had to make some changes in order run my Rails app. The instructions below are not the only ones you would require to run your app but depending on your app and the Javascript in it, you may require to make some more changes.
I have included foundation in my example. The code is available on Github.
Javascript Load Order
Its important to put all the Javascripts to be loaded inside the <head> tag. The order of inclusion of jQuery is important – ensure you load jquery.turbolinks before turbolinks and after jquery. Include all your custom js between jquery-turbolinks.js and turbolinks.js in your application.js
// app/assets/javascript/application.js //= require jquery //= require jquery.turbolinks //= require jquery_ujs //= require foundation //= require jwplayer/jwplayer.js //= require asset_videos //= require turbolinks
Event Binding
Bind all events on the document For example, if you want to bind the click event on button having class ‘btn-submit’, you may end up writing code like this and it’s bad because your even may never get bound if the page gets modified!
$('btn-submit').bind('click', function(){ // your custom code })
The event handler needs to bind to element each time DOM is modified but when turbolinks are used, the HTML head is not reloaded andthe page load is actually without full page refresh. So, $(document).ready will not get fired when turbolinks and the above event may not get bound. The correct way to implement the event binding is
$(document).on('click', 'btn-submit', function(){ // your custom code })
CoffeeScript Issues
Be careful while using CoffeeScript, since CoffeeScript enclose all your code in an anonymous function and its possible that the code will get executed more than once! For Example, suppose you write some CoffeeScript in sample.js.coffee
$("form").submit()
While compiling CoffeeScript to Javascript, these code gets wrap around an anonymous function like this
(function(){ $("form").submit() })();
These above problem typically occurs only when jquery.turbolinks.js will be included in you app since it can call your Javascript code multiple times before actually rendering page. I don’t have the solution for this right now but am working on it.
ClientSide Javascript Frameworks
Be careful while using client side javascript frameworks just as backbone.js. Turbolinks and backbone.js are not compatible due to clash between the push state api.
I have found while using the gem zurb-foundation version 4, the select box was not showing the options when page loading through Turbolinks. I had to manually call the foundation events on event “page:load”( the turbolink custom event ).
document.addEventListener("page:load", function(){ Foundation.libs.dropdown.events(); });
I am compiling a list of problems and solutions that we commonly face when using Turbolinks. Feel free to fork my sample application on github and try some stunts. I would be more than happy to help resolve any other issues you face.
Keep me posted!
Your post was very usefull to put my thougths in order about these matter.
I’ve been trying to use Rails 4 with Turbolinks and Bootstrap 3 RC 1, but the turbolink failed with BS’s Dropdown component.
I hope they fixed it when final version of Bootstraps arrives!
thanks i will check
I’ve tried again, and after moving the javascript include line:
true %>
to the head html section, it worked as it should!
@FeraBR – put code inside [ sourcecode ] [ /sourcecode ] block
Thanks for the tip @Gautam
I’ve tried again, and after moving the javascript include line:
to the head html section, it worked as it should!