DEV Community

Cover image for Getting Started with JavaScript Modules
Alok Kumar
Alok Kumar

Posted on • Edited on

Getting Started with JavaScript Modules

Hey All ๐Ÿ‘‹ ,

This is my second article on JavaScript ES6 Concepts. If you have not read the first one yet, you can read it here. In this article I'm going to talk about all you need to get started with JavaScript Modules.


Table Of Contents -

  • History
  • What are modules, and why do we need them?
  • Intro to CommonJS Modules
  • ES6 Modules
  • Import and Export
  • Some important features of ES6 Modules

History

Earlier back in the days' applications used to be simpler and small, and thus their code. When the Javascript code was smaller, it was no big deal to keep them in a single file, but as applications improved and grew big, the code grew too, making it challenging to manage them and keep them in a single file.

Thus the concept of modules came into existence. There were a variety of ways invented to implement this concept. AMD and UMD, to name a few.

But these are now a part of history and are no longer used now generally, but you can find them in some of the older applications.

Another module system invented was CommonJS, which was created for the Node.js server. We'll talk about the CommonJS module system later in this article.

The language-level module system came in 2015 and is generally called ES6 Modules. Also, now it is supported by all major browsers and Node.js, so we'll talk more about ES6 modules in this article.

But first, let's talk about what modules are.

What are modules, and why do we need them?

Modules are simply the building blocks of data using which we can build a large application.

The basic idea behind modules is that we can export a part of the code, and then we can import that into other files to be used.

Using modules, we can break a large script into smaller modules, which can also be used in other files.

Let's understand this with the help of a picture -

JS Modules

You can see that all functions or code is in one file in the first picture, thus making it large. Now imagine having such 20-30 functions along with other code; how large will this file get. It'll make it hard to understand and manage such a large file.

Thus we split the code into modules, as shown in the second picture. We have written the functions in separate modules and exported them. Now they can be imported by the index.js and also by other modules. As we can see, Modules A, B, and C are imported by index.js; also, Module A is imported by Module B. And now, our code is easy to understand and manage as functions are in different modules, and our index.js is small.

Note: JS modules can export variables, functions, objects, etc.

Let's have a look at some of the benefits of JS Modules -

Maintainability:

As we talked about, if our code will be split and well organized, it'll be easy to maintain it. Also, a module is always aimed to be made independent as much as possible so that it can grow and improve independently. And we don't have to change much in our codebase if we make changes in our modules.

Reusability:

With the help of modules, we can reuse our code again and again. All we have to do is to export it from a file, and all other files across the project can import and use it.

Shareability:

As modules aim to be made independent so we can also share them with other developers, they can import them into their project and use them. One of the biggest examples of this is npm. With the help of npm, we can import packages( contains all the files you need for a module ) shared by other developers and use them in our project.


Intro to CommonJS Modules

The CommonJS module system is the standard used in Node.js for working with modules.

CommonJS modules are loaded synchronously and processed in the order the JavaScript runtime finds them.

This system was invented keeping server-side JavaScript in mind and is not suitable for the client-side.

Also, the npm ecosystem is based on the CommonJS module system.

Let's see a small example of how to import and export in CommonJS -

We can export any function, class, variable, etc. by simply using the exports keyword :



// ๐Ÿ“‚ func.js

exports.add = (a, b) => a + b;


Enter fullscreen mode Exit fullscreen mode

Then any Javascript file can import it. The syntax for importing :



const package = require('module-name')


Enter fullscreen mode Exit fullscreen mode

Using this syntax, we can import the module by using the require keyword:



// ๐Ÿ“‚ main.js

const addModule = require('./func.js')
addModule.add(2,4)


Enter fullscreen mode Exit fullscreen mode

Before talking about ES6 modules, let's have a look at the main differences between the CommonJS module system and ES6 modules -

1) CommonJS module system is used for server-side Javascript, while ES6 modules are used for client-side Javascript.

2) CommonJS module system uses the exports keyword for exporting and the require keyword for importing, while ES6 modules use the export keyword for exporting and the import keyword for importing.


ES6 Modules

We've already talked about what modules are, So let's now talk about ES6 modules.

ES6 modules use:

export: to export function,classes, etc.
import: it allows the modules to import exported modules.

Let's see an example -

Here we have three files: index.html, func.js, and main.js



<!-- ๐Ÿ“‚ index.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>modules</title>
    <script type="module" src="./main.js"></script>
  </head>
  <body></body>
</html>


Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ func.js

export const sayHi = (user) => {
  console.log(`Hi!!! ${user}`);
};



Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ main.js

import { sayHi } from "./func.js";

sayHi("Alok"); // Hi!!! Alok


Enter fullscreen mode Exit fullscreen mode

