Loading jQuery, Underscore and Backbone using RequireJS 2.0.1 and shim

vrde picture vrde · Jun 3, 2012 · Viewed 21k times · Source

I am experimenting a little bit with RequireJS 2.0.1. My goal is to load correctly jQuery, Underscore and Backbone. From the original RequireJS doc I discovered that the author J. Burke added (to this new release) a new config option called shim.

Then I wrote this stuff down here:

index.html

<!DOCTYPE html>
<html>
    <head>
        <title>Testing time</title>
        <script data-main="scripts/main" src="scripts/require.js"></script>
    </head>
    <body>
        <h1>Testing time</h1>
    </body>
</html>

scripts/main.js

requirejs.config({
    shim: {
        'libs/jquery': {
            exports: '$'
        },
        'libs/underscore': {
            exports: '_'
        },
        'libs/backbone': {
            deps: ['libs/underscore', 'libs/jquery'],
            exports: 'Backbone'
        }
    }
});


define(
    ['libs/jquery', 'libs/underscore', 'libs/backbone'],

    function (jQueryLocal, underscoreLocal, backboneLocal) {
        console.log('local', jQueryLocal);
        console.log('local', underscoreLocal);
        console.log('local', backboneLocal);
        console.log('global', $);
        console.log('global', _);
        console.log('global', Backbone);
    }
);

Everything seems to work quite fine, but I have the feeling that I'm missing something, I know that there are AMDed version of jQuery and Underscore but if the setup is so simple I don't understand why I should use them.

So, is this setup right or I'm missing something?

Answer

jrburke picture jrburke · Jun 4, 2012

You only need to use "shim" config if the library does not already call define() to declare a module. jQuery does this already, so you can remove that from the shim config. The above code will work as is, but the exports shim config for jQuery will be ignored since jQuery will call define() before the shim work is done.

The downsides with the shim vs having the script call define() to define a module:

  1. It is less portable/reliable: every developer needs to do the shim config, and keep track of library changes. If the library author does it inline in the library, everyone gets the benefits more efficiently. The code templates at umdjs/umd can help with that code change.

  2. Less optimal code loading: shim config works by loading shim deps before loading the actual library. So it is a bit more sequential loading than parallel. It is faster if all scripts can be loaded in parallel, which is possible when define() is used. If you do a build/optimization for final deployment and combine all the scripts into one script, then this is not really a downside.