Sparkplug.js is a tiny initializer for AMD modules, primarily
for use in web browsers.
It can be used as an alternative to AMD loaders like requirejs and curl.jsm, giving you namespaces and AMD module structure
with a Node-like require()
style dependency management, but without the overhead of a full AMD loader.
After compilation with Google Closure and gzip'ing its size is only 597 bytes.
Use sparkplug.js if...
- you want a
require()
function that works just like in node.js - you want AMD modules without the overhead of real AMD loaders
sparkplug.js...
- will initialize all AMD modules that you include via <script> tags
- allows more than one AMD module per <script> (so you can compress them into a single file)
- provides you with a
require()
function to obtain references to module exports
Name | Compiled Size | Compiled and GZip'd |
---|---|---|
sparkplug.js | 1041 bytes | 597 bytes |
requirejs 2.1.4 | 14629 bytes | 6029 bytes |
curl 0.7.3 | 7967 bytes | 3921 bytes |
You have to
- Load sparkplug.js with a <script> tag before any AMD modules.
- Load as many AMD modules as you like using <script>
- Then execute your JavaScript which can use
require()
to obtain references
For optimal performance, you can also compile sparkplug.js and the AMD modules into a single file, just make sure that sparkplug.js is on top.
For example, you can load AMD modules like that:
<script src="sparkplug.js"></script>
<script src="minified.js"></script>
<script src="someotherlib.js"></script>
<script>
var $ = require("minified");
// do something
</script>
You could also define your main code as AMD module and start it with a simple require.
<script src="sparkplug.js"></script>
<script src="minified.js"></script>
<script src="someotherlib.js"></script>
<script>
define("main", function(require) {
var $ = require("minified");
// do something
});
require("main"); // start the main module
</script>
Of course, your application code can and usually should be put into a separate script file.
As sparkplug.js does not load any files itself, all the usual tips for improving load time apply. Ideally you compile all your files into a single file as this will reduce the number of HTTP requests and improve the GZip compression rate.
To prevent the browser from blocking while it processes JavaScript you should either work with the defer
and
async
attributes of the <script>
element, or use the old-fashioned trick of putting all your JavaScript
at the end of the page.
Assuming you have put all your JavaScript, including sparkplug.js and all AMD modules, into a single file, I would recommend to load it like this:
<script src="all.js" defer async></script>
The defer
and async
attributes will prevent the browser from blocking. This works in practically all browsers today,
even in older Internet Explorers.
If you can not or do not want to put all your files into a single file, you should use only the defer
attribute. async
is not possible then, because it does not guarantee the order in which the files are initialized and sparkplug.js must always be invoked
before the AMD modules.
Sparkplug.js has some limitations:
- All AMD modules should define an id, because sparkplug.js does not know file names. To include anonymous modules without id, see the Troublemakers section below.
- sparkplug.js will not load files given to
require()
, only modules that calleddefine()
with their id - sparkplug.js does not load/initialize asynchronously.
Sparkplug.js is best suited for smaller projects that benefit from having only one or two files. Large JavaScript applications, especially those with an overall size over 50kb, may be better off using one of the more sophisticated loaders such as curl.js or require.js.
sparkplug.js provides three global functions:
-
define()
implements the full API described in the AMD wiki.define()
will also provide the symbolsrequire
,exports
andmodule
to AMD modules, if required by their dependencies.define.amd
is defined with the properties shown below. -
require()
implements the CommonJS Modules/1.1.1 syntax as well as the extensions required by AMD.In other words, both syntax variants
require(string)
andrequire(array, callback)
will work, both locally and globally.require(string)
is not required by AMD, but as long as you use sparkplug.js there are no disadvantages by using this simple variant. As sparkplug.js does not load asynchronously, callbacks are not really needed. If you do not plan to migrate your code to a asynchronous loader, usingrequire(string)
is recommended.You can also call
require(integer)
with a numeric argument to retrieve an anonymous module. -
require.toUrl()
is an AMD extension that usually is not very useful when you use sparkplug.js, because sparkplug does not handle URLs. Still,require.toUrl()
will resolve paths relative to the module's path.
The AMD extension define.amd
has the following, proprietary extensions in sparkplug.js:
-
define.amd.anonIds
can be used to assign ids to anonymous modules. You only have to put one desired ids per module in the order of definition. See Troublemakers section for examples. -
define.amd.ids
is an array containing the ids of all defined modules in the order of their definition. Anonymous modules will show up as 0-based, increasing numbers, even if you have defined an id for them usinganonIds
. The first anonymous module will be 0, the second 1...
Many AMD modules do not declare their id, but instead depend on the AMD loader to determine their id from their file name. sparkplug.js can not do this, as it does not know the file names, and also because it allows putting several modules into a single script.
The recommended way to handle such modules is to set define.amd.anonIds
. It contains an array of ids for anonymous modules
in the order of their declaration. It can be set either before or after their definition, but always before the first time they are
required (either explicitly or as dependency).
The following example loads three AMD modules. lodash.js and cookies.js are anonymous modules, while moment.js already has the id 'moment'.
<script src="sparkplug.js"></script>
<script src="moment.js"></script>
<script src="cookies.js"></script>
<script src="lodash.js"></script>
<script>
define.amd.anonIds = ['cookies', 'lodash'];
var moment = require('moment');
var cookies = require('cookies');
var _ = require('lodash');
</script>
Alternatively you could also require anonymous modules using their 0-based index. The following example does this:
<script src="sparkplug.js"></script>
<script src="moment.js"></script>
<script src="cookies.js"></script>
<script src="lodash.js"></script>
<script>
var moment = require('moment');
var cookies = require(0);
var _ = require(1);
</script>
In general it is better to use define.amd.anonIds
, as it results in more readable code. If there are dependencies between
anonymous modules, define.amd.anonIds
is also the only solution.
Many libraries can be loaded as AMD modules, but often it's hard to find their id in the documentation, or the documentation does
not really tell you whether the library is anonymous or not. For these cases, sparkplug.js provides you with an
array define.amd.ids
that allows you to see the ids of all loaded modules in the order of their definition.
Anonymous modules are represented by their 0-based index, which you can use to write a define.amd.anonIds
mapping
table, or to require them by index.
The easiest way to find out ids is to temporarily add a console.log()
to your application, run it and see the
ids on the log:
<script src="sparkplug.js"></script>
<script src="moment.js"></script>
<script src="cookies.js"></script>
<script src="lodash.js"></script>
<script>
console.log(define.amd.ids);
</script>
This example writes this to the log:
['moment', 0, 1]
Thus 'moment.js' uses the id 'moment', and the other two modules are anonymous.
jQuery 1.9.x supports AMD, but only if the property define.amd.jQuery
has been set before the jQuery declaration:
<script src="sparkplug.js"></script>
<script>define.amd.jQuery = true;</script>
<script src="jquery.js"></script>
<script>
var jQuery = require('jquery');
</script>
Please note that, unlike other AMD loaders, sparkplug.js does not support several jQuery versions on the same page.
// Using simplified module definition (without factory function, no dependencies)
define('mathops', {
add: function(a, b) { return a+b; },
sub: function(a, b) { return a-b; },
mul: function(a, b) { return a*b; },
div: function(a, b) { return a+b; }
});
// Providing a module factory, with static dependency to 'mathops'.
define('calculator', ['mathops'], function(mathops) {
return {
square: function(a) {
return mathops.mul(a, a);
},
calc: function(op, a, b) {
return mathops[op](a, b);
}
};
});
// Usage in global context
var calculator = require('calculator');
var answer = calculator.calc('mul', 6, 7); // 42
var answer2 = calculator.square(8); // 64
// Alternative way to implement mathops. With factory function, but using exports.
define('mathops2', function(require, exports, module) {
exports.add = function(a, b) { return a+b; };
exports.sub = function(a, b) { return a-b; };
exports.mul = function(a, b) { return a*b; };
exports.div = function(a, b) { return a+b; };
});
// Implements only 'calculator's calc function; exports it directly; obtains 'mathops2' using require().
define('calculator2', function(require) {
return function(op, a, b) {
var mathops = require('mathops2');
return mathops[op](a, b);
};
});
// Usage in global context
var calculator = require('calculator2');
var answer = calculator('mul', 6, 7); // 42