Since B.m is provided by a dynamic dependency, B should provide an interface for waiting on it to become available. There are a number of plugins to allow that, e.g. rq (using Q promises), promise (using jquery, Q, RSVP or ES6 promises), promiseme (self-contained?).
Using one of those, B would not return moduleB, but a promise. The nested require call would resolve the promise with complete moduleB. A would require <PLUGIN>!B. E.g. using promise and jquery:
// A.js define(["promise!B"], function(moduleB){ // B is complete now moduleB.m(); }) // B.js define([ "dep1", "dep2", "jquery" ], function( dep1, dep2, $ ) { var dyndeps = dep2.getDynDeps(); var moduleB = {}; var loaded = new $.Deferred(); require(dyndeps, function() { moduleB.m = function() { ... }; loaded.resolve(moduleB); }) return loaded.promise(); });
The only remaining problem with this approach is that the client code (A.js) needs to know to depend on B in a special way. A better solution would be to have B hide its dynamic nature like:
// A.js define(["B"], function(moduleB){ moduleB.m(); }) // B.js define([ "promise!dynamicB" ], function( moduleB ) { return moduleB; }); // still inside B.js define a "private" named module: define("dynamicB", ["dep1", "dep2", "jquery"], function() { var dyndeps = dep2.getDynDeps(); var loaded = new $.Deferred(); var moduleB = {}; require(dyndeps, function() { moduleB.m = function() { ... }; loaded.resolve(moduleB); }) return loaded.promise(); });
Now B can be used just as any other module.