1

I'm trying to use/load UnderscoreJS 1.7.0 with RequireJS 2.1.14-3. At my application startup, UnderscoreJS is well loaded, but it is "undefined". See details below:

main.js

define(function() {
    // Configuration of RequireJS
    requirejs.config({
        enforceDefine : true,

        map : {
            '*': { 
                ...
                'underscore' : 'webjars/underscorejs/1.7.0/underscore'
            },
        },

        // The base URL is just the top-level directory where the files are stored
        baseUrl : './',

        // Kick-start the application by loading these files
        deps : [ 'MyPanel' ],
    });
});

The module using it :

define(['ractive',
    'underscore',
    ...], 
    function(Ractive,
            _,
            ...){
var Foo = Ractive.extend({
    ...

    oninit: function(){
        var anArray = [1, 2, 3]
        _.each(anArray, function(item){
               ...
        })
    }
}

And the result in the browser console : Browser result

The underscoreJS file is loaded by the browser:

Module loaded

This must be a detail, but I managed my Javascript dependencies with mavenand webjars

So why is my _ undefined ?

1 Answer 1

1

If you look at the source of Underscore 1.7.0, you see it registers itself like this:

if (typeof define === 'function' && define.amd) {
    define('underscore', [], function() {
        return _;
    });
}

Note the first argument to define. This hardcodes the name of the module as 'underscore'.

The problem is that you are using a map configuration which is not compatible with this hardcoded name. What you do is tell RequireJS "in all modules ("*"), when the module requires a module with the name 'underscore', then please return instead the module with the name 'webjars/underscorejs/1.7.0/underscore'". So when you require 'underscore':

  1. RequireJS looks for the module named 'webjars/underscorejs/1.7.0/underscore' instead.

  2. It uses the default path for such a module name and finds a file at that location. It loads the file and executes it.

  3. However, the file contains a define calls that defines 'underscore', not 'webjars/underscorejs/1.7.0/underscore'. So RequireJS is not able to honor the request.

Instead of map, you should be using a paths configuration for Underscore. Something like:

paths : {
    'underscore' : 'webjars/underscorejs/1.7.0/underscore'
}

This tells RequireJS something like "you'll find the module named 'underscore' at the location 'webjars/underscorejs/1.7.0/underscore'". When you use this, the name of the module requested and the name of the module defined match.

Sign up to request clarification or add additional context in comments.

5 Comments

This should be fixed in the 1.7.0-1 or newer version of the WebJar. See: github.com/webjars/underscorejs/issues/12
@JamesWard How does the patch associated with that issue you link to have anything to do with map?
Well, it depends on if @rémi-doolaeghe is using the RequireJS feature of WebJars. If so then the RequireJS config is automatically generated from the pom.xml file. If not, then you are right - it doesn't have anything to do with the issue.
@JamesWard I have given a try to your idea, but unfortunately this was not the source of the problem. Thanks anyway
@Louis Your solution did the trick. Thanks for the really clear explanation you provided too. I'll take a look at the subtilities between map and paths in the doc. I always thought there were really few differences, but this should not be the case. Thanks anyway for the time you used for me.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.