Grunt build not exposing the globals I need

amd, gruntjs, javascript, r.js, requirejs

Solution

This is due to `wrap: true` in the r.js config. Here's a simple configuration that isolates the issue:

main.js

define([ 'legacy' ], function(legacy) {
    var greeting = 'hi';
    console.log(greeting, legacy.foo);
});

legacy.js

var globalThing = { foo: 1, bar: 2 };

build.json

{
    "name": "main",
    "optimize": "none",
    "out": "main-built.js",
    "shim": { "legacy": { "exports": "globalThing" } },
    "wrap": true
}

Let's run r.js (`r.js -o build.json`) and consider the result (formatted by me):

(function() {  // this immediately-invoked function expression (IIFE)
               // is here because r.js has "wrap: true" in the config

    var globalThing = { foo: 1, bar: 2 };

    // code generated from the "shim" entry in the config 
    define('legacy', function(global) {
        return function() {
            var ret, fn;
            // since global.globalThing is undefined,
            // that's where it goes wrong
            return ret || global.globalThing;
        };
    }(this));

    define('main', [ 'legacy' ], function(legacy) {
        var greeting = 'hi';
        console.log(greeting, legacy.foo);
    });

})();  // end of the IIFE

As you can see from the code above, `globalThing` isn't global any more. The same happens with the stack and highlight libraries in your project as they use `var` and function declarations to define their globals.

To tackle this issue, we have a couple of options. The first is to consider whether you really need `wrap: true` in the config. If you drop it, the globals will get global again and everything should start working as expected. The second option is to try adding `wrapShim: true` to the config. You can read about nuances of using this option here. If we try it with our sample configuration, we'll get something like this:

(function() {

    (function(root) {
        define('legacy', [], function() {
            return function() {
                var globalThing = { foo: 1, bar: 2 };
                return root.globalThing = globalThing;
            }.apply(root, arguments);
        });
    })(this);

    define('main', [ 'legacy' ], function(legacy) {
        var greeting = 'hi';
        console.log(greeting, legacy.foo);
    });

})();

Looks good to me.

Problem

When I run my project locally with my grunt:server task, the project works as I expect. However, after building which takes all the vendor code and puts it into one file, two of my needed module aren't avialable, and the project doesn't work. Here is my requirejs configuration: ``` requirejs.config baseUrl: './js' shim: 'underscore': exports: '_' 'backbone': deps: ['underscore', 'jquery'] exports: 'Backbone' 'stack': deps: ['d3.global'] exports: 'stack' 'highlight': exports: 'hljs' paths: 'underscore': '../components/underscore/underscore' 'backbone': '../components/backbone/backbone' 'jquery': '../components/jquery/jquery' 'd3': '../components/d3/d3' 'd3.global': '../components/d3.global/d3.global' 'stack': '../components/stack/stack' 'highlight': '../components/highlightjs/highlight.pack' require ['app/vendors'],-> console.log("Backbone", Backbone) console.log("_", _) console.log("$", $) console.log("d3", d3) console.log("stack", stack) console.log("hljs", hljs) ``` app/vendors looks like ``` define [ 'underscore' 'jquery' 'backbone' 'text' 'd3.global' 'stack' 'highlight' ], -> ``` When I run the project locally via grunt, I see all the globals printed out. However, when I build the project, Backbone Underscore and JQuery print out, while stack fails (hljs is also not available, and if I remove stack from app/vendors, it doesn't fix highlight, so its probably not an order thing). the requirejs optimizer is called with the following configuration: ``` requirejs: compile: options: baseUrl: 'js/' appDir: './<%= yeoman.tmp_dist %>/' dir: './<%= yeoman.dist %>/' wrap: true removeCombined: true keepBuildDir: true inlineText: true mainConfigFile: '<%= yeoman.tmp_dist %>/js/main.js' # no minification, is done by the min task optimize: "none" modules: [ { name: 'app/vendors', exclude: [] } { name: 'app/app', exclude: ['app/vendors'] } { name: 'main', exclude: ['app/app', 'app/vendors'] } ``` Could there be something wrong with the stack and highlight files that I need to fix in order to make requirejs optimization and uglify work with them? I installed highlightjs via bower by adding `"highlightjs": "~8.0"` to my bower.json file and running `bower install`. I downloaded stack.js from mbostock's stack project. I'm using v0 at the moment, with minor changes to make it work in this project. The source for all these are in the components directory of my github project. BOUNTY If anyone is willing to clone the repo themselves, and try running the project with `grunt server` and `grunt build` to help me track down the problem, I'd greatly appreciate it. At the moment I have the vendor scripts in the github repo itself, so all you should need is compass and bower to run it.

Original source