modular, we generally mean it’s composed of a set of highly decoupled, distinct pieces of functionality stored in modules. As you probably know, loose coupling facilitates easier maintainability of apps by removing dependencies where possible.
Loose coupling implies each component can operate or be tested independently of other components.
Tight coupling implies each component “knows” the details or inner workings of other components.
In just a few lines of code you can provide for architectural features above to improve from revealing module pattern to asynchornous module definition code. Here’s a look into why and how.
Script Tag Vomit
James Burke of Mozilla Messaging who writes require.js explains the problem in his presentation Fast, modular code with jQuery and RequireJS.
It’s slow with many http requests, manual dependencies (did I load it in the right order?), and a real lack of encapsulation.
Asynchronous Module Definition is designed to solve this issue.
There are a number of great loaders for handling module loading in the AMD and CJS formats. My personal preference us RequireJS. There is also curl.js.
Is an asynchornous script tag loader that you can call at any time. It provides encapsulation, traces nested dependencies, and provides an optimization tool.
You end up with the following code in your page:
<script src="../js/require-jquery.js"></script> <script>require(["app"]);</script>
You also can get optimized CSS files.
Modules provide strict encapsulation and isolation of the globals, as you learned in Namespaces, Anonymous Module, Revealing Module Pattern. For example, you can have multiple version of a module on a page. So if one part of your script requires one version of JQuery and another script requires another version, you are still in business.
Let’s take an example of taking jQuery and making an extension with and without use code written using the asynchronous module pattern.
The module pattern looks like this:
Asynchronous Module Pattern
The RequireJS Pattern looks like this:
There is a quite a bit of difference between the two examples. In one, you are calling the function and relying that you have already loaded jQuery. In the Asynchronous Module, you require it to be loaded before loading or running your module.
It’s About Dependencies
With Asynchronous Module Definition, you can specify the dependencies for each module, and those dependencies are automatically loaded for you.
Even if you are using ASP.NET Bundling and Minification, you and your team must put the order loading into the C# code. Instead, if you use RequireJS, even if the order is slightly out of whack in the server code, when you use RequireJS
require() will end up with your code working as expected.
Why Not Web Workers?
Web Workers might be another way to load scripts, but it is a message-passing API, and the scripts likely want to interact with the DOM, so it means just using the worker to fetch the script text, but pass the text back to the main window then use eval/script with text body to execute the script.
In the following posts, you will learn how to use RequireJS to build your modules in Getting Started with Modules Using RequireJS.