In an effort to make my libraries more portable I've been reading up on AMD and CommonJS. The one thing I have noticed above all is the way they use a directory structure and aim to have one module per file. From what I can tell their 'namespaces' coincide with the directory tree.
However, my own code uses a global object as a namespace, then among my various files, regardless of the directories, I add classes to this object.
(function (Twifty) {
// Add objects to the Twifty namespace
return Twifty;
}(Twifty || {}));
In the upgrade effort, I'm trying to support AMD and CommonJs. There are many articles out there about how to this, but I can't wrap my head around the AMD define function. Here is how I am transforming the above code:
(function (root, factory) {
// Define the namespace if it doesn't exist
var Twifty = root.Twifty || {};
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD is used - Register as an anonymous module.
define([], factory);
} else if (typeof exports === 'object') {
// CommonJS is used - Twifty is a namespace and doesn't need to be required
factory(Twifty);
} else {
// Neither AMD nor CommonJS used. Use global variables.
if (!document) {
throw 'twifty-map requires a DOM object';
}
root.Twifty = factory(Twifty);
}
}(this, function(Twifty) {
// Add objects to the Twifty namespace
return Twifty;
}));
The problem is with the AMD define
. The factory requires a Twifty
object but since it is not a module I can't add it as a dependency. How should I handle this?
It's not really feasable to remove the namespace as this would break any code that depends on it.
Sorry in advance if this is a trivial question.
In an AMD or CommonJS context, your modules should not leak variables into the global space.
So a strategy has to be used in order to have a common object (the namespace) that the various modules can add to.
You can have a twifty.base
module like this:
(function (root) {
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD
define([], {});
}
else if (typeof module === "object" && module.exports) {
// CommonJS
module.exports = {};
}
else {
root.Twifty = root.Twifty || {};
}
}(this));
All other modules would depend on twifty.base
:
(function (root, factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD
define(['twifty.base'], factory);
}
else if (typeof module === "object" && module.exports) {
// CommonJS
module.exports = factory(require('twifty.base'));
}
else {
root.Twifty = factory(root.Twifty || {});
}
}(this, function(Twifty) {
Twifty.foo = 1;
Twifty.bar = function () {};
return Twifty;
}));
In an environment where modules are not used, the script
elements could load the scripts in any order and twifty.base
would actually not be needed. (Because factory(root.Twifty || {})
.) In an AMD or CommonJS environment, since all modules depend on twifty.base
, and since modules in AMD and CommonJS environments are singletons, then all modules are extending the same JavaScript object.