Skip to content

Instantly share code, notes, and snippets.

@millermedeiros
Forked from ryanflorence/universal-module.js
Created September 29, 2011 19:21
Show Gist options
  • Save millermedeiros/1251668 to your computer and use it in GitHub Desktop.
Save millermedeiros/1251668 to your computer and use it in GitHub Desktop.
Universal JavaScript Module, supports AMD (RequireJS), Node.js, and the browser.
(function(def){
def('myModule', ['someDependency', 'somethingElse'], function(someDependency, somethingElse){
//return the module's API
return {};
});
}(
// wrapper to run code everywhere
typeof define === 'function' && define.amd?
//AMD
function(name, deps, factory){
define(deps, factory); //registering as an unnamed module, more flexible and match CommonJS
} :
(typeof require === 'function' && typeof module !== 'undefined' && module.exports ?
//CommonJS
function(deps, factory){
module.exports = factory.apply(this, deps.map(require));
} :
//Browser (regular script tag)
function(name, deps, factory){
var d, i = 0, global = this, old = global[name], mod;
while(d = deps[i]){
deps[i++] = this[d];
}
global[name] = mod = factory.apply(global, deps);
mod.noConflict = function(){
global[name] = old;
return mod;
};
}
)
));
// AMD
require(['myModule'], function (myModule){
// use myModule here
});
// Node.js
var myModule = require('myModule');
// Global
myModule
// if myModule is already defined, `noConflict` gives it back
var myNonConflictingModule = myModule.noConflict();
@millermedeiros
Copy link
Author

I've been using a simplified version of this pattern: https://github.com/millermedeiros/crossroads.js/blob/master/dev/src/wrapper.js - specially since I don't think that noConflict() is that important (unless you use a very common name like $ - which is a very bad idea BTW..) and also because I don't "trust" the automatic dependency conversion for globals..

@unscriptable
Copy link

line 10 should be typeof define === 'undefined' no? Actually, typeof define == 'function' && define.amd is the only way to truly detect AMD. require is not standardized (nor should it be, imho).

I'm with you: "embrace AMD and be happy", but ppl can embrace CommonJS and be happy, too. :)

@millermedeiros
Copy link
Author

line 10 should be typeof define === 'undefined' && typeof require === 'undefined' (AMD have define and CommonJS have require).. in fact the logic should be the opposite check for define first (and use AMD), than check for require and module.exports than fallback to browser..

the code above makes a lot of assumptions like checking for require when it is only using define for AMD, check for exports when it uses module.exports... I was only worried about making it work with RequireJS/Node.js and being concise.. even checking for module.exports we can't be sure that it is really what we expect it to be, define.amd is a "safe" check, will start using it from now on..

I only recommend using a wrapper like this if it is a library that you are going to distribute and have no idea how people may want to use it, I like this simple wrapper way better:

(function(def){
def(['someDependency', 'foo/bar/somethingElse'], function(someDependency, somethingElse){
    //return the module's API
    return {};
});
}(
   typeof define === 'function' && define.amd?
    //AMD
    function(name, deps, factory){
        define(deps, factory);
    } :
    //CommonJS
    function(deps, factory){
        module.exports = factory.apply(this, deps.map(require));
    }
));

who uses globals anyways? :P

@unscriptable
Copy link

I like how your boilerplate is on the bottom and the module definition at the top.

imho even define && define.amd is safe enough. Doesn't hurt to do the additional check though.

@millermedeiros
Copy link
Author

in case someone reaches this gist, I just published a new post explaining why AMD rocks: http://blog.millermedeiros.com/2011/09/amd-is-better-for-the-web-than-commonjs-modules/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment