Imediava's Blog

Just another WordPress.com site

Monthly Archives: April 2012

Introduction to Require.js

In a programming language like Java you normally don’t need to pay attention to how dependencies are loaded. All you need to do is define your dependencies with a fully qualified name (e.g. import java.utils.Collection) and the loading is done transparently by the JVM.

However when you move to JavaScript the landscape changes and you realize that loading dependencies is not a simple process. JavaScript doesn’t initially define a smart module system, what means that the programmer needs to take care of it by himself, making modularisation difficult.

Let’s have a look at an example of a project and the dependencies that are defined within its modules. The dependencies are represented as arrows from the client module on the left to the required module on the right:

module1 → module 2 → module3, module4

With this system in JavaScript, every time you need to use the module1, all the other modules need to be imported in the right order in the following manner:

<script type="text/javascript" src="module4”></script
<script type="text/javascript" src="module3”></script>
<script type="text/javascript" src="module2"></script>
<script type="text/javascript" src="module1"></script>

Whereas in Java a similar system could be defined like this:

//Module 1
import module2; 

class Module1 { .. }

//Module 2
import module3;
import module4;

class Module2 { .. }

// And a client module would only need to import module1
import module1;

class Client { .. }

Disadvantages of Javascript

We can see that JavaScript’s approach is less adequate:

  • It means that every time we want to use module1 we have to first have a look at which are its dependencies recursively.
  • What makes it even worst those dependencies need to be defined every time the module is used.
  • If the dependencies change, they need to be redefined in every module that imports module1. If someone is using module1 and forgets or is not informed of the changes, its code would stop working without any previous notice regardless of if there have been any changes in module1’s public API.

CommonJS and Require.js

The good news are that there are ways on JavaScript of defining hierarchies of dependencies in a way pretty similar to that of languages like Java.

In platforms like Node and Rhino, you can use the “require” function that allows to load dependencies of modules that have been defined using the CommonJS specification. However this loading mechanism is not specially suited for JavaScript on the browser where loading synchronously is not the more appropriate mechanism. Luckily Require.js exists, a library that allows defining dependencies between modules in a way that is appropriate for the browser.

Applying Require.js to our initial example

To allow a module to be imported with requirejs you need to wrap your javascript in a module format defined by the library. Fortunately the format is really simple. Let’s start applying it to the leafs of our hierarchy, the modules 3 and 4.

define(function(){

     // Code defining the module (private code)
     ....

     // It returns the properties that form the module's public API
     return {
         myMethod1: function(){ .. } 
         myProp1: value
     };
});

All we need to do is wrap our code in a call to define and pass it a callback function. The callback function must return the methods and properties of the module that you want to make available to its clients , it’s public API . This is done in a way that follows the Module Pattern a pattern that has as purpose to preserve the encapsulation of modules. Despite of wether or not you’re interested in using requirejs you should definitely use the Module Pattern when programming in Javascript to protect the clients of your module and to avoid polluting the namespace.

When you’re defining modules that have dependencies on other modules like module1 and module2, the definition doesn’t change that much. The only modification requires to provide as the first argument to the define function an array with the dependencies of the modules (the imports) and as many parameters as imported modules to the callback function. Taking as an example module2 the definition would be the following.

define([“module3”, “module4”], function(module3, module4){

   // Any code 
   ...

   // Accessing the methods of the imported modules is done
   // through the parameters of the callback function

   module3.myMethod1();
});

Loading any module would follow the same pattern keeping the benefit of only having to define direct dependencies.

Finally defining the starting point

Any Javascript application that uses requirejs needs to have a starting point. It is something similar to how an application in Java has to have a class with a main method. This starting point uses the require function to define its dependencies. This function works just like define by passing an array of dependencies and a callback function with the code that will run when the dependencies are loaded.

require([“module1”], function(module1){
   // Code to run as a main method
   ....
});

Best Javascript Tools

I remember when I started creating webpages coming from a background in Java that I looked at Javascript and I really didn’t get it. I guess it didn’t help the fact that the critics about the language were spread all over the internet. It gave me the impression of a really old language, the legacy of a list of wrong design decisions. Overall I felt like it was something I had to deal with but I should avoid, trying to do as much as possible on the server.

However, now after I’ve had some experience with it I realize that it was just a prejudiced impression. It’s a fact that Javascript is an old language and there are some things that have been done wrong over its history.

Nonetheless, Javascript is living a renaissance. There is a really active community backing it and many innovations going on. Many of the mistakes in its design have been addressed and overall it is just a matter of having the expertise to be able to avoid them. As with any programming language, it is a matter of using it well. The great news with Javascript are that thanks to its community there are many available tools that make this task of “programming well” easier.

This is the list of my favourite Javascript libraries for this task:

  • Underscore – A really interesting library of useful functions to operate with collections, arrays, objects or other functions.
  • Coffeescript – A language that takes influences from ruby and provides among other things list comprehensions, a smarter way of dealing with variables without polluting the namespace and many other useful tricks that can make Javascript development simple. Coffeescript compiles to a well formated Javascript, thus allowing for easy debugging.
  • Require.js – A library for defining dependencies between Javascript files, Require.js facilitates a better modularization of code. It also allows smart resource loading and resource compression, making page loading faster. (See an introduction to the library here)
  • Backbone – An MVC-like framework for defining complex one page web applications.
  • Mustache: A logic-less template engine that is available for many languages including Javascript. Its markup is powerful while keeping developers from cluttering templates with complexity. It can be replaced by handlebars whose templates are fully compatible with Mustache but provides even more powerful features. Both can be plugged into Backbone’s template-agnostic views system.

  • My intention is that this article serves as an introduction for a list of posts where I delve into each of this tools features, advantages/shortcomings and alternatives.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: