Modules in JavaScript

Modularity is a corner stone in handling complexity. This is a solution which is applied in multiple discipline with same result – reduced complexity; which eventually leads to many secondary benefits. Modules are the outcomes of applying principles of modularity in let us say – JavaScript. This is not necessarily limited to the language of JavaScript. In fact, it is javascript which borrowed this concept from other programming languages. But for the sake of yielding examples let us say JavaScript. That said; let us see quickly what does a module look like in JavaScript –

 

(function remoteStub() {

   … // Private code

   return {

       … // Public more code

   }

})();

 

If this code corresponds to module, it might be confusing you with closure which looks like this –

 

 

function remoteStub() {

   … // Private code

   return {

       … //Public code

   }

}

 

If you notice closely, you will observe that we have few extra parentheses in module. Those extra parentheses are organized in a manner which makes the module what is commonly known as IIFE (pronounced as eyefee). That stands for Immediately Invoked Function Expression. So, we could para-phrase ourselves to state that modules are a type of closure and is also an IIFE or better way to put it will be modules are IIFE closures.

These analogies or way of arranging the thoughts put us right in the entrance of the topic Design Pattern. Yes, modules are nothing but a design pattern that have been adopted so widely that it is part of the ECMA standard and is now part of browser. We used a simplistic way of defining module. But, in real life there are many other considerations that lead to what we can find as modules section today in ECMA standard.

Before we take flight in different types of module interpretations, long time JavaScript developers can ask what about the humble script HTML tag in browsers?

 

<script src=”…” type=”text/javascript”>

</script>

 

 

Before these fancy frameworks were there, we scaled up code in javascript using the very techniques of IIFE and script HTML tags. What is wrong with them? The answer is simply nothing wrong with them. Like in any enterprise project where scope changes over long time and the humble old code needs to be loaded up with modern features etc., similarly the reason for modules being included in standard is to address such a change. The change here refers to the change in the way javascript is consumed. As long timer you wouldn’t take a blink of eye to say javascript is for browsers. In the modern era you will hesitate to make that statement and factually it is not correct to make that statement as well.

Javascript now a days run in many different context – Browser (definitely), Native application (Node), Virtual machine (JVM, CLR) etc. For these varied contexts we cannot use the humble script HTML tag only, isn’t it? That is why the concept of module found abode in ECMA standard.

This doesn’t mean that the fundamental of IIFE and Closure are changing, rather finding place in standard means they have now found a more uniform way of being coded across multiple environments. In the recent past before the modules were standardized in ECMA there were multiple ways to achieve the same behaviour. Names like CommonJS, AMD and UMD might resonate. This led to library compatibility issues and much of boiler plating. But that is all a thing of past today. With ECMA standard in place all runtimes of javascript have a common way of leveraging the modular design pattern for javascript.

The two cornerstones of keyword for this standardization are – import and export. Thus, the IIFE we declared earlier as a primitive module will now look like this –

 

export const pi = 3.14;

 

export radius = 1;

 

export function calculateArea() {

   return Math.pow(pi*radius,2);

}

 

export function shapeLibrary {

   function draw() {

       …

   }

   return {

       rect: () => {….},

       triangle: () => {draw();}

   }

}

 

This code though much longer than the IIFE version has intentions clearly expressed with what all we are exporting. Let us say if this file was to be called as geometry.mjs then it can be used in another library as follows

 

import {pi, radius, ..} from ‘./geometry.mjs’;

 

Provided both the files; the one importing and the one that exports are in same directory.  This is not the only way we could also call upon an import like this –

 

import * as shapes from ‘./geometry.mjs’;

 

The earlier one is called named imports and the one above is called as default import. The ‘as’ keyword is used to avoid name collision as there are loose elements in the geometry.mjs file like variables. Typically, an export will be wrapped in class or an outer cannister which will eliminate the challenge of name collision.

In case you are curious toward the mjs extension; it is an extension for the module file recommended by V8 and has the same MIME type as that of the js files. The reason for propagating a different extension for module file is for advanced scenarios of Babel processing based on file extension and for Node to be able to differentiated between a module file and a consuming regular javascript file.

This is just the surface that we have scratched on the topic of modules. Much of maintainability of modern day javascript applications can be accomplished with carefully drafted modules. With browser support for ECMA standard coming in for modules the choice to run same code in multiple run time environments improves the prospects of reusability.