You can see the func.js file is exporting a function ( using export keyword ) named sayHi(), which just console.log out Hi !!! ${user}.

While the main.js is importing the same sayHi() function( using import keyword ) from the func.js file. After that, we have run that function with the input "Alok" which console.log out " Hi !!! Alok ".

We can see that we have not defined the sayHi() function in our main.js file, but still, we can access and use it as now it is imported in our main.js file from the func.js file.

Note: To use modules, we have to specify that our script is a module by using the attribute as we have done in our index.html above :



 <script type="module" src="main.js"></script>


Enter fullscreen mode Exit fullscreen mode

Import and Export

There are different ways to import and export ES6 modules. You can use them as per your need.

Let's talk about them one by one :

Export before declarations -

As we have seen in our previous example, all you have to do is place an export keyword before class, array, function, etc., whatever you want to export.

And then, you can import them by using the import keyword followed by a list of what you want to import in curly braces like import {...}.

Example -



// ๐Ÿ“‚ func.js

//exporting a function
export const sayHi = (user) => {
  console.log(`Hi!!! ${user}`);
};

//exporting a variable
export let person = "Alok";

//exporting an array
export let personArray = ["Alok", "Aman", "Rajan"];

// All are valid


Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ main.js

//importing using a list of what to import
import { sayHi,person,personArray } from "./func.js";


Enter fullscreen mode Exit fullscreen mode

Export Separately -

We can also use the export keyword separately and export using a list of what to export.

And then import them similarly as we have done before.

Example -



// ๐Ÿ“‚ func.js

const sayHi = (user) => {
  console.log(`Hi!!! ${user}`);
};

let person = "Alok";

let personArray = ["Alok", "Aman", "Rajan"];

// exporting all using a list
export { sayHi, person, personArray };


Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ main.js

//importing using a list of what to import
import { sayHi,person,personArray } from "./func.js";


Enter fullscreen mode Exit fullscreen mode

Import *

Till now, we have imported using a list of what to import, but if there's a lot to import, we can import everything as an object using -

import * as

Example -



// ๐Ÿ“‚ func.js

const sayHi = (user) => {
  console.log(`Hi!!! ${user}`);
};

let person = "Alok";

let personArray = ["Alok", "Aman"];

// exporting all using a list
export { sayHi, person, personArray };


Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ main.js

//importing using import * as <obj>
import * as func from "./func.js";

//usage
func.sayHi("Alok");// Hi!!! Alok
console.log(func.person);// Alok
console.log(func.personArray);// ["Alok", "Amanโ€]


Enter fullscreen mode Exit fullscreen mode

Import "as" -

We can also import classes, variables, etc., using a different name. For example - we can import the person variable with another name ( user ) using the as keyword.

Example -



// ๐Ÿ“‚ func.js

const sayHi = (user) => {
  console.log(`Hi!!! ${user}`);
};

let person = "Alok";

let personArray = ["Alok", "Aman"];

// exporting all using a list
export { sayHi, person, personArray };


Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ main.js

//importing using "as"
import { sayHi as Hi, person as user, personArray } from "./func.js";

//usage
Hi("Alok"); //Hi!!! Alok
console.log(user); //Alok
console.log(personArray); //["Alok", "Aman"]


Enter fullscreen mode Exit fullscreen mode

Export "as" -

Similarly, you can export with a different name using the as keyword.

Example -



// ๐Ÿ“‚ func.js

const sayHi = (user) => {
  console.log(`Hi!!! ${user}`);
};

let person = "Alok";

let personArray = ["Alok", "Aman"];

//exporting using "as"
export { sayHi as Hi, person as user, personArray };


Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ main.js

//importing using a list
import { Hi, user, personArray } from "./func.js";

//usage
Hi("Alok"); //Hi!!! Alok
console.log(user); //Alok
console.log(personArray); //["Alok", "Aman"]


Enter fullscreen mode Exit fullscreen mode

Export default -

We can make any export a default one by using the default keyword.

Generally, developers keep a single export in a module to keep the code clean, and in such a case, when we have a single export, we can use default export.

If we have a default export, then we can import it directly without using the curly braces { }.

Example -



// ๐Ÿ“‚ func.js

const sayHi = (user) => {
  console.log(`Hi!!! ${user}`);
};

//exporting using default
export default sayHi;


Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ main.js

//importing without { }
import sayHi from "./func.js";

sayHi("Alok"); // Hi!!! Alok


Enter fullscreen mode Exit fullscreen mode

Notice while importing sayHi() we are directly using sayHi, not { sayHi }.

Note: We can also mix default export with named export, but a module can have only one default export as shown :



// ๐Ÿ“‚ func.js

const sayHi = (user) => {
  console.log(`Hi!!! ${user}`);
};

let person = "Alok";

let personArray = ["Alok", "Aman"];

//exporting using default
export default sayHi;

