0

On some occasions, requirejs returns an undefined object to my module. I've looked at a number of posts and most of the answer are related to circular dependencies. However I could find none (I have checked several times). I apologize by advance for pasting a quantity of code that I've tried to reduced to the minimum :) Any help would be greatly appreciated!

Here is the module init_app.js that fails:

define([
  'marionette',
], function(
    Marionette
) {
  "use strict";

  var App;
  App = new Marionette.Application();
  App.addRegions({ body: "#main_body" });
  return App;
});

Sometimes the Marionette module is undefined. Here is the part of my config.js that might be relevant:

define([], function() {
  'use strict';
  require.config({
    baseUrl: 'js',
    paths : {
      underscore : 'vendors/underscore/underscore',
      jquery : 'vendors/jquery/dist/jquery',
      backbone : 'vendors/backbone/backbone',
      marionette : 'vendors/marionette/lib/backbone.marionette',
      wreqr : 'vendors/backbone.wreqr/lib/backbone.wreqr',
      eventbinder : 'vendors/backbone.eventbinder/lib/backbone.eventbinder',
      babysitter : 'vendors/backbone.babysitter/lib/backbone.babysitter',
    },
    shim : {
      jquery : {
        exports : 'jQuery'
      },
      underscore : {
        exports : '_'
      },
      backbone : {
        deps : ['jquery', 'underscore'],
        exports : 'Backbone'
      },
      wreqr: {
        deps : ['backbone'],
        exports: 'Backbone.Wreqr'
      },
      eventbinder : {
        deps : ['backbone']
      },
      babysitter : {
        deps: ['backbone']
      },
      marionette : {
        deps: ['backbone', 'wreqr', 'eventbinder', 'babysitter'],
        exports : 'Marionette'
      },
    }
  });
});

The main.js file is

require(['config'], function() {
  require( ['app'], function (App) {
    App.start({});
  });
});

where the app.js file is

define([
  'init_app',
  'router',
], function(
    App,
    Router
  ) {
  "use strict";

  App.on('start', function() {
    new Router();
    Backbone.history.start();
  });
  return App;
});

And the router will define a bunch of things that might depend on init_app.js. I've been especially carefull that none of them defines the app.js, which should be sufficient to guaranty that no circular dependency could cause this bug. Any clue??

Guig
  • 9,891
  • 7
  • 64
  • 126
  • Both `init_app.js` and `app.js`return the same constructor `App`. Can you possibly combine these two modules? – seebiscuit Mar 08 '15 at 11:56
  • I don't think so: my router and its dependencies need to access `App.regions` and `App.vent` so I need `App` to be instantiated first. For that they depend on `init_app`. Is it a problem to return several times the same constructor? – Guig Mar 08 '15 at 16:12
  • Also, the problem seems to come from the loading of `Marionette` rather than `App` – Guig Mar 08 '15 at 16:16
  • I believe returning the same constructor may be your problem. I don't see a problem merging `app.js` and `init_app.js` (we do something similar in our enterprise app). But you could also stick the `start` listener on your `main.js`. – seebiscuit Mar 08 '15 at 16:19
  • No, "returning the same constructor" is not a problem. – Louis Mar 09 '15 at 10:45

2 Answers2

1

Here is how I solved it: I changed the main.js to

require(['config'], function() {
  require( ['init_app'], function () {
      require( ['app'], function () {
        App.start({});
      });
  });
});

and put the App in the global scope in init_app. This works well but doesn't explain the previous failure.

Guig
  • 9,891
  • 7
  • 64
  • 126
1

You should review your shim configuration to remove all those shims that you've put in for modules that actually use define. For instance, jQuery uses define and thus does not need a shim. The same is true of Marionette. I've just installed it with Bower and found this towards the start of the file:

 if (typeof define === 'function' && define.amd) {
    define(['backbone', 'underscore'], function(Backbone, _) {
      return (root.Marionette = root.Mn = factory(root, Backbone, _));
    });
  }
  ...

If you see something like this in a module you use, or a flat out call to define, then you should not use a shim for it.

I've not checked every single module you use. Please review all of them to make sure you do not use shims where not needed. If you use shims incorrectly, you can get undefined values for your modules.

Louis
  • 146,715
  • 28
  • 274
  • 320