Sunday, January 29, 2017

Modular Javascript

I actually never heard much about modules until I have started developing Angular 2 applications(enterprise level). This post is more about modules in javascript which include different module formats and module loaders starting with the necessity of going modular.

Why Modules in javascript:

1.To define higher level abstractions that let you make an application of larger building blocks

2.To maintain implementation details hidden . can re-factor code and easy maintained and re-usability

3.Simplify dependency management 

So how does the modules evolve?

Earlier when javascript was developed there was no support for modules until now which led many developers groups  to invent solutions for writing modular based and then after writing too many modules for an application  by setting some standards(led to different module formats) then they found it hard to integrate all modules i,e packaging and distribution..then again.. finally meanwhile javascript evolved and started supporting MODULES(Current version ES6 mostly referred as ES2015  )

However this newer version of javascript is not supported by browsers yet which require a transpilation step using external  compilers like Babel or Typescript

lets define Module before we go ahead :

A group of code and data related to a particular piece of functionality. It encapsulates implementation details exposes a public API and is combined with other modules to build a larger application.

Module Format: 

is just a syntax used to define a module which is independent of loader , but syntax is useless without something that executes .Different Module formats are;
1)Asynchronous Module Definition Format(AMD)
2)CommonJS
3)Universal Module Definition (UMD)
4)System.register format
5)ES2015 fomat

Module Loader :

They are just javascript libraries we'll include in our project to understand the module format we decide to use  and how to load and execute.Some of the module loaders are:

1)RequireJS :-supports AMD module format
2)SystemJS :- Most popular loader which supports AMD,commonJS,UMD and system.register formats.

Before we go in detail about  module formats and loaders let us see how we used to manage javascript code without  these external libraries.

One of the familiar way was
1) IIFE (Immediately Invoked Function expressions) : Provides encapsulation and reduce the number of variables that we store in global scope (reducing global scope pollution )

(function(){

})();     which is immediately invoked that is no global storage

2)Revealing Module Pattern: Variables are scoped to functions in  js
Function scoping provides nice encapsulation of module implementation details

Unlike IIFE we need referred modules in code , so they should have name ....that means that they do add new value to the global scope

Along with encapsulation good thing about this pattern is the code is easier to read, maintain and provides clear separation b/w private implementation details and modules public api (i.e we can have all implementation and expose methods or properties we choose to )

We have 2 different types in this pattern 
1)Singleton and
2)Constructor pattern

Just quickly have syntax look

Singleton Pattern :



Constructor Pattern:



I think the name and code implementation are self explanatory 😃

So What do you think is lagging in going that way ...? yes Dependency Management we will load these js files in index.html with out missing the order i.e loading the dependent modules is trivial and is not so easy in enterprise level applications where we have 100's of js files

So lets actually get in to Module formats and load them using Module loaders

Asynchronous Module Definition Format (AMD) 

Used to define modules that will be loaded in browser . The AMD format supports loading asynchronously which is good when modules are requested from server and loaded in browser.. i.e on demand

syntax:
We define AMD modules by calling a function name define (this is not a built in Javascript but require a javascript loader) which have two parameters where the first is an Array of dependencies(mentioning relative path of module) and second is function which turns as module.
We  have to mention the module name and extension of js is not required 

employee.js

define([], function () {
    var empName = "";
    function displayName() {
        console.log('Name is ' + empName);
    }
    function setName(employeeName) {
        empName = employeeName;
    }
    function getName() {
        return empName;
    }
    return {
        //We can choose what we want to expose i.e hiding rest of
        displayName: displayName,
        setEmployeeName: setName,
        getEmployeeName: getName
    }

});

this file itself becomes a module, to have this module in other modules we need to provide this as a dependency
define (['./employee','./manager'], function (employee,manager) {
    //we can use methods and properties exposed by
    // employee and manager using the objects
});

So we have created a module , now to load the module we need a module loader i,e using requirejs module loader , we can get this from   http://requirejs.org/

Another way is through package.json with npm (node package manager), we can specify in dependencies or just install with command
npm install requirejs --save

So how to load these files?

<script data-main="js/app" src="node_modules/reuirejs/require.js"></script>

We have to mention the entry point module of the application   


What ever the dependencies are with app.js i.e app module are loaded first.

CommonJS Module Format:

Mostly used in server applications.(Node JS which have a built in loader that supports CommonJS format). However we can load with  SystemJS Loader also.

We can get dependent modules using require keyword

var employee = require('./employee.js');  //Module loader will make sure that dependent modules will be loaded 1st before executing the current module.

In order to expose functions and other properties of current module i.e as an api we need to add them as new members of special object named exports 

function testing(){

}
exports.firstfunction = testing;
Just like require, a keyword , exports object is a special object that a commonjs syntax  loader will use when creating the structure of the  module and the api that is exposed to other modules of the application. The member name on the object need not to be same as the function name you are exposing as api.

The major difference of commonJs format is that module definition is not wrapped inside a function as we do in other formats(as AMD ).

In CommonJs format by default each file is treated as module.

A little bit more about exports object 
We' usually find module.exports ,so how different it is from exports object , both are equivalent except for a few gotchas
exports.firstfunction = testing;  is same as 
module.exports.firstfunction = testing;
but we cannot export object literals by assigning them to short hand export object 

exports={ }  and also we cannot directly assign a function to short hand version of export object.
exports= function() { } 
We have to export along with module i.e like module.exports={ };

So how can we load these modules i.e commonjs module.. which is .. using SystemJs module Loader.
We can install systemJS with npm as npm install systemjs --save

So to load systemJS we need to reference it in index.html as 

<script src="node_modules/systemjs/dist/system.js"></script>

We need to add some extra javascript with a configuration object (to mention the which syntax or module format , as SystemJs supports multiple formats) provided by Systemjs loader and to put up an entry point to application we need to have a import 

<script>
       System.config({
              meta: {
                     format:'cjs'
              }
       });
       System.import('js/app.js');
</script>