Assets are reloaded between pages with Turbolinks 5 and Rails 5 - ruby-on-rails

In my production environment, I noticed Turbolinks was not caching assets between pages. When I come on the first page of my application, my javascript bundle gets loaded, so as my CSS. When I then get to another page with a link, I can see in the chrome devtools, network tab, that they are reloaded (HTTP code 200).
application.html.erb
<html>
<head>
<title>My title</title>
<meta name="description" content="My description">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="index, follow">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<%= csrf_meta_tags %>
<%= action_cable_meta_tag %>
</head>
<body class="<%= body_user_class %> <%= controller.controller_name %>">
// Stuff
</body>
</html>
application.js
//= require turbolinks
//= require jquery
//= require jquery.slick
//= require jquery-ui/sortable
//= require rails-ujs
//= require_tree ./components
The fingerprint of the assets remains the same between the first and the second page, so I don't think the issue comes from there.
I can understand why my bootstrap asset is reloaded, as it is referenced as a classical resource without using rails. But why are my application's js and css reloaded?

In your application JavaScript bundle, you have the following:
document.addEventListener("turbolinks:before-visit", function(e) {
e.preventDefault(),
window.location = e.data.url
})
This cancels the default Turbolinks behaviour. If you remove this event listener, it should work as expected.

Related

Bootstrap styling breaks when I add own stylesheets

This is what I have on my application.html.erb file.
<head>
<title>Software & Cia.</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolineks-track': 'reload' %>
<%= csrf_meta_tags %>
</head>
If I delete the application stylesheet_link_tag, bootstrap works just fine, but I want to add my own styling to some parts. Sorry for the noobish question, but tried to find a solution and can't get it working.
My application.scss is
#import "bootstrap-sprockets";
#import "boostrap";
My application.js is
//= require jquery
//= require jquery_ujs
//= require bootstrap-sprockets
//= require turbolinks
//= require_tree . here
If you want to use Bootstrap in rails, it's a good way to use the bootstrap gem (same for jquery)
gem 'turbolinks', '~> 5'
gem 'bootstrap', '~> 4.1.1'
gem 'jquery-rails'
This way you keep your application <head> clean:
<head>
<title>Software & Cia.</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
Now your assets/stylesheets folder can be organize like that:
stylesheets
|_ custom_folder
| |_ custom1.scss
| |_ custom2.scss
|
|_ application.scss
|_ another_custom.scss
And you import all these files, bootstrap included, in your application.scss:
#import "bootstrap";
#import "custom_folder/custom1";
#import "custom_folder/custom2";
#import "another_custom";
If you have multiple files inside a custom folder, you can even
create an index.scss where you import all your files and just import
"custom_folder/index" in application.scss
If you override some boostrap variables in a file, import this one before bootstrap

my custom elements don't work in Rails 4.2 with polymer-rails

Using the polymer-rails gem with Rails 4.2 I am able to use the predefined polymer elements such as the paper element set and the iron element set.
However when I make my own elements they are not rendered.
E.g. I created an element with this command
rails g polymer:component testing
and I left it untouched
/app/assets/components/testing/testing.html looks like this:
<dom-module id="testing">
<link rel="stylesheet" href="testing.css" />
<template>
<h2>Testing</h2>
</template>
<script src="testing.js"></script>
</dom-module>
/app/assets/components/testing/testing.js looks like this:
Polymer({
is: "testing"
});
/app/assets/components/application.html.erb has this:
//= require polymer/polymer
//= require paper-styles/paper-styles
//= require iron-icons/iron-icons
//= require paper-tooltip/paper-tooltip
//= require easy-paper-tabs/easy-paper-tabs
//= require testing/testing
the <head> of /app/views/layouts/application.html.erb is this:
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0"/>
<title><%= full_title(yield(:title)) %></title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
<%= javascript_include_tag "https://www.google.com/jsapi", "chartkick" %>
<%= csrf_meta_tags %>
<%= favicon_link_tag %>
<%= html_import_tag 'application', 'data-turbolinks-track' => true %>
</head>
When I put the tag <testing></testing> into a view I expect to see the h2 heading "Testing", but I don't. Instead nothing is rendered there. When I inspect the page I just see the empty tag <testing></testing>.
What am I missing?
I've tried putting the <testing></testing> tag into different views
I've tried replacing <%= html_import_tag 'application', 'data-turbolinks-track' => true %> with <%= html_import_tag 'application' %> in /app/views/layouts/application.html.erb
I've tried putting the custom component into /vendor/assets/components/testing/ instead of /app/assets/components/testing/
For each thing I tried I restarted the server.
I noticed the console logged an error that said
Failed to execute 'registerElement' on 'Document': Registration failed for type 'testing'. The type name is invalid.
so I googled it and found that the web-components spec bizarrely requires all user-created elements to have a hyphen in their name! There's not much documentation about this - it's like secret knowledge.
Putting a hyphen in the name of the element fixes my problem.

