Require.JS shim config global scope?

13,051

Backbone and Underscore both modify the global scope, so if the browser has run their code, then the globals will exist.

This will happen if loading as a shim in RequireJS, or as if you included a script tag with their src directly.

Once the globals exist, they exist (unless explicitly deleted I guess).

This jsfiddle is a simple example of using shims, and seeing that the values (for certain libraries) are set as globals.

The aim of the example is to show that the value of the globals is only guaranteed inside a require() call. (if using an AMD loader, and not simply importing the libraries in a script tag). And that the values of the globals will exist at some indeterminate time in the future.

Source code

require.config({
    shim: {
        underscore: {
            exports: '_'
        },
        backbone: {
            deps: ["underscore", "jquery"],
            exports: "Backbone"
        }
    },
    paths: {
        jquery: "http://code.jquery.com/jquery-1.9.1",
        backbone: "http://backbonejs.org/backbone",
        underscore: "http://underscorejs.org/underscore"
    }
});

function appendVersions(msg, $, _, Backbone) {
    var pre = document.getElementById("content");
    var s = "<h2>" + msg + "</h2>";
    s += "jquery=";
    try { s += $.fn.jquery; } catch (e) { s += e.msg; }
    s += "<br>";
    s += "_=";
    try { s += _.VERSION; } catch (e) {  s += e.msg; }
    s += "<br>";
    s += "Backbone=";
    try { s += Backbone.VERSION; } catch (e) {  s += e.msg; }
    pre.innerHTML += s;
}

appendVersions("Before require (will be undefined)", window["$"], window["_"], window["Backbone"]);

require(["jquery", "underscore", "backbone"], function ($, _, Backbone) {
    appendVersions("Inside Require (should *always* be ok, unless the scripts aren't there)", $, _, Backbone);
});

appendVersions("After require (Probably be undefined, as the require probably won't have loaded the scripts yet)", window["$"], window["_"], window["Backbone"]);

setTimeout(function () {
    appendVersions("After Timeout (should be ok, but depends on how quickly the scripts load. Try changing the timeout duration)", window["$"], window["_"], window["Backbone"]);
}, 2000);

Sample output

enter image description here

Share:
13,051
nimgrg
Author by

nimgrg

Updated on August 17, 2022

Comments

  • nimgrg
    nimgrg almost 2 years

    I have following setup for requireJS.

    requirejs.config({
         paths: {
                'resources' : '/Scripts/resources'
         },
         shim: {
                 'resources': {
                               exports: 'LocalizedStrings'
               }
         }
    });
    

    And my resources.JS look like following:

    LocalizedStrings = {
                        title: "Demo",
                        save: "Save"
    }
    

    Now when I load resources as a dependency in main.JS file I can access LocalizedStrings and it works.

    //main.js
    define(function(require){
        var LocalizedStrings = require('resources');
        console.log(LocalizedStrings); //works as expected
    });
    

    However on other modules I don't really need to load the resources as dependency to access 'LocalizedStrings'.

    //othermodule.js
    define(function(require){
        console.log(LocalizedStrings); //works as expected even though resources dependency is not loaded
    });
    

    What I don't understand here is if I load a JS file using shim and load it once, does it become globally available and I don't have to load the same dependency again in other modules.

    • Paul Grime
      Paul Grime about 11 years
      A module loaded via AMD (such as RequireJS) does not normally become global. But you are not using a 'real' module in resources.js. The code you have in resources.js mutates the global scope, so in your case you are mutating the global scope.
    • nimgrg
      nimgrg about 11 years
      Thanks for answering the question. I don't really want the resources.js in module. I was just trying to understand how the shim configurations worked. Now let's say, if I shim Backbone and Underscore in requireJS and load them as dependency in main.js once, does requireJS make Backbone and Underscore to be available globally as well without the need for me to load them in other modules.
    • Paul Grime
      Paul Grime about 11 years
      Backbone and Underscore both modify the global scope, so if the browser has run their code, then the globals will exist. This will happen if loading as a shim in RequireJS, or as if you included a script tag with their src directly. Once the globals exist, they exist (unless explicitly deleted I guess).
    • Paul Grime
      Paul Grime about 11 years
      I'll tidy it up as an answer.