RequireJS is an open source JavaScript library that has gained a lot of popularity in the recent years. The library is used to manage JavaScript dependencies and to prevent script loading order issues. It is also helps avoid having to load all the JavaScript files at once and only load the ones needed on demand. It also promotes ‘modularizing’ the code and breaking it apart into smaller modules that are managed independent of one another, which leads to a more scalable and robust applications.

RequireJS relies on using the Asynchronous Module Design (AMD) pattern. In this pattern, each Javascript module or pieces of functionality is declared as stand alone module with a known list of dependencies. These dependencies are passed in during the load time of the module. Doing so prevents the issue of loading dependencies in a particular order. It also leads to cleaner and more modular code that can be easily replaceable in the future. It also prevent variable collisions and scope contamination.

Creating AMD Modules
Declaring a new (AMD) module in RequireJS is straight forward. For that, the provided ‘define’ function is used to declare the new module. The ‘define’ function takes in two parameters. The first parameter is an optional parameter, and it is an array containing a list of all the dependencies for the module. The second parameter can be a function or an object literal representing the body of the module. The name of the module can be passed in as a the first parameter. But when omitted, the file name is used to infer the module name. Typically, when creating simple (AMD) modules, it is simple enough to use an object literal. However, when the module is more complex, the module reveal pattern is used by passing in a function to the ‘define’ method.

Example:
Say one is implementing a service that is used to sign up college students for various courses. Using the ‘define’ function, a ‘course.js’ module is declared as the following:

define([], function() {
function signupForCourse(studentId, courseId) {
// The signing up logic here
}

return {
signupForCourse: signupForCourse
};
});

The code above must be included in a file called ‘course.js’ since this is how the name of the module is declared. The code does not have any dependencies, so there is no need to pass in any parameters to the define function. The first parameter (‘[]’) is optional in this case and it can be dropped.

Creating AMD Modules with Dependencies
Say in the previous example the ‘course’ module needs to check for any prerequisites courses before singing up a student for a given course. All the prerequisite validation operations are handled by a separate ‘prerequisite.js’ module. The ‘course’ module can be declared using the same ‘define’ function above. However, the ‘prerequisites’ module needs to be passed in as a dependency:

define(['prerequisite'], function(prerequisite) {
function signupForCourse(studentId, courseId) {
// First check for any prerequisites
prerequisites.checkForPreRequisites(studentId, courseId);
// Then the signing up logic Here
}

return {
signupForCourse: signupForCourse
};
});

In the code above, the ‘prerequisites’ modules is passed in the dependencies array in the first parameter. It is then mapped to the ‘prerequisites’ variable that is passed in to the call back function. Note that the two names do not have to be the same. However, they are usually kept the same for consistency. The name ‘prerequisites’ that is passed in to in the first parameter must match the name of the file ‘prerequisites.js’. RequireJS append the ‘.js’ extension automatically.

Loading AMD modules on Demand
Once an AMD modules is declared, it can be loaded using the ‘require’ function provided by RequireJS. The syntax of the ‘require’ function is almost identical to the ‘define’ function. It takes in an array of dependencies as the first parameter, and a call back function to be invoked once the loading is complete. The only difference between the ‘define’ and the ‘require’ function is that the first parameter is required in the ‘require’ function.

The entry point to any JavaScript application that uses RequireJS is typically the ‘main.js’ module. It is not a requirement, but more of a convention use in the industry. To declare a ‘main’ module that load the ‘course’ module above as a dependency, the code looks like the following:

require(['course'], function(course) {
// Get a student and a course ID
var studentId = 123,
courseId = 456;
course.signupForCourse(studentId, courseId);
});

If the ‘main’ module require other dependencies, they can be passed in like the ‘course’ module.

Wiring Up the ‘Main’ Module
In order to trigger the load of the ‘main’ module to launch the JavaScript application, RequireJS requires a specific HTML attribute called ‘data-main’ to be added to the script tag that loads the ‘RequireJS’ library. The attribute’s value must be the path to the ‘main.js’ file, and the extension ‘.js’ is omitted by convenstion. The script tag can be added to the header of the ‘index.html’ file of to the end of the body to ensure the DOM is loaded. An example of the script tag looks like this:

define() vs. require()
Given that both functions are very similar in the way they are applied and declared, it can get confusing to when they should be used. Typically, ‘define’ is used when declaring a new AMD module. This is analogous to declaring a class an object-oriented language. The ‘require’ function however is used when an instance of the AMD module is needed. This is analogous to making an instance of a class in an object-oriented language.

RequireJS Configuration
RequireJS can be configured in various ways to better suites the application needs. The ‘require’ object takes in a ‘config’ object that accepts an object literal that defines various parameters. One of the most commonly used parameters is the ‘paths’ object. You can setup ‘shortcut’ to various paths in order to simplify the loading of the modules. The RequireJS configuration are typically handled in the ‘main’ module. It also supports loading libraries from CDN providers:

Example:

require.config({
paths: {
'scripts': '../scripts/js',
'tests': '../scripts/jasmine',
'plugins': '../scripts/plugins',
'jquery': 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min'
}
});

An enthusiastic architect and full-stack developer with many years working with enterprise software and cloud services in multiple domains.