AngularJS with Rails asset pipeline

I cannot get Angular to work with Rails asset pipeline. I have:
application.js
//= require angular
angular.module('myApp', [])
.config([function() {
console.log('In config.');
}]);
application.html.erb
<!DOCTYPE html>
<html>
<head>
<%= javascript_include_tag 'application' %>
</head>
<body ng-app="myApp"></body>
</html>
When I load the page I do not see the expected "In config" in the console. Where are no errors prompted, the source is loaded correctly. After refreshing the page two times, on the third load the console message does appear eventually.
If I replace <%= javascript_include_tag 'application' %> with simply <script src="/assets/application.js"></script>, the application does work as expected.
What am I missing here?

gmaps4rails + JQM with Ajax not working

I am building a webapp with rails and JQM. The map shows up fine on my laptop and on my phone. The problem is when I am trying to launch it as a fullscreen app from a saved icon on my smartphone:
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
the map doesn't show up, just a white canvas.
It works when I disable ajax (data-ajax = false) but then the page is opened in my browser and leaves the webapp.
I followed the instructions in:
gmaps4rails on jQueryMobile don't work.
(I couldn't call gmaps4rails(#json, false, false) since gmaps4rails only accepts one parameter...)
Here is some of my code:
application.js:
//= require jquery
//= require jquery_ujs
//= require gmaps4rails/gmaps4rails.base
//= require gmaps4rails/gmaps4rails.googlemaps
//= require_tree .
$('#gmaps').live('pageshow',function(event){
Gmaps.loadMaps();
});
layout:
<%= javascript_include_tag "http://code.jquery.com/mobile/1.3.0/jquery.mobile-1.3.0.min.js" %>
<%= javascript_include_tag "application" %>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?v=3.5&sensor=false&libraries=geometry"></script>
<script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/tags/infobox/1.1.5/src/infobox.js"></script>
<script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerclustererplus/2.0.1/src/markerclusterer.js"></script>
<script type="text/javascript" src="http://google-maps-utility-library-v3.googlecode.com/svn/trunk/richmarker/src/richmarker-compiled.js"></script>
<%= stylesheet_link_tag "https://ajax.aspnetcdn.com/ajax/jquery.mobile/1.3.0/jquery.mobile-1.3.0.min.css", :media => "all" %>
<%= stylesheet_link_tag "application", :media => "all" %>
<meta name="viewport" content="width=device-width, initial-scale=1" user-scalable=no>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
view:
<%= gmaps4rails(#markers_json) %>
<%= yield :scripts %>
Thanks for your help, this is driving me crazy!!

Managing page-specific stylesheets and javascript files with Rails 3 application layout

I'm attempting to keep the application layout in my Rails 3 app for the stylesheets and javascript files I use most frequently (application.js, jquery, style, etc.). However there are plugins I'm using on certain pages and want to include those stylesheets/javascripts properly. For example, I'm looking to use slides only on my homepage. If my application layout is like the one below, what's the best way to include page-specific files?
<!doctype html>
<head>
<title>Title</title>
<link rel="stylesheet" href="http://localhost:3000/stylesheets/style.css" media="screen and (min-width:481px)">
<!--[if IE]>
<link rel="stylesheet" href="http://localhost:3000/stylesheets/style.css" media="all"><![endif]-->
<%= javascript_include_tag :defaults %>
<%= csrf_meta_tag %>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="user-scalable=no,width=device-width">
</head>
<body>
<%= render 'layouts/header' %>
<%= yield %>
<%= render 'layouts/footer' %>
</body>
</html>

Resources