Question

My JS code is Backbone.js based, so I think it is a good idea to separate "classes" with this logic as shown on picture (though I'm not sure where to place templates - in this packages or in global templates folder, and do not mind main.js - it is not related to CommonJS packages) :

enter image description here

Now since there is fairly lot of them - I've decided to use require.js to deal with this bunch of <script src=... tags but got stuck with app.js config file (which is the only one that I include like this -

<script data-main="/static/js/app.js" src="/static/js/libmin/require.js"></script>

What do I mean with stuck - of course I can iterate all this js files in require statement using names like PlayerApp/PlayerAppController.js, or using paths directive (not sure if it will make the code look not that ugly), but it would be cool if I can use something like python's from package import *, and of course there is no such thing in require.js.

The most similar thing is packages directive, but seems like it allows you to import only main.js from each package, so then the question is - what is the most correct way to load other files of concrete package from CommonJS's main.js? I have even found a way to determine current .js file's name and path - like this, and given that I can make up other files names in current package(if I will keep naming them with the same pattern), but still do not know how to import them from main.js

Edit:

There might be an opinion that it is not very clear what exactly am I asking, so let me get this straight: how on Earth do I import a huge amount of javascript files with that project structure in the most nice way?

Was it helpful?

Solution

You are mis-understanding the purpose of a module loader. require.js is not there to make it easy for you to import all of your packages into the current namespace (i. e. the browser). It is there to make it easy to import everything you need to run app.js (based on your data-main attribute). Don't try to import * - instead, just import thingYouNeed.

Configuration

What you will want to do is set up your require.config() call with all the necessary paths for libraries like Backbone that don't support AMD and then update your code to explicitly declare its dependencies:

require.config({
  // Not *needed* - will be derived from data-main otherwise
  baseUrl: '/static/js/app',
  paths: {
    // A map of module names to paths (without the .js)
    backbone: '../libmin/backbone',
    underscore: '../libmin/underscore',
    jquery: '../libmin/jquery.min',
    jqueryui.core: '../libmin/jquery.ui.core'
    // etc.
  }
  shim: {
    // A map of module names to configs
    backbone: {
      deps: ['jquery', 'underscore'],
      exports: 'Backbone'
    },
    underscore: {
      exports: '_'
    },
    jquery: {
      exports: 'jQuery'
    },
    // Since jQuery UI does not export
    // its own name we can just provide
    // a deps array without the object
    'jqueryui.core': ['jquery']
  }
});

Dependencies

You will want to update your code to actually use modules and declare your dependencies:

// PlayerAppModel.js
define(['backbone'], function(Backbone) {
    return Backbone.Model.extend({modelStuff: 'here'});
});

// PlayerAppView.js
define(['backbone'], function(Backbone) {
    return Backbone.View.extend({viewStuff: 'here'});
});

// PlayerAppController.js
define(['./PlayerAppModel', './PlayerAppView'],
function(Model, View) {
    // Do things with model and view here
    // return a Controller function of some kind
    return function Controller() {
      // Handle some route or other
    };
});

Now, when you require(['PlayerApp/PlayerAppController'], function(Controller) {}) requirejs will automatically load jQuery, underscore, and Backbone for you. If you never actually use mustache.js then it will never be loaded (and when you optimize your code using the r.js compiler, the extra code will be ignored there as well).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top