RequireJs “map” configuration

map:

For the given module prefix, instead of loading the module with the given ID, substitute a different module ID.
This sort of capability is really important for larger projects which may have two sets of modules that need to use two different versions of ‘foo’, but they still need to cooperate with each other.
This is not possible with the context-backed multiversion support. In addition, the paths config is only for setting up root paths for module IDs, not for mapping one module ID to another one.
map example:

requirejs.config({
    map: {
        'some/newmodule': {
            'foo': 'foo1.2'
        },
        'some/oldmodule': {
            'foo': 'foo1.0'
        }
    }
});

If the modules are laid out on disk like this:
• foo1.0.js
• foo1.2.js
• some/
• newmodule.js
• oldmodule.js
When ‘some/newmodule’ does `require(‘foo’)` it will get the foo1.2.js file, and when ‘some/oldmodule’ does `require(‘foo’)` it will get the foo1.0.js file.
This feature only works well for scripts that are real AMD modules that call define() and register as anonymous modules. Also, only use absolute module IDs for map config. Relative IDs (like ‘../some/thing’) do not work.
There is also support for a “*” map value which means “for all modules loaded, use this map config”. If there is a more specific map config, that one will take precedence over the star config. Example:

requirejs.config({
    map: {
        '*': {
            'foo': 'foo1.2'
        },
        'some/oldmodule': {
            'foo': 'foo1.0'
        }
    }
});

Means that for any module except “some/oldmodule”, when “foo” is wanted, use “foo1.2” instead. For “some/oldmodule” only, use “foo1.0” when it asks for “foo”.
Note: when doing builds with map config, the map config needs to be fed to the optimizer, and the build output must still contain a requirejs config call that sets up the map config. The optimizer does not do ID renaming during the build, because some dependency references in a project could depend on runtime variable state. So the optimizer does not invalidate the need for a map config after the build.

For more info : http://requirejs.org/docs/api.html#config-map

Learning RequireJS

Why requirejs?

Why are we using requirejs? I’ve even asked it of myself. For me, organizing large javascript projects and managing dependencies led to it. There are lots of great posts about how to use requirejs but I wanted to focus on WHY.

Explicit Dependency Specifications :
Open up any significant sized javascript file with 100+ lines of code, even 50, and tell me, within 5 seconds, what dependencies it has. Can’t do it? You can with modules and requirejs.

function View() {
    this.name = ko.observable('bob');
    this.age = ko.observable(20);
    ...
}
var view = new View();
ko.applyBindings(view, $('viewPlaceHolder')[0]);    

versus

require(['jquery', 'knockout'], function($, ko) {
    // who knows whats in here, but I do know what it needs
});

How often do you use this information as a developer? Think about the value in not spending 5 minutes everytime you need to know, or more likely, the value in not creating a bug because you didn’t take the time to find them all or you missed one.

Explicit Export Specifications :

Along with explicit dependencies, modules have an explicit mechanism to define what they export. We can quickly read a module and know what it provides by looking at the return statement, instead of wondering what globals to access. define makes explicit that it is providing an interface to consumers.

define('math', ['dependencyA', 'dependencyB'], function(dependencyA, dependencyB) {
    // horrible things to local scope
    return {
            min: min,
            max: max,
            average: average
    };
});

Avoid Script Tag Soup :

<script src="scripts/utils.js">
<script src="scripts/numbers.js">
<script src="scripts/common.js">
<script src="scripts/formatting.js">
<script src="scripts/thing.js">
<script src="scripts/other.js">
<script src="scripts/site.js">

More info : http://devblog.wesmcclure.com/posts/why-requirejs

Using RequireJS :

Application Structure :

├── app.js
├── index.html
├── lib
│ ├── modules
│ │ └── template.js
│ ├── require.js
│ └── underscore.js

The data-main Attribute

Once you downloaded RequireJS, the first thing to do after you put its script in your solution is to understand how RequireJS starts working. Once RequireJS is loaded, it search for a script with data-main attribute (it should be the same script with the src attribute set to load RequireJS). The data-main should be set to the base Url for all the scripts. From the base Url, RequireJS will start loading all the relevant modules. Here is an example of a script tag with the data-main attribute:

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

Configuring RequireJS

Another way to define the base Url is using the config function.

Now, let’s take a look at app.js.

