Neilos
Neilos

Reputation: 2746

RequireJS - config; paths and shims not working

I have a common.js that defines the config for RequireJS:

(function(requirejs) {
    "use strict";

    requirejs.config({
        baseUrl: "/js",
        paths: {
            "jsRoutes": "http://localhost:8080/app/jsroutes"
        },
        shim: {
            "jsRoutes": {
                exports: "jsRoutes"
            }
        }
    });

    requirejs.onError = function(err) {
        console.log(err);
    };
})(requirejs);

I then have a main.js file that I try to use the jsRoutes path that I created:

require(["./common", "jsRoutes"], function (common, routes) {
    // do something interesting
});

but I do not load the resource at http://localhost:8080/app/jsroutes instead it tries to load http://localhost:8080/js/jsRoutes.js when the main.js is executed. But this resouce doesn't exist and I get a 404.

How do I get the jsRoutes path to work correctly? Also do I need the shim (I'm not 100% sure)?

I can debug into the common.js file, so the paths should be being set, right?

Update 1

I believe that the paths should work as I have them defined shouldn't they?

Excerpt from http://requirejs.org/docs/api.html

There may be times when you do want to reference a script directly and not conform to the "baseUrl + paths" rules for finding it. If a module ID has one of the following characteristics, the ID will not be passed through the "baseUrl + paths" configuration, and just be treated like a regular URL that is relative to the document:

Ends in ".js".
Starts with a "/".
Contains an URL protocol, like "http:" or "https:".

Update 2

I may have misread the docs, I can solve the issue by defining the main.js like so:

require(["./common", "http://localhost:8080/app/jsroutes"], function (common, routes) {
    // do something interesting
});

I was rather hoping not to have to pass round this rather unwieldy URL though.

Update 3

Further investigation of the docs revealed the following snippet:

requirejs.config({
    enforceDefine: true,
    paths: {
        jquery: 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min'
    }
});


//Later
require(['jquery'], function ($) {
    //Do something with $ here
}, function (err) {
    //The errback, error callback
    //The error has a list of modules that failed
    var failedId = err.requireModules && err.requireModules[0];
    if (failedId === 'jquery') {
        //undef is function only on the global requirejs object.
        //Use it to clear internal knowledge of jQuery. Any modules
        //that were dependent on jQuery and in the middle of loading
        //will not be loaded yet, they will wait until a valid jQuery
        //does load.
        requirejs.undef(failedId);

        //Set the path to jQuery to local path
        requirejs.config({
            paths: {
                jquery: 'local/jquery'
            }
        });

        //Try again. Note that the above require callback
        //with the "Do something with $ here" comment will
          //be called if this new attempt to load jQuery succeeds.
        require(['jquery'], function () {});
    } else {
        //Some other error. Maybe show message to the user.
    }
});

It would seem here that the jquery path is working with a full URL

Upvotes: 1

Views: 1689

Answers (3)

Kenny Evitt
Kenny Evitt

Reputation: 9811

I had the same problem but I fixed it by changing my code like your original code:

require(["./common", "jsRoutes"], function (common, routes) {
    // do something interesting
});

to this:

require(["./common"], function (common) {
    require(["jsRoutes"], function (routes) {
        // do something interesting
    });
});

I'm guessing that, in the original code, RequireJS attempts to load the "jsRoutes" dependency before the configuration changes made in "common" are applied. Nesting the require calls effectively ensures that the second dependency is loaded only after the first is evaluated.

Upvotes: 0

Neilos
Neilos

Reputation: 2746

Ok I realised what I was doing wrong. It was simple really.

I had dependencies for ./common and jsRoutes being passed to the same module so jsRoutes was being required before it had been defined by the config.

I moved the dependency from the main.js file to where it was actually needed and things worked as I expected.

Upvotes: 1

Shan Robertson
Shan Robertson

Reputation: 2742

I'm fairly certain your path should be relative to your baseUrl. So giving it the domain & port is screwing it up.

EDIT: My standard require js config... it might help?

require.config({
  baseUrl : "./",
    paths: {

    // Bower Components
    respond:      'assets/bower_components/respond/dest/respond.min',

    // Libraries & Polyfills
    polyfillGCS:  'assets/js/lib/polyfill-getComputedStyle', 
    polyfillRAF:  'assets/js/lib/polyfill-requestAnimationFrame',
    polyfillPro:  'assets/js/lib/polyfill-promise', 
    easing:       'assets/js/lib/easing',
    signalsui:    'assets/js/lib/Signals.ui',
    signalsjs:    'assets/js/lib/Signals',
    domReady:     'assets/js/lib/domReady', // TODO: Still needed?

    // Modules
    app:          'assets/js/es5/app'

    },
    shim: {
    app: {
      deps: ['signalsjs']
    },
    signalsjs: {
      deps: ['easing', 'polyfillGCS', 'polyfillRAF']
    },
    signalsui: {
      deps: ['signalsjs']
    }
    }
});

// Load the app
require(['app']);

Upvotes: 1

Related Questions