0
votes

I have a library which internally uses AMD modules (requirejs). I want to return some methods from those modules as a public API. At the moment i'm using a sychronous require call to do this.

eg:

// library
define("a", function(){
    define("b", ['somedep','anotherdep'], function(dep, dep2){
        return { something: "x"};
    });

    return {
        b: require('b').something
    };
});



// then to use it.
require(['a'], function(a){
});

However this gives the error. Error: Module name "b" has not been loaded yet for context: _. Use require([])

I don't want to expose the internal define calls externally (by flattening out all the defines) since i don't want library consumers to be able to use those internal modules.

4
Why you need to define a module inside a module ? You can separate those right ? I think requirejs was not meant to do that wayVigneswaran Marimuthu
The library is quite large and splitting it into modules means it's easier to handle.Chris Whittington
You can do that in a different way. Check my answer :)Vigneswaran Marimuthu

4 Answers

0
votes

You can't nest your module definitions. Try this instead:

define("b", ['somedep','anotherdep'], function(dep, dep2){
    return { something: "x"};
});

define("a", ['b'], function(b){
    return {
        b: b.something
    };
});

// then to use it.
require(['a'], function(a){
});
0
votes
// Defined module "b"
define("b", ['somedep','anotherdep'], function(dep, dep2){
    return { something: "x"};
});

// Defined module "a"
define("a", ["b"], function(b){

    return {
        b: b.something
    };
});



// then to use it.
require(['a'], function(a){
});

You can do something like this

0
votes

I don't want to expose the internal define calls externally (by flattening out all the defines) since i don't want library consumers to be able to use those internal modules.

I don't know of a simple way to declare to RequireJS a module and at the same time prevent the module from being able to be used by any code that can call RequireJS's require. Let's suppose the code you show would work. Then module b would be accessible to any code as soon as module a has been loaded. ("Loaded" here means that the factory function has executed.) So while accessing b would be dependent on loading a first, b would not be hidden.

The reason your code does not work is that the "synchronous" require of RequireJS is pseudo-synchronous... or perhaps a better term is that it is a pseudo-require which does operate synchronously but will bail right away if the module you want is not loaded. Again, "loaded" here means not only that a define call for the module has been executed but that the module's own dependencies are already loaded and that the module's factory function has executed already. In your code, the dependencies of module b have not been loaded and the factory function for b has not executed yet, so your require call fails.

You'd be able to load b with require(['b']) but then you'd have to return a promise of some sort from a.

You could essentially hide what is in module b by using scoping but not making b a module:

define("a", ['somedep', 'anotherdep'], function(dep, dep2){
    var b = (function (foo, bar) {
        return { something: "x" };
    })(dep, dep2);

    return {
        b: b.something
    };
});
-1
votes

We ended up changing the project to use es6 modules, bable and browserify. This makes everything synchronous instead of being async.