📜 ⬆️ ⬇️

A modular approach to developing web applications using JavaScript: AMD and RequireJS

RequireJS When developing applications with a modular structure of JavaScript, two problems arise:
Both of these problems are solved using the Asynchronous Module Definition approach. It comes down to the description of modules by the function define and connecting them with require. At the moment there are several tools that implement AMD. I began my acquaintance with them with RequireJS and was surprised how convenient and easy it is to describe the dependencies of the modules. I'll tell you how it works, on a simple example.

Bootloader connection

We have the following directory structure:
siteroot/ js/ app.js require.js jquery.js mymodule.js index.html 

To begin with, we will connect the loader in index.html. We will use RequireJS:
<script data-main="/js/app" src="/js/require.js"></script>

Great, this is the only script tag we need. The rest of the JS connection work will be done by the bootloader. The file specified in the data attribute (the .js extension is always omitted in RequireJS for short) will be a kind of entry point for our application. In it, we will be able to connect the necessary modules with the help of require and perform the conceived actions.

Module Description

We describe our module in /js/module.js with define:
 define( 'mymodule', ['jquery'], function( $ ){ return { foo : 'bar' }; } ); 

The first argument is a string, the name of the module, is optional. The second argument passes the dependencies as an array of strings, also optionally. The third argument is a factory function that is executed only after all dependencies have been satisfied (loading the listed files). Exported variables are passed to it as arguments. And it should return the module itself. In this case, it is an object with one field.

Using

In /js/app.js connect the necessary modules with JS and execute our code:
 require( ['mymodule', 'jquery'], function( Module, $ ){ $('body').append( Module.foo ); } ); 

Module will not be available in the global scope, as well as other variables exported by libraries from dependencies. Despite the fact that the jQuery library from version 1.7 supports the AMD architecture, it is an exception: it exports its dollar to the global scope. Most likely, this is done to preserve compatibility with an army of plug-ins written over many years.
')

Configuration

RequireJS has a number of parameters that can be passed before use. For this is the object require.config .

What if you need to connect a module that is not designed as an AMD and exports the variable to the global scope? You can, of course, modify its source code, but this is a bad practice. To describe such modules is the parameter shim . You can manually specify its dependencies and the exported variable, and it will become part of our application along with other AMD guys:
 require.config = { shim: { 'oldmodule' : { deps: [], exports: 'OldModule' } } }; 

Now you can specify it as a dependency:
 require( ['mymodule', 'jquery', 'oldmodule'], function(){} ); 

In addition to shim, there are many more parameters: the root directory for connecting the baseUrl files, aliases for more convenient paths , etc.

Conclusion

I hope the concept of AMD hooked you, as well as me. It helps to avoid chaos when using a large number of JS-files in development, pushes to write a reuse code, removes the responsibility for connecting files from the backend. And if you have a really large MVC application from a couple of dozen files, then such a system is simply indispensable.

In parting, here are some links that will help continue the study of the issue:

The source code from the article is available in the GitHub repository .
Happy hacking!

Source: https://habr.com/ru/post/152833/


All Articles