Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreAlmost ten years ago Adrian Colyer wrote a memorable blog post, giving the best explanation on aspect oriented programming (AOP) out there: clear and simple style, accurate content, no buzzwords. If you've taken a look at the the earlier two posts in this series, you may have noticed some of our architecture choices in the client module of the Sagan application, including the use of JavaScript modules.
In this post, I want to walk you through the basics of JavaScript modules in the style of Adrian's post: clear, simple, accurate, no buzzwords!
If, like me, you have a Java background, some JavaScript language features may look a bit odd to you:
Simple web applications usually look like this:
<html>
<head>
<!-- scripts are loaded **sequentially** -->
<script src="jquery.js"></script>
<script src="widget.js"></script>
<!-- all objects are in the global namespace,
no way to isolate the code completely! -->
<script>
window.$; // this is jquery
</script>
</head>
</html>
Developers often try to reuse blocks of functionality and manage dependencies between them. That's really hard to achieve in the previous case: you have to declare scripts in the right order and avoid name collisions without any metadata about dependencies. With a growing application, this task becomes a nightmare: imagine managing your Java applications without the benefit of packages or dependency management infrastructure!
Fortunately, the JS community is well aware of the need for modularity and over the last few years, a couple widely-adopted approaches to solving this problem have emerged:
AMD (Asynchronous Module Definition) is one of them:
// defining a module that depends on "graphmodule",
// injected in the function definition as an argument
define(["graphmodule"],
function (graph) {
// this module exports a "draw" function
return function draw(data) {
return graph.piechart(data);
}
}
);
The AMD format is often used in browser applications, since:
CommonJS is another authoring format, often used in Node.js applications on the server side, but also in browser applications.
/**
* Our module's dependencies and API
**/
// we fetch the graph module as a dependency
var graph = require('graphmodule');
// we decorate the `exports` variable to export our function
exports.draw = drawFunc;
/**
* API implementation
**/
function drawFunc(data) {
return graph.piechart(data);
}
You probably spotted some differences with AMD:
define
The next version of JavaScript (technically called ECMAScript 6) will standardize JavaScript modularity, albeit using a slightly different syntax than either the AMD or commonJS formats we've seen above. More, EcmaScript 6 will solve many problems in that space but will also make available syntactic sugar to define OO-like classes.
Wherever you're putting JavaScript to use, be it client or server, consider taking the modular approach — for all the same reasons we do in Java. There is a small learning curve to getting proficient with JS module technology, but the results are well worth it.
If you're brand new to JavaScript modularity, I recommend checking out the "Authoring CommonJS modules" tutorial and the module loader we're using in Sagan: curl. And once you're feeling familiar, take a look at our module definitions in the Sagan app.