Javascript includes not loading for later in the p

2019-04-05 04:21发布

We have a Rails application where we are including our application dependencies in the html head within application.js:

//= require jquery
//= require analytics
// other stuff...

Then on individual pages we have a script tag at the bottom of the page for analytics:

<script>
  analytics.track('on that awesome page');
</script>

This normally works fine, but very occasionally we see the error analytics is not defined, most recently on Chrome 43. Because everything should be loaded synchronously, this seems like it ought to work out of the box, but I changed the script to:

<script>
  $(document).ready(function () {
    analytics.track('on that awesome page');
  });
</script>

And now instead every once in a while we see $ is not defined instead. We don't see any other errors from the same IP, otherwise I would suspect something went wrong in application.js. Any other ideas why it might break? You can see an example page here.

The full application.js:

// Polyfills
//= require es5-shim/es5-shim
//= require es5-shim/es5-sham
//= require polyfills
//
// Third party plugins
//= require isMobile/isMobile
//= require jquery
//
//= require jquery.ui.autocomplete
//= require jquery.ui.dialog
//= require jquery.ui.draggable
//= require jquery.ui.droppable
//= require jquery.ui.effect-fade
//= require jquery.ui.effect-slide
//= require jquery.ui.resizable
//= require jquery.ui.tooltip
//
//= require jquery_ujs
//= require underscore
//= require backbone
//= require backbone-sortable-collection
//= require bootstrap
//= require load-image
//= require react
//= require react_ujs
//= require classnames
//= require routie
//= require mathjs
//= require moment
//= require stink-bomb
//= require analytics
//
// Our code
//= require_self
//= require extensions
//= require extend
//= require models
//= require collections
//= require constants
//= require templates
//= require mixins
//= require helpers
//= require singletons
//= require actions
//
//= require object
//= require components
//= require form_filler
//= require campaigns
//= require form_requests
//= require group_wizard
//= require step_adder

Chalk = {};
underscore = _;

_.templateSettings = {
  evaluate:    /\{\{(.+?)\}\}/g,
  interpolate: /\{\{=(.+?)\}\}/g,
  escape:      /\{\{-(.+?)\}\}/g
};

moment.locale('en', {
  calendar: {
    lastDay: '[Yesterday at] LT',
    sameDay: '[Today at] LT',
    nextDay: '[Tomorrow at] LT',
    lastWeek: 'dddd [at] LT',
    nextWeek: '[Next] dddd [at] LT',
    sameElse: 'L LT'
  }
});

Update:

We're still seeing this on production occasionally. We've also seen it in a case where we load a script before application.js and then reference it within:

javascript_include_tag 'mathjs'
javascript_include_tag 'application'

Every so often we see a math is not defined error. I'm wondering if an error happens during the loading of mathjs or other scripts preventing it from being loaded, but the fact that it happens on so many different libraries, and so infrequently, makes it seem less likely. We did put in some debug checks to see whether our application.js is fully loaded and it often doesn't seem to be, even if accessing something like Jquery later in the page.

One motivation in this was to avoid old browser notifications about scripts running too long, but we may just give up and pull it all into application.js to avoid the errors.

7条回答
放我归山
2楼-- · 2019-04-05 04:47

This can happen if you don't wait for the script to load that defines analytics or if you do not define the order in which the javascript files are loaded. Make sure that the script that defines analytics is always loaded before you try to call its method track. Depending on your setup the scripts could load in random order, leading to this unpredictable behavior.

You tried to make sure everything was loaded, but the listener $(document).ready(function () {}); just makes sure that the DOM is ready, not that analytics is available. And here you have the same problem. $ is just jQuery so $ is not defined means jQuery hasn't been loaded yet. So probably your script came before jQuery was loaded and tried to call what wasn't defined yet.

查看更多
登录 后发表回答