AMD, Asynchronous Module Definitions, is a method of loading Javascript code into a web browser. It was the heart of what I believe is the first practical module system for browser-based Javascript.
Another important tech piece of that era of modules was Bower, a Javascript package management system. Bower was not specific to AMD, but was a very good match to it.
In this article we’ll provide an overview of this style of browser-based Javascript development. In future articles we’ll dig deeper into AMD and Bower.
The overarching theme will be simplicity and understandability.
The small “stack” of AMD and Bower is simple, especially in comparison to what has come since.
AMD
Asynchronous Module Definitions is a bit of a lofty term of art, so let’s tease it apart.
Asynchronous
Asynchronous refers to the fact that with AMD Javascript code can be loaded, well, asynchronously. This is simply a requirement of the fact that AMD code is loaded from a url. Imagine a web app composed of many pieces of JavaScript code organized into files. Each of the files needs to be loaded first to bring the code into the app.
(We’ll get into this later, but AMD code does not actually need to be loaded from a remote file via a URL - but even then it will be treated as asynchronous.)
Module
At the time of AMD’s inception (___) Javascript did not support a concept of modules at the language level. What is a module?
From wikipedia:
Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.
The “module” in AMD refers to the concept to of an independent cluster of code which can rely upon other modules, and resolves to a single value.
For example, a module could define a UI component, providing a component object as it’s value, or a formatter for markdown, provided as a class implementing such a formatter.
Definition
The final component of AMD is “definition”. I’ve always thought this a rather odd part of AMD. It refers to the fact that, at its year, AMD provides a module definition in the form of Javascript code.
I hope that will more clear below.
Putting it all together: AMD
Okay, lets put that together into some concrete examples, and at the same time, show how it looks in real-world usage.
AMD is used to define modules, and then such definitions are used.
Here is just about the simplest possible module:
define([], () => {
return "Hello!"
});
We’ll place this into a file js/greeting.js in our public folder.
This defines a module which resolves simply to the string "Hello!"
How would you use this “module”?
In a page, you can add a script like this:
require(['js/greeting'], (greeting) => {
console.log(`I greet you with: "${greeting}"`);
});
The amd system will load the file js/greeting.js, execute the function supplied as the second argument, and associate the results with the module name js/greeting. This is only conducted the first time the module is loaded. In subsequent accesses, the module will be fetched from the module cache.
For a ruby site like this, the caching quality is not as important as for a single page web app (SPA). It is still rather convenient, however: it makes code usage transparent, adding functionality uniform and ordered.
Alternative code storage
Due to the design of AMD, we can fetch the code modules from anywhere we like. By default code is loaded from the server filesystem, based on a single root directory, in our example above the root is the public directory.
Some alternative code loading strategies:
- compile all modules into a “virtual file system” so that all code is loaded from memory, without fetching the code from the server for each module
- place modules into a database, so that modules are fetched form the database and not the file system
- load modules from a CDN
Want More?
In future articles we’ll discuss additional topics on AMD and our implementation of it, including:
- Using AMD to load other file types like CSS, JSON, Yaml.
- Limitations and noncompliance of our implementation