require.config({
    //By default load any module IDs from scripts/app
    baseUrl: 'scripts/app',
    //except, if the module ID starts with "lib"
     paths: {
        lib: '../lib',
        jquery: "jquery-1.11.0.min"
    }, 
    // load backbone as a shim
    shim: {
        'backbone': {
            //The underscore script dependency should be loaded before loading backbone.js
            deps: ['underscore'],
            // use the global 'Backbone' as the module name.
            exports: 'Backbone'
        }
    }
});
  • The config Function :
  • If you want to change the default RequireJS configuration values with your own configurations, you can do that using the requirejs.config function. The config function receives an options object that can include a lot of configurations options. Here are some of the configurations that you can use:
    baseUrl – the root path to start the loading of modules.
    paths – path mapping for modules that don’t exists in under the baseUrl
    shim – configuration for dependencies, exports and initialization function to wrap scripts/modules that don’t use the RequireJS define function. For example, if underscore library doesn’t use the RequireJS define function and you still want to use it with RequireJS, you will have to define it as a shim in the config function.

    // Sets the configuration for your third party scripts that are not AMD compatible( that do not use define() to declare the dependencies and set a module value)

      shim: {
    
          "backbone": {
              deps: ["underscore", "jquery"],
              exports: "Backbone"  //attaches "Backbone" to the window object
          }
    
      } // end Shim Configuration
    

    The Shim configuration can also be used to make sure that that certain scripts executed in a particular order.
    http://requirejs.org/docs/api.html#config-shim
    deps – array of dependencies to load.

    Defining Modules Using RequireJS :
    Modules are just well-scoped objects that expose an API and encapsulate their internals. In order to define a module, RequireJS exposes the define function. There should be only one call for define in each JavaScript file by convention. The define function receives an array of dependencies and a function which is going to hold all the module definitions. By conventions the module definition function receives as parameters all the previous dependencies and in the order they were supplied in the array. For example, here is a simple module definition:

    define(["logger"], function(logger) {        
            return {
                 firstName: “John",
                 lastName: “Black“,
                 sayHello: function () {
                    logger.log(‘hello’);
                 }
            }
        }
    );
    

    Using The require Function :

    Another useful function in RequireJS is the require function. The require function is used to load dependencies without the creation of a module. For example, here is a usage of the require function which defines a function that require jQuery to work:

    require(['jquery'], function ($) {
        //jQuery was loaded and can be used now
    });
    

    Dynamically-loaded Dependencies :

    define(function ( require ) {
        var isReady = false, foobar;
     
        // note the inline require within our module definition
        require(["foo", "bar"], function ( foo, bar ) {
            isReady = true;
            foobar = foo() + bar();
        });
     
        // we can still return a module
        return {
            isReady: isReady,
            foobar: foobar
        };
    });
    

    you can use a synchronous require() as long as the module was already registered for that context:

    define(['require', 'lorem/ipsum'], function(require){
        // since 'lorem/ipsum' is on the dependency list it will be registered
        // before calling the definition function, so the synchronous require will
        // also work
    	var ipsum = require('lorem/ipsum')
        	console.log(ipsum.doSth());
    });
    

    But this would fail if the module dolor/amet wasn’t registered yet:

    define(['require'], function(require){
        	var ipsum = require('lorem/ipsum')
        	console.log(ipsum.doSth());
    });
    

    Some Tricks for Troubleshooting :

    You can use these API calls in your code if you need to, but I’ve actually found them quite useful when on the console in Chrome:
    require.defined(moduleId) – returns true if your moduleId has been defined and is ready for use.
    require.specified(moduleId) – returns true if your moduleId has been listed as a dependency by another defined module. Note that just because this returns true doesn’t mean your moduleId is ready to use (don’t you just love asynchrony?).
    Get module Url
    If you ever need to find the path to a given module, just use the following…

    var path = require.toUrl("./style.css");
    

    requirejs.s.contexts._.config – I learned about this from Vernon Kesner. This is technically a “back door/undocumented” call – so it could change or disappear without warning. However it returns a very useful object full of configuration info, see below:

    require

    This is the result of calling requirejs.s.contexts._.config inside a sample gif-generation app I used to demo Web Workers at Devlink. You can see all the relevant configuration data: the base URL, the paths we’ve mapped, the shim configuration, etc.
    Two other key items to know about when it comes to troubleshooting RequireJS are ‘errbacks’ and the requirejs.onError method.

    RequireJS “errbacks” :

    When you make a require call, you can include a third argument – a callback that receives an error argument, allowing you to react to the error, instead of ultimately generating an uncaught exception. The method signature, when using “errbacks” looks like this:

    require(
        [ "backbone" ], 
        function ( Backbone ) {
            return Backbone.View.extend({ /* your magic here */ });
        }, 
        function (err) {
            /* 
                err has err.requireType (timeout, nodefine, scripterror)
                and err.requireModules (an array of module Ids/paths)
    
                Inside here you could requirejs.undef('backbone') to clear
                the module from require locally - and you could even redefine
                it here or fetch it from a different location (though the
                fallback approach earlier takes care of this use-case more succinctly)
            */
        }
    );
    

    requirejs.onError :

    RequireJS has a global onError handler that will catch any errors not already handled by “errbacks”. To use it, simply set it like this:

    requirejs.onError = function (err) {
        /* 
            err has the same info as the errback callback:
            err.requireType & err.requireModules
        */
        console.log(err.requireType);
        // Be sure to rethrow if you don't want to
        // blindly swallow exceptions here!!!
    };
    

    http://backbonetutorials.com/organizing-backbone-using-modules/
    http://tech.pro/tutorial/1300/deep-dive-into-requirejs
    http://tech.pro/blog/1561/five-helpful-tips-when-using-requirejs