Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails asset pipeline: JavaScript being executed twice

My JavaScript is being executed twice. When I run the Chrome debugger, I noticed that the individual JavaScript file will execute the code the first time, then after that, the application.js file will execute the code again.

I believe this is happening because I recently turned precompile off because I was having issues with Heroku. After this I ran rake assets:precompile.

like image 230
user2158382 Avatar asked Jul 08 '14 06:07

user2158382


People also ask

What is require_ tree in Rails?

The require_tree directive tells Sprockets to recursively include all JavaScript files in the specified directory into the output. These paths must be specified relative to the manifest file.

What is assets precompile in Rails?

The Rails asset pipeline provides an assets:precompile rake task to allow assets to be compiled and cached up front rather than compiled every time the app boots. There are two ways you can use the asset pipeline on Heroku. Compiling assets locally. Compiling assets during slug compilation.

What is assets precompile?

Manifests and directives. rails assets:precompile is the task that does the compilation (concatenation, minification, and preprocessing). When the task is run, Rails first looks at the files in the config.assets.precompile array. By default, this array includes application.js and application.css .

What are assets in Rails?

Generally asset is anything that browser loads after it gets the HTML page. Meaning javascript, css and any images. But as you pointed out there are two different image types in a rails project.


1 Answers

Turbolinks

You probably have an issue with Turbolinks (considering you've included it in your asset pipeline); although this might not be the problem.

Turbolinks is meant to speed up your page load times by loading the <body> tag of your new pages with ajax, keeping the <head> tag intact. This is meant to let your application load just the HTML it needs, but messes up the JS on your page.

If you're having your JS fired twice, it could be a sign that Turbolinks is interfering with your JS. Because you haven't included any examples from the logs, I won't be able to give you any specific information, but you should be able to test this by removing the turbolinks include from both your layout and your application manifest JS file:

#app/views/layouts/application.html.erb
= javascript_include_tag "application", "data-turbolinks-track" => false

#app/assets/javascripts/application.js
//= require turbolinks -> remove this line

If you do this, restart your server & reload the page in question. If it still comes back with the erroneous functionality, it means Turbolinks is not the problem (and you should reset all the things you changed)

--

Events

The other problem you might have is how you're calling / triggering your events. This could be down to a number of reasons, but you should definitely look at how you're calling your JS:

#app/assets/javascripts/application.js
$(document).on("click", ".element", function(){
    //your stuff here
});

We always delegate from the document element of the DOM now. Whilst this might cause some resource issues, we've found it makes Rails apps much more robust with the Asset Pipeline, as it allows you to truly identify elements on the page.

If you're trying to trigger an event from a single object on your DOM, you may find that JS will "capture" the event twice (for whatever reason), leading to your issue. Try delegating your events which are being called twice

--

Functions

Finally, your functions could be the issue.

If you have any anonymous functions, or functions for specific events, you will need to ensure they are able to be called correct. You should do this by using page events in JS & Turbolinks:

#app/assets/javascripts/application.js
var your_function = function() {
    //stuff here
};

$(document).on("page:load ready", your_function);
like image 197
Richard Peck Avatar answered Sep 19 '22 12:09

Richard Peck