How to Modularize Javascript Code

How to Modularize Javascript Code


Before we learn How to Modularize Javascript Code, we first need to understand what they are.

Can you think of any complex system ranging from a bicycle to a more complex automobile engine?

What is the common feature of these complex systems? These systems are made of individual parts with different functionalities interacting with one another to perform various actions.

Modularize Javascript Code
Image of a disassembled bicycle

Let’s take a bicycle for an illustration. A bicycle is made up of several parts, each of these parts is made up of various components. All of these parts are put together to form a bicycle.

Looking at the diagram above, one can notice how many of the same pieces are being used throughout the bicycle example the tires, brakes, etc. This ability to re-use pieces simplifies the manufacturing process.

In software development, this concept is termed REUSABILITY.

Don’t be carried away by the visual simplicity of a bicycle because it is pretty difficult to understand its entire system. Since a bicycle is composed of small parts, each of those parts can be built or repaired by engineers while not hindering one another.

Also, if some of its parts get damaged, instead of replacing the whole bicycle, just the damaged parts have to be replaced. In software development, this concept is termed ISOLATION.

The benefit of these concepts holds the same in software development.

What are the Modules?

Modules are the basic building blocks for constructing javascript applications. In a simplified term, modules are small pieces of code with independent functionalities.

Why Modules in JavaScript?

A typical real program grows gradually. New pieces of functionality are added as new needs come up.

Structuring and preserving your codebase is additional work. It’s work that will pay off only in the future, the next time someone works on the codebase.

So it is tempting to neglect it and allow the parts of the program to become deeply entangled.

Practically this can cause two major issues. it is difficult to look at any given piece in isolation (i.e testing functionalities becomes difficult).

If you want to use any of the functionality from such a program in another situation, rewriting it may be easier than trying to disentangle it from its context (i.e issues with the reusability of code).

JavaScript Module Formats

There are two module formats in JavaScript, CommonJS and ES6 Modules format. In this article, we will consider both formats

CommonJS module Format

Loading a CommonJS module is a synchronous operation. That means that when the require (module-name) function call returns, the module has been located and completely read into memory and is ready for use.

The module is cached in memory so that subsequent require (module-name) calls return immediately, and all return the exact same object. Objects and functions can be exposed from a CommonJS module using module and exports.

The export object is the same as the module. exports object. This means that the following two lines of code are equivalent:

exports.myFunctionName = function(arg, arg1) { … };
module.exports.myFunctionName = function(arg, arg2) { .. };        

Beware of this  syntax

 exports = function(arg, arg1) { … };

if your intent is to assign a single object or function to be what’s returned by requiring as it is considered bad practice since exports will no longer be equivalent to module.exports.do this instead:

module.exports = function(arg, arg1) { ... };

ES6 module format:

The interesting detail is that

  • ES6 modules-load asynchronously.
  • ES6 module format makes use of the import and export keyword.
  • ES6 module import happens before a module’s script starts running.

The export keyword is used to export function, class, or binding definition. It may appear in front of a function, class, or binding definition ( let, const, or var ). 

Also, the import keyword is used to import function, class, or binding definition. It is possible to rename imported bindings using the word as

import {months as monthNames} from "date-names";

How to Modularize Your Javascript Codes

Note: For this code to run on the browser we have to host it on GitHub or better still you can use a live-server.

Enough of this theoretical write up let’s get into coding. Open your favourite code editor and create a folder “modular code”. Create a file module_1.js with the following code.

    let count = 0;
    export function increment () { return ++count; }
    function decrement () { return --count; }
    export function hello () {
        return "Hello, world!";
    }
    export default function() { return count; }
    export const meaning = 42;
    export let numberOfCount = -1;
    export { decrement };

The export keyword is used to make items available outside a module while the import keyword is used to import items into another module. The statement in line 2, 4, 8 and 9 are named export, meaning the exported thing has a name, and that code outside the module uses that name to access the object.

Named exports are used if we don’t want to import everything the module is exporting. As we see here, named exports can be functions or objects, and they may also be class definitions.

Using export default as seen in line 7 can be done once per module, and is the default export from the module. Now let’s see how to use this ES2015 module. Create a module_2.js file with the following:

import * as sample_1 from './module_1.js';
console.log(sample_1.hello());
console.log(`${sample_1.increment()} ${sample_1.hello()}`);
export function firstName () {
   return "Emmanuel"
}
export function lastName () {
   return "John"
}
export default function count () { return count; }

The asterisk symbol in line one means all the exported items. Notice the difference between the console.log statement in line 2 and line 3 the later is using javascript template literals for interpolation. When you use a named default export, that changes how you import that module. Instead of using the *  or using named imports, you just use import name from ./path. Let’s import the count function from module_2.js file.

import count from './module_2'

Did you notice how I omitted the .js extension in the code snippet above? This is because it is optional to add the extension when importing a module.

Now, what if you had a module that was exporting a default export but also other named exports as well? Well, I’ve got you covered.

import count, { firstName, lastName } from './module_2'

Now to see how to import anonymous default export from a module, create another file, named module_3.js, containing the following:

 import { default as simple, hello, increment        
 } from './module_1.js';
 console.log(hello());
 console.log(increment());

In this case, each imported object is its own thing rather than being attached to another object. Instead of writing sample_1.next (), you simply write next() .

CONCLUSION

Modular programming is very important in the front-end as well as the back-end in software development. So in order to build a scalable and reusable software, you need to embrace modular programming.  

The full code can be found here.


Share on social media

//