TAMD
Tiny, extensible implementation of the Asynchronous Module Definition (AMD) specification from CommonJS
Install / Use
/learn @jivesoftware/TAMDREADME
tAMD 
Tiny, extensible implementation of the CommonJS Asynchronous Module Definition (AMD)
specification. The core implementation, define.js, comes to 812 bytes
when compressed using Closure Compiler with advanced optimizations
and UglifyJS. Integration points in module definition and loading
allow for any kind of custom behavior to be added.
Why another AMD implementation?
There are a quite a few implementations out there already:
The implementations that I have seen tend to be monolithic, including all the features that you might want in one package. What I wanted was a micro-library.
tAMD is very small and makes few assumptions about your use case. The
core implementation, define.js, includes the features that the AMD
specification says must be included and very little else. All other
features are provided as addon components. Some of those are provided
in this repository to get you started. Because of this tAMD can be
customized to suit just about any requirements while remaining as small
as possible. You are invited to create your own components to suit your
needs. tAMD is intended to be easy to read and easily hackable.
Building
tAMD is made up of several files that provide required and optional functionality. A ready-made combined file that includes all optional functionality is available at dist/tAMD.min.js
It is recommended that you build your own custom file to get a smaller size. There is a grunt task provided for this purpose. To use it you will have to clone this repository and install grunt. You will also need to have Java installed to run Closure Compiler.
In the project directory run grunt compile --components='...' with
a space-separated list of the components that you want to include in
your custom build. The components that are available are:
| component | description
| ------------------ | -------------------------------------------------------
| define | minimal core
| hooks | provides extensibility via lifecycle callbacks
| normalize | automatically resolves relative module names
| plugins | supports plugins with the pluginname!resource syntax
| loader | downloads modules on demand, requires configuration
| debug | reports potential problems, such as missing modules
| jquery | jQuery compatibility with versioning support
| jquery-minimal | jQuery compatibility without versioning support
The functionality provided by each component is described in detail below.
If you want the smallest possible build with no extra features, use this command:
grunt compile --components='define'
A more typical build might look like this:
grunt compile --components='define normalize plugins loader'
Minified builds will be output in dist/tAMD.min.js.
To make minification as effective as possible the source for define.js
defines global variables. These are wrapped in a private scope as part
of the compilation process. You can just grab files for the modules
that you want and combine them with your own system - but if you do so
you will get variable leakage.
The included grunt command has the additional advantages that it will perform aggressive minification using Closure Compiler's advanced optimizations and will make sure that your components are combined in the correct order with the correct dependencies (many of the included components have interdependencies).
Included modules
define.js - tAMD
This is the core of tAMD and is the only required component. It does not implement module loading, resolution of relative paths, multiple module versions, or any of that fancy stuff. Look for these features in the other modules below.
define.js places two functions into the global namespace, define()
and require(). The first, define(), behaves exactly as is specified
in the AMD specification. require() is similar in that it
lets you load dependencies asynchronously; but it does not define
a module. require() has the same API as define(), but it should not
be given a module name argument. For example:
require(['jquery'], function($) {
setInterval(function() {
$('.blink').css('visibility', 'hidden');
}, 500);
setTimeout(function() {
setInterval(function() {
$('.blink').css('visibility', 'visible');
}, 500);
}, 500);
});
There is also a synchronous version of require() available that
matches the behavior of require() in traditional CommonJS modules. To
get the synchronous version grab it as a dependency in a module or in an
async require() callback:
// The outer require() is asynchronous.
require(['require'], function(require) {
var $ = require('jquery'); // This is synchronous!
$('body').append('<p>greetings</p>');
});
If you have a project where all of your JavaScript assets are loaded
together and you want the organizational powers of AMD modules in the
smallest package possible, then define.js by itself may be ideal for
you. Just include define.js before any calls to the define()
function.
hooks.js - tAMD/hooks
The hooks component provides friendly integration points into tAMD. You can register callbacks to be invoked when a module is declared or before a module is published and made available to other modules. Your callbacks can modify properties of a module before it is created, cancel creation of a module, or perform some side-effect like logging or dependency loading.
See Customizing for details.
normalize.js - tAMD/normalize
When this component is included dependencies that are given as relative paths are automatically normalized. Relative paths will probably not work as you expect unless you include this component or one like it.
For example, if you have a module called myFeature/view and another
called myFeature/model, since both modules have the same myFeature/
prefix, you can include one from the other with a relative reference:
define('myFeature/view', ['./model'], function(Model) {/* ... */});
This component includes a module called tAMD/normalize, which exports
a function that takes a module id, which may or may not be a relative
path, and a context and returns the normalized module name.
plugins.js - tAMD/plugins
The plugins component adds support for AMD plugins. These allow an AMD implementation to load resources other than JavaScript, or to load JavaScript resources that are not written as AMD modules.
A module name that is handled by a plugin has the format
pluginname!resource where resource can be any string - the plugin
determines how the resource is looked up. When this component
encounters a dependency name with that format, it requires a regular
module the same name as the plugin and hands of responsibility for
loading the special module.
One use for plugins is to download text resources that should not be
executed. You might use this to download templates. First define
a text plugin:
define('text', ['jquery'], function($) {
return {
load: function(resource, require, done) {
$.get(resource).success(done);
}
};
});
The plugins component looks for the load function exported from the
plugin definition and calls it to load text modules. Here is how this
plugin could be used:
require(['text!/templates/hello.txt'], function(hello) {
alert(hello);
});
Plugins might also be used to load stylesheets, compile CoffeeScript, or anything else that you can dream up.
For more details, see the AMD plugin specification.
Note that this implementation does not currently support the 'dynamic'
property on plugins or a config argument to the plugin load
function.
loader.js - tAMD/loader
This component allows you to specify mappings between module names and URLs. When a module name is referenced as a dependency, if it is not already loaded, then corresponding URLs will automatically download and execute.
Mappings are created using the map() function in the loader module:
require(['tAMD/loader'], function(loader) {
loader.map(
['jquery'],
['https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js']
);
});
The first argument to map() is a list of module ids, and the second is
a list of URLs. If any of the given module ids is referenced as
a dependency then the given URLs will be loaded in order. If two
different dependencies match up with two different URL
