LB

Javascript Module Evolution

Published at: 2022-12-10T00:00+03:00

Introduction

Javascript has been around the web for quite some time now in the web development world, starting as a language to add interactivity to the browser alongside with HTML and css, but now it is everywhere. Javascript has evolved over the years. It is now used in web servers, desktop applications, mobile applications, and even in IoT devices. It is now used as a general-purpose programming language.

For a long time, back when javascript was needed for website interactivity, javascript existed without a language-level module system. This was not a problem because the web was not a big place and the code was not that big. But as time goes by, the solutions, the user interfaces, and user experiences provided by web applications grew, scripts become bigger and bigger and more complex in size, and the need for a module system became more and more important. This is where the evolution of JavaScript modules started.

JavaScript is written in script tags inside HTML files and the browser loads the script and executes it. The browser has a global scope and all the variables and functions are defined in the global scope. But writing javascript this way poses a problem when the code becomes bigger and bigger. You might solve the code by writing the code in a function and calling the function in the src attribute of the script tag. But this is not a good solution because:

  1. the code is polluting the global namespace

  2. lack of dependency resolution: the order of the script tags in the html file matters. If the script tag that contains the code that depends on another script tag is loaded before, the code will not work. So you have to write the scripts in the right order.

So what is a module?

A module is a piece of code that is self-contained and can be reused in other parts of the code. It is a way to:

  • separate big and bulky code into smaller and more manageable pieces, divided by functionality and use case.

  • avoids name collisions and polluting the global namespace(in the browser).

  • reuse code and avoid duplication.

  • organize code and make it more readable, maintainable, testable, reusable and predictable.

Types of JavaScript modules

As time goes by, to solve the aforementioned problems, Different types of JavaScript modules have been developed over the years. The most common ones are:

  • IIFE: Immediately Invoked Function Expression

  • AMD: Asynchronous Module Definition

  • CommonJS: CommonJS Modules

  • ES6 Modules: ECMAScript 6 Modules

IIFE: Immediately Invoked Function Expression

It all started here, as this is the oldest form of the module of javascript. An IIFE is an anonymous function that is executed when it is declared. it isn't really a module pattern, it is a way to avoid polluting the global namespace. It is a way to wrap your code in a function and execute it and create a scope for your code. An IIFE is written like this:

(function(){

//code}

)();

The code inside the function is executed in a local scope and the variables and functions defined inside the function are not accessible from outside the function. It is an improvement compared to writing plain javascript inside script tags. By writing using this method you can expose the variables, objects, and functions that you want to expose to the outside scope. But still, IIFE is not a perfect solution as it suffers from the same problems mentioned above:

  • Lack of dependency resolution. The order of the script tags in the html file matters, as referencing a variable or a function that is not loaded yet will result in an error.

  • Still pollutes the global namespace(although it is much smaller than writing plain js in HTML), as the variables and functions exposed by the IIFE are still accessible from the global scope. So you have to be careful when naming your variables and functions to avoid name collisions.

CommonJs

CommonJS is a project with the goal to establish conventions on the module ecosystem for JavaScript outside of the web browser. It was one step movement to create a module specification for javascript. It was started by a Mozilla engineer called Kevin Dangoor in 2009, and initially named as server.js and later named as CommmonJs to show the broader applicability of the APIs. CommonJS is the default module system used in NodeJs. It is synchronous in nature i.e. when you load a module, your code will synchronously wait for the loading of that module to complete before continuing.

Modules need to be exposed(export) to others for use and be accessible(import) by others for use. The module syntax looks like this: // Exporting a module

module.exports = {

name: 'Lioul B.',

print: function(){

console.log(this);

}

}

// Importing a module

var module = require('./module.js');module.print();

You can find the full specification here. When using commonJs modules for frontend development, code bundlers and transpilers must be used, since browsers don't support commonJs.

AMD(Asynchronous Module Definition)

Because of the fact that the main intention of CommonJS is for server-side JavaScript, it is synchronous in nature. This means that when you load a module, your code will synchronously wait for the loading of that module to complete before continuing. This is not ideal for the web browser, where you want to load your modules asynchronously. This is where AMD comes in. AMD is a module specification for javascript that is asynchronous in nature. AMD is the default module system used in RequireJs. The module syntax looks like this:

// Exporting a module

define('module', [], function(){

return {

name: 'Lioul B.',

print: function(){

console.log(this);

}

}

});

// Importing a module

require(['module'], function(module){ module.print();});

For AMD modules to work in the browser environment it take the leverage of a module loader called require.js, as it will help us load modules asynchronously as needed. Before using the AMD modules in our environment Requires need to be installed and a script tag need to be added to the html file along with the entry point, like so:

<scriptdata-main="entrypointjs"src="require.js"></script>

You can find the full specification about AMD here.

ES6 Modules(ESM)

Finally, in 2015, Ecma International, the standards body for JavaScript, released the ECMAScript 2015 specification(ES6). This specification included the module system for javascript. The next stage in evolution and the most modern and best-case module pattern to use today is the ES6 modules. It is a standard module system for javascript. It is asynchronous in nature i.e. when you load a module, your code will not wait for the loading of that module to complete before continuing. It is the default module system used in browsers as more and more browsers are supporting running ESM natively. The module syntax looks like this:

// Exporting a module

export const name = 'Lioul B.';

export default function print(){

console.log(name);

}

// Importing a module

import anotherModule, {name, print} from './module.js';

anotherModule();

Since 2015 JavaScript has standardized module specification and the ECMAScript specification has been updated every year with new features and syntax and ES.Next is a dynamic name that refers to whatever the next version is at the time of writing. Full specifications can be found here.

As for running ESM in browsers, there are two ways to do it for the development and production environment. The first way is to use a bundler like webpack , rollup, esbuild, and e.t.c to bundle your code into a single file and then use a script tag to load that file. This method is good for the production environment as it will reduce the number of HTTP requests for every imported module and the size of the file by bundling, code splitting, and minifying. The other way is running ESM natively in the browser, as most browsers are supporting running ESM natively, Currently, Vite is a good example of this, and also saves a huge amount of bundling time on the development environment as we no longer need to bundle on development.

That's it about JavaScript modules, Thanks for reading to the end.👏👏👏💪💪.

Get In Touch

© 2024 Lioul Behailu . All rights reserved.