Requirejs why and when to use shim config

Requirejs why and when to use shim config

i read the requirejs document from here api
requirejs.config({
shim: {
‘backbone’: {
//These script dependencies should be loaded before loading
//backbone.js
deps: [‘underscore’, ‘jquery’],
//Once loaded, use the global ‘Backbone’ as the
//module value.
exports: ‘Backbone’
},
‘underscore’: {
exports: ‘_’
},
‘foo’: {
deps: [‘bar’],
exports: ‘Foo’,
init: function (bar) {
//Using a function allows you to call noConflict for
//libraries that support it, and do other cleanup.
//However, plugins for those libraries may still want
//a global. “this” for the function will be the global
//object. The dependencies will be passed in as
//function arguments. If this function returns a value,
//then that value is used as the module export value
//instead of the object found via the ‘exports’ string.
return this.Foo.noConflict();
}
}
}
});

but i am not getting shim part of it.
why should i use shim and how should i configure, can i get some more clarification
please can any one explain with example why and when should we use shim.
thanks.

Solutions/Answers:

Solution 1:

A primary use of shim is with libraries that don’t support AMD, but you need to manage their dependencies. For example, in the Backbone and Underscore example above: you know that Backbone requires Underscore, so suppose you wrote your code like this:

require(['underscore', 'backbone']
, function( Underscore, Backbone ) {

    // do something with Backbone

}

RequireJS will kick off asynchronous requests for both Underscore and Backbone, but you don’t know which one will come back first so it’s possible that Backbone would try to do something with Underscore before it’s loaded.

NOTE: this underscore/backbone example was written before both those libraries supported AMD. But the principle holds true for any libraries today that don’t support AMD.

The “init” hook lets you do other advanced things, e.g. if a library would normally export two different things into the global namespace but you want to redefine them under a single namespace. Or, maybe you want to do some monkey patching on a methods in the library that you’re loading.

More background:

Solution 2:

As per RequireJS API documentation, shim lets you

Configure the dependencies, exports, and custom initialization for
older, traditional “browser globals” scripts that do not use define()
to declare the dependencies and set a module value.

– Configuring dependencies

Lets say you have 2 javascript modules(moduleA and moduleB) and one of them(moduleA) depends on the other(moduleB). Both of these are necessary for your own module so you specify the dependencies in require() or define()

require(['moduleA','moduleB'],function(A,B ) {
    ...
}

But since require itself follow AMD, you have no idea which one would be fetched early. This is where shim comes to rescue.

require.config({
    shim:{
       moduleA:{
         deps:['moduleB']
        } 
    }

})

This would make sure moduleB is always fetched before moduleA is loaded.

– Configuring exports

Shim export tells RequireJS what member on the global object (the window, assuming you’re in a browser, of course) is the actual module value. Lets say moduleA adds itself to the window as ‘modA'(just like jQuery and underscore does as $ and _ respectively), then we make our exports value ‘modA’.

require.config({
    shim:{
       moduleA:{
         exports:'modA'
        } 
    }

It will give RequireJS a local reference to this module. The global modA will still exist on the page too.

-Custom initialization for older “browser global” scripts

This is probably the most important feature of shim config which allow us to add ‘browser global’, ‘non-AMD’ scripts(that do not follow modular pattern either) as dependencies in our own module.

Lets say moduleB is plain old javascript with just two functions funcA() and funcB().

function funcA(){
    console.log("this is function A")
}
function funcB(){
    console.log("this is function B")
}

Though both of these functions are available in window scope, RequireJS recommends us to use them through their global identifier/handle to avoid confusions. So configuring the shim as

shim: {
    moduleB: {
        deps: ["jquery"],
        exports: "funcB",
        init: function () {
            return {
                funcA: funcA,
                funcB: funcB
            };
        }
    }
}

The return value from init function is used as the module export value instead of the object found via the ‘exports’ string. This will allow us to use funcB in our own module as

require(["moduleA","moduleB"], function(A, B){
    B.funcB()
})

Hope this helped.

Solution 3:

you must add paths in requirejs.config to declare, example :

requirejs.config({
    paths: {
          'underscore' : '.../example/XX.js' /// your file java script
          'jquery' : '.../example/jquery.js' /// your file java script
    }
    shim: {
        'backbone': {
            deps: ['underscore', 'jquery'],
            exports: 'Backbone'
        },
        'underscore': {
            exports: '_'
        },
        'foo': {
            deps: ['bar'],
            exports: 'Foo',
            init: function (bar) {
                return this.Foo.noConflict();
            }
        }
    }
});