Why is Highchart loaded twice in my rails app ? (U

2019-08-15 17:17发布

问题:

I can't make working the basic example of Highcharts.

I got these errors :

Uncaught Highcharts error #16 in app/assets/javascripts/application.js Uncaught TypeError: undefined is not a function in app/assets/javascripts/graphique_repartition_budgetaire

Highcharts says that the error 16 is because :

This error happens the second time Highcharts or Highstock is loaded in the same page, so the Highcharts namespace is already defined. Keep in mind that the Highcharts.Chart constructor and all features of Highcharts are included in Highstock, so if you are running Chart and StockChart in combination, you only need to load the highstock.js file.

But I can't figure out how can Highcharts could be loaded twice in the same page.

I'm using Rails 3.2.21

I put this into my Gemfile :

gem 'jquery-rails'
gem 'highcharts-rails', '~> 3.0.0'

I put this into my app/assets/javascripts/application.js :

//= require jquery
//= require jquery_ujs
//= require_tree .
//= require highcharts

I put this into my app/views/layouts/application.html.haml :

%html
  %head
    %title My title blablabla
    = javascript_include_tag 'application'
    = stylesheet_link_tag    'application', :media => 'screen'
    = stylesheet_link_tag    'application', :media => 'print, projection'
    /[if IE]
      = stylesheet_link_tag    'application', :media => 'screen, projection'
    = csrf_meta_tags
...

This is the code I have in my view (HAML-like) :

.groupe-champs-encadres
  #graphique-repartition-budgetaire

This is the what I put into my stylesheet (SASS-like) :

#graphique-repartition-budgetaire
  width: 100%
  height: 400px

This is the code (frome Highcharts example) that I put into my app/assets/javascripts/graphique_repartition_budgetaire.js

$(function () {
    $('#graphique-repartition-budgetaire').highcharts({
        chart: {
            type: 'bar'
        },
        title: {
            text: 'Fruit Consumption'
        },
        xAxis: {
            categories: ['Apples', 'Bananas', 'Oranges']
        },
        yAxis: {
            title: {
                text: 'Fruit eaten'
            }
        },
        series: [{
            name: 'Jane',
            data: [1, 0, 4]
        }, {
            name: 'John',
            data: [5, 7, 3]
        }]
    });
});

====== EDIT 1 ======

I notice that this error also happen on other pages that don't use any ID : #graphique-repartition-budgetaire". In other words, the error also happen on pages that don't use the javascript Highcharts.

So this excludes a mistake on the view itself where the javascript chart example function is called (though the Highcharts.js is of course called on every page). The problem should lie somewhere else.

====== EDIT 2 ======

I made this simple test to check if jquery is working properly. And it fails. It doesn't display the "TEST" on my page. So there must be a problem with jquery and Rails 3.2. I saw on stackoverflow that some people also got problem making jquery working. But I did't find any working solution for now.

====== EDIT 3 ======

There is something wrong with the recommanded test. It was not working until I save the script into a file app/assets/javascript/display_my_div.js, and changed it to :

$(function() {
  $('#mydiv').show();
});

So JQuery is working like a charm. The problem is definitively linked with Highcharts library.

回答1:

Ok, I found that there is a bug in rails when you do a rake assets:precompile that would lead to include twice the JS code from app/assets and public/assets.

This bug is referenced here since april 2013, but the rails community don't seem to be willing to correct it.

As workaround I just :

  1. run rake assets:clean
  2. add the line //= require highcharts to app/assets/javascripts/application.js
  3. run rake assets:precompile
  4. delete the line //= require highcharts from app/assets/javascripts/application.js

So Highchart library is precompiled in assets pipeline from the public/assets.

Its a bit weird, but it works... in development...

I still have to test it in production to confirm that it continues to work.

=== EDIT 1 ===

In fact, it simpler than that : In developpement mode, Rails auto-compile your JS files, but if they were already precompiled with the rake:assets precompile command and compressed into a file (I dont remember where yet) ; then rails would use both occurence of your JS code. This would of course not happen in production mode as there is (usually) no auto-compile mode activated (for performance consideration).