Skip to content

Instantly share code, notes, and snippets.

@geraintluff
Last active August 29, 2015 14:10
Show Gist options
  • Save geraintluff/58a0c3aa163b6d19f972 to your computer and use it in GitHub Desktop.
Save geraintluff/58a0c3aa163b6d19f972 to your computer and use it in GitHub Desktop.
AMD define() and require() in 550 bytes

Asynchronous Module Definitions, in 550 bytes

This provides implementations of Asynchronous Module Definition's define() and require() functions. The minified code comes out around 550 bytes.

This enables module definitions, but it doesn't actually fetch any modules that are missing. If you want to automatically fetch modules, see "Extending" below.

The "CommonJS"-style hacks are not supported (e.g. special behaviour for dependencies "module", "require" or "exports").

Usage

// module definition
define('my-module', ['some-dep'], function (someDep) {
    // you can also use require() synchronously
    assert(someDep === require('some-dep'));

    return {/* some API */};
});

// Asynchronous require()
require(['my-module'], function (myModule) {
   ...
});

Extending / hacking about

If you want to plug into this to make a full-featured module loader, then you can hook into a few special private properties:

define._p

This is an array of pending modules, as triples [moduleName, deps, factory]. The first (moduleName) may be null, indicating it's an asynchronous require() callback, not a module definition.

define._d

This should be a function you define. When present, it is called after every define() or asynchronous require() call - this would be a good time to inspect define._p and attempt fetching of missing modules.

(function (global) {
var require = global['require'] = function (nameOrDeps, func) {
if (func) {
for (var i = 0; i < nameOrDeps.length; i++) {
isRequired[nameOrDeps[i]] = 1;
}
return define(0, nameOrDeps, func)
} else {
isRequired[nameOrDeps] = 1;
// For efficiency, don't scan if we already have a result - costs us ~10 bytes, but probably worth it
if (!modules[nameOrDeps]) {
scanForReadyModules();
}
if (nameOrDeps in modules) return modules[nameOrDeps];
throw nameOrDeps;
}
};
var counter = 0;
var define = global['define'] = function (name, deps, factory) {
if (!name || (name + "" === name)) {
// We were given a name (or a falsy value to indicate no module name at all)
if (!factory) {
factory = deps;
deps = [];
}
} else {
factory = deps || name;
// Two arguments -> actual deps in the name, otherwise only one argument
deps = deps ? name : [];
name = define._n || ('_anon' + counter++);
}
pending.push([name, deps, factory]);
scanForReadyModules();
};
var isRequired = {};
var pending = define._p = [];
var modules = {};
function scanForReadyModules() {
var item;
for (var pendingIndex = 0; item = pending[pendingIndex]; pendingIndex++) {
var name = item[0];
if (!name || isRequired[name]) {
var deps = item[1];
var value = item[2];
var args = [];
var depName;
for (var j = 0; j < deps.length; j++) {
args[j] = modules[depName = deps[j]];
// Use item as a flag for whether we're ready to go
item = (depName in modules) && item;
// Mark all our dependencies as required, restarting if necessary
if (!isRequired[depName]) {
pendingIndex = isRequired[depName] = -1;
}
}
if (item) { // Ready to evaluate
pending.splice(pendingIndex, 1);
value = (typeof value === 'function') ? value.apply(global, args) : value;
if (name) {
modules[name] = value;
}
pendingIndex = -1;
}
}
}
// Hook for later, so an automatic loader can hook into this by replacing define.d().
if (define._d) define._d();
};
define.amd = {};
})(this);
(function(m){function f(){for(var a,b=0;a=n[b];b++){var c=a[0];if(!c||g[c]){for(var f=a[1],h=a[2],p=[],k,l=0;l<f.length;l++)p[l]=d[k=f[l]],a=k in d&&a,g[k]||(b=g[k]=-1);a&&(n.splice(b,1),h="function"===typeof h?h.apply(m,p):h,c&&(d[c]=h),b=-1)}}e._d&&e._d()}m.require=function(a,b){if(b){for(var c=0;c<a.length;c++)g[a[c]]=1;return e(0,a,b)}g[a]=1;d[a]||f();if(a in d)return d[a];throw a;};var q=0,e=m.define=function(a,b,c){a&&a+""!==a?(c=b||a,b=b?a:[],a=e._n||"_anon"+q++):c||(c=b,b=[]);n.push([a,b,c]);f()},g={},n=e._p=[],d={};e.amd={}})(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment