Writing modular and dependency based JavaScript

Standard

Usually most of the websites are always using some kind of JavaScript to make them more interesting and modern. Occasionally this means animations, carousels, parallax scrolling and so on.

To create this kind of functionality, some developers are loading tens of JavaScript files separately and no further code or dependency organizing is done. It will be hard for other developers who have to maintain the code –  it is unreadable and scripts may easily overlap when creating new features.

This is okay for simple websites, but what happens when we are dealing with a large scale website, which has huge amount of different JavaScript files in various sizes ? Code is not organized anymore and it is hard to maintain. How to solve this problem?

Looking for the solution

A few years ago I was creating a frontend application for a client in JavaScript and I needed to have solution for this kind of problem. I had around 30 JavaScript files and every file was giving a little functionality, but usage of functionality was different from page to page. It seemed not wise for me to load all the files in header and also compiling everything into one big file was also not a solution.

So every little little JavaScript file was having content like this:

This was very hard to manage as scripts started to have many dependencies in a way that may overlap and nest.

I was working a lot with Dojo framework that time and Dojo had built in functionality for loading scripts through XHR calls. This seemed like a solution, but it wasn’t enough. After reading roadmap for 1.6 release there was a feature called AMD (Asynchronous Module Definition), which was using CommonJS API proposal.

Asynchronous_Module_Definition_overview

This was a solution – I created an AMD loader based on Dojo’s implementation and I refactored all small files as modules, which were loaded during runtime according to dependencies. I was happy with this solution – there was no delay during loading and my code was organized really well. I am still using AMD actively in my biggest projects, although I abandoned my own implementation and decided to use requireJS instead.

Getting started with Javascript modules and dynamic dependency loading

At first you should look for a loader and today there are dozens of AMD module loaders available – some are lesser known like $script.js and Dojo’s native loader and some are more known as curlJS and requireJS.

I prefer requireJS, because it is well maintained, documented and works really good with jQuery. It also includes an excellent optimizer “r.js”.

Typical requireJS module looks like this. Let’s call it “message.js”:

And typical initialization script looks like this:

When using jQuery, things get a little bit complicated, because jQuery registers itself as global variables “$” and “jQuery”. To make it work, it is needed to add shim configuration to your already defined requireJS configuration.

Loading plugin according to dependencies somewhere in your code is easy. Just call:

Now you can easily load dependencies when actual functionality is needed rather than loading everything at once.

When to use?

Creating dependency based JavaScript modules depends on the project – you will not win anything when using this approach on small projects, but you will certainly win a lot when using this approach on large scale projects. Your code will be much better organized, maintainable and your overall application quality will increase a lot. Also all other developers who have to work with your script will thank you.

Combining requireJS and backboneJS

When I am doing JavaScript development, I am also using backboneJS to have MVC approach in my application. BackboneJS is wonderful and minimalistic framework, but it does not support AMD and therefore it is needed to use AMD loader.

Combining backboneJS with requireJS is easy:

App module will setup router and initializes collection and views.

Typical boilerplate module will look like this:

You can read more about combining backboneJS with requireJS on backbone tutorials.