Search code examples
ruby-on-railsturbolinks

Ruby on Rails CSS/JS error with Turbolinks


I'm building a web app on ROR5 and the layout/design is all done, with the CSS/JS files finalized. But when I open the app, click on one link, and navigate through the website, the CSS fails to load. More specifically, the CSS is all messed up. For example, say I go from 'Home' -> 'Page A', then if I backspace to 'Home' again (or click the logo to navigate to 'Home'), the 'Home' page will be messed up. Only when I refresh the page, I would get the correct display.

At first I thought it was a cache problem, but soon discovered that this line is causing the issue:

<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> 

When I delete this line, the display issue is no longer present. However, all JS effects/JS-based plugins would not work. I have a text editor, a few jQuery animations and tab navigations, which all don't work when I delete that line. + of course, instead of just deleting the line, I also tried to simply disable turbolinks by doing: <%= javascript_include_tag 'application' %> and removing turbolinks from my Gemfile. This also didn't work.

My Gemfile includes: gem 'turbolinks', '~> 5' gem 'coffee-rails', '~> 4.2' gem 'jquery-rails'

And the remaining GEMs are all standard gems for my frontend side (bootstrap, SASS, font awesome etc).

My application.js looks like this:

//= require rails-ujs
//= require jquery
//= require jquery_ujs
//= require tinymce
//= require turbolinks
//= require bootstrap-sprockets
//= require_tree .

And for reference, my application.html.erb contains a like the following:

<head>
    <title>..</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag 'application', media: 'all' %>
    <%= stylesheet_link_tag params[:controller] %>

    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> 
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Adobe Typekit Scripts -->
    <script src="https://use.typekit.net/ovy4zfg.js"></script>
    <script>try{Typekit.load({ async: true });}catch(e){}</script>
</head>

What could be the problem? Thanks.


Solution

  • I think the issue here is that you're loading in controller-specific stylesheets (<%= stylesheet_link_tag params[:controller] %>). Turbolinks will append new stylesheets, but will not remove those that are absent in subsequent page loads. So here is the flow:

    1. User visits Home
    2. Stylesheet for Home's controller loaded
    3. User visits Page A
    4. Stylesheet for Page A's controller loaded after the Home CSS
    5. Home CSS and Page A CSS will remain in the head

    If possible, include all your CSS in the application.css manifest file. If you have some controller-specific styles, try adding a class to the body, e.g.:

    <body class="<%= controller_name %>">
    

    Then you can scope your styles, e.g. for a pages_controller:

    body.pages {
      …
    }
    

    Alternatively you could add data-turbolinks-track="reload" to your CSS link tag:

    <%= stylesheet_link_tag params[:controller], 'data-turbolinks-track': 'reload' %>
    

    However, this will mean that you will only get the benefits of Turbolinks when navigating between pages that use the same controller. When navigating between pages that use a different controller, you will get a full page load. This is because Turbolinks will track the presence or absence of the CSS and reload if it has changed.

    One last thing: it is generally a good idea to add 'data-turbolinks-track': 'reload' to your application.css so that if you release a new version of your CSS, the users on the site will be up-to-date when the change goes live.

    Hope that helps