//exporting using list
export { person, personArray };


Enter fullscreen mode Exit fullscreen mode


// ๐Ÿ“‚ main.js

//importing without { }
import sayHi from "./func.js";

//importing using a list
import { person, personArray } from "./func.js";

//usage
sayHi("Alok"); //Hi!!! Alok
console.log(person); //Alok
console.log(personArray); //["Alok", "Aman"]


Enter fullscreen mode Exit fullscreen mode

But as we talked about, developers generally keep only one export in a module and do not mix them to keep the code clean.


Some important features of ES6 Modules

Always "use strict"

Modules always use strict, by default.

Assigning to an undeclared variable will give an error.

Example -



<script type="module">
  a = 5; {/* error */}
</script>


Enter fullscreen mode Exit fullscreen mode

Module-level scope

A module can't access the top-level variables and functions of another module.

Example -



<script type="module">
  {/* scope of person is only this module script */}
  let person = "Alok";
</script>

<script type="module">
   alert(person);{/* Error: person is not defined */}
</script>


Enter fullscreen mode Exit fullscreen mode

A module code is executed only the first time imported

If multiple modules are importing a module ( for example, func.js ), then only during the first time import it will be executed and given to all importers.

"this" is undefined

In modules, top-level this is undefined.

Example -



<script>
  alert(this); {/* global object */}
</script>

<script type="module">
  alert(this); {/* undefined */}
</script>


Enter fullscreen mode Exit fullscreen mode

Note : Thanks Seijinx for the info - "ES modules are not supported in IE11. You still need to rely on bundlers in that case."


I have tried to keep it simple and precise, thanks for reading it till last, and if you find any typo/error please report it to me so that I can correct it ๐Ÿ™‚

If you find this useful then you can share it with others :)

Feel free to drop a Hi and let's chat ๐Ÿ‘‹๐Ÿ‘‹๐Ÿ‘‹


Read other blogs in the series

๐Ÿ‘ˆGetting Started with JavaScript Classes

โ€ƒโ€ƒโ€ƒโ€ƒโ€ƒโ€ƒโ€ƒโ€ƒโ€ƒโ€ƒโ€ƒโ€ƒโ€ƒGetting Started with JavaScript Promises ๐Ÿ‘‰

Top comments (31)

Collapse
 
hygull profile image
Rishikesh Agrawani

Yes, really a great article. I appreciate your fully detailed explanation with excellent examples. I found here what I wanted to know. Really I appreciate it.

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks Rishikesh, I'm glad it was useful :)

Next is on JS Promises, and I'm also planning to compile all these ES6 concepts articles into an e-book, stay tuned ๐Ÿ™‚

Collapse
 
hygull profile image
Rishikesh Agrawani

Ok great, thanks!๐Ÿ˜Š

Collapse
 
douglasvdmerwe profile image
Douglas

Thanks @thecoollearner for the clear and concise post.

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks Douglas :)

You can read the other articles in this series, I'm sure you'll like them too ๐Ÿ™‚

Collapse
 
kevinleebuchan profile image
KevinLeeBuchan

This helped solidify a concept that is new to me.

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks Kevin, I'm glad it was helpful :)

Collapse
 
rameshkmunjal profile image
RAMESH KUMAR MUNJAL

Thank you Alok for such a good blog. I used module in React but did not have understanding about it. Now I think I can use it in simple js files also.

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks for reading Ramesh, glad you liked it :)

Next blog is on JS Promises, stay tuned ๐Ÿ™‚

Collapse
 
candersson1 profile image
candersson1

Thank you Alok. This really helped me understand this concept better. I use it often but have often wondered why sometimes I use {} in my imports and sometimes not. It all makes sense now!

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks candersson1 for reading :)

glad it helped, stay tuned for more such articles ๐Ÿ™‚

Collapse
 
timhuang profile image
Timothy Huang

Great! Thank you.

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks for reading, Timothy :)

Collapse
 
erikson profile image
Erikson

Nice article! Easy to understand with examples. :bd

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks Erikson :)

I'll sure come up with more such articles, stay tuned ๐Ÿ™‚

Collapse
 
sriramanam profile image
Raman Jha

Module explained in a simplified manner !! Good .

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks Raman :)

Collapse
 
silvesterwali profile image
silvesterwali

awesome bro

Collapse
 
thecoollearner profile image
Alok Kumar

Thanks silvesterwali :)

Collapse
 
seijinx profile image
Seijinx

Great article!! Very useful.

It might be useful to add that, sadly (again!) ES modules are not supported in IE11. You still need to rely on bundlers in that case.

Collapse
 
thecoollearner profile image
Alok Kumar • Edited

Thanks Seijinx ๐Ÿ™

I've added it as a note at last of the article :)