DEV Community

Cover image for JavaScript Modules
Kiran Raj R
Kiran Raj R

Posted on • Updated on

JavaScript Modules

A module is a simple JavaScript file. As the application become bigger the code become complex and it might contain thousands of line, so maintaining the code become difficult. Modules helps in dividing the codes into multiple block of codes, which help to separate functionality into multiple files. Modules help to maintained code and help in code reusability. A module may contain a class, a functions or code that perform a specific task. Modules can communicate between each other like they are in one file if we wish to be like that. We can also specify what code should be visible to the outside. Module gives us more control to our code.

Modules use export keyword to label variables or functionality that should be made available to the outside world. Import keywords are used to import variables or functionality to a module from other modules.

Example

Filename: Greet.js
export function greet(user){
    console.log(`Hello my dear ${user}`);
}
Enter fullscreen mode Exit fullscreen mode
FileName: Main.js
import {greet} from './Greet.js';
console.log(greet);

greet("kiran");           //Hello my dear kiran

//Output of console.log(greet);
//ƒ greet(user){ console.log(`Hello my dear ${user}`);}

Enter fullscreen mode Exit fullscreen mode

In the above code snippet we export the greet function from Greet.js using export keyword and is imported to Main.js using import keyword.

Modules work in strict mode by default. Each module has it's own top level scope. In a module top level this is undefined.

Let's look at another example

Filename: module_exp.js
let name = {fname : "Kiran", lname: "raj", initials: "R"};
function dispName(name){
    console.log(`${name.fname} ${name.lname} ${name.initials}.`)
}
export{name, dispName};
Enter fullscreen mode Exit fullscreen mode
Filename: main.js
import {name, dispName} from './module_exp.js'
console.log(name);
dispName(name);

// Output {fname: "Kiran", lname: "raj", initials: "R"} 
          Kiran raj R.
Enter fullscreen mode Exit fullscreen mode

If there are multiple variables(variable, functions, classes...) to export or import we can use {}. For example, to export variable a, b and c, we can write it as export {a, b, c};. Same can be done for import, import {a, b, c} from 'file.js'.

We can use * to import everything that the file labeled to export, import * from 'file.js'.

We can use as to import or export using alias name.
import {displayName as n, printMessage as msg} from './file.js'
export {displayName as n, printMessage as msg} from './file.js'

We can export variables using export default keyword, the variable exported with default keyword can be import without {}. Normally only one item can be exported as default. Default variable can be imported with any name.

Filename: module_exp.js
export default function dispName(){
    console.log("kiran raj")
}

import disp from './module_exp.js'
Enter fullscreen mode Exit fullscreen mode

Summary

Export

export variableA // export single variable
export {variableA, variableB, ...} // export multiple variables
export variableA as a // export variable using alias
export default variableA // export variable as default

Import

import { variableA} from "module" // import single variable
import {varA, varB,..} from "module" // import multiple variables

import {variable as a} from "module" //import variable using alias
import * from "module" // import all variables from a module

Dynamic import

export function func1() {}
export default function dispName() {} 
export default const PI = 3.14;
export default 3.14;

import {fun1, fun2 } from './module.js';
import * from './module.js';
import {fun1 as f} from './module.js';
Enter fullscreen mode Exit fullscreen mode

The above shown exports and imports are static, in static export / import the module path must be "primitive string". Static import syntax cause the module to be evaluated at the load time only. We can use dynamic import if we like to load a module on demand. The import("moduleName") will loads the module and return a promise. If the loading is successful then the promise returned will resolve to an object which have all the exports, else promise will provide an error reason that should be handled. The below example use a catch statement to do the error handling. Static import is the preferred one. Dynamic imports work like regular scripts ,type="module" is not required.

import('/module.js')
    .then((mod) => {// code to execute})
    .catch((err) =>{// code to handle error})
Enter fullscreen mode Exit fullscreen mode

Re-exporting / Aggregating

Consider a situation were we have a large number of modules in an application and we want certain modules to be accessed by users but we don't want anyone from the outside to know what modules we have or our module structure. As we have large number of modules, maintaining will be a tedious task. An idea is to create a single point of entry for outsiders, a module that will import the necessary modules that are needed by the users and export those modules, so the user can access it. All the user required modules are available under one module. Re-export help in this, it will import the modules and immediately export those modules.The module in which re-exports occur does not have access to the modules that was re-exported.

Syntax : export <module,...> from "module"

export {fun1, fun2 } from 'module.js';

// The above code is equivalent to

import { fun1, fun2 } from 'module.js';
export { fun1, fun2 };
Enter fullscreen mode Exit fullscreen mode

The default exports need to be handled separately.

export { default as fun1, fun2 } from 'module.js';
                    //or
export { default, fun2 } from 'module.js';

//The above code is equivalent to

import { default as fun1, fun2 } from 'module.js';
export { fun1 as default, fun2 };
Enter fullscreen mode Exit fullscreen mode

An example of dynamic loading using async await

//File name : module_imp.js
async function getModule() {
    let modules = await import('./module_exp.js');
    modules.dispName(modules.name); //Kiran raj R.
    modules.default();              //Success
}
getModule();

//File name : module_exp.js
export let name = {fname : "Kiran", lname: "raj", initials: "R"};
export function dispName(name){
    console.log(`${name.fname} ${name.lname} ${name.initials}.`)
}

export default function(){
    console.log("Success");
}

// Output
Kiran raj r
Success
Enter fullscreen mode Exit fullscreen mode

Another example of dynamic import

// File name : module_exp.js
export let name = {fname : "Kiran", lname: "raj", initials: "R"};
export default function dispName(name){
    console.log(`${name.fname} ${name.lname} ${name.initials}.`)
}

// Filename : module_imp.js
import ( './module_exp.js').then((result)=> {
    console.log("Module loaded");
    let name = result.name;
    console.log(name.lname, name.fname);
    result.default(name)
});

// Output
Module loaded
raj Kiran
Kiran raj R.
Enter fullscreen mode Exit fullscreen mode

Top comments (8)

Collapse
 
raddevus profile image
raddevus

This is a great article on Modules. I am a long-time dev (with C++ / OOP background) so seeing Modules in JavaScript is a step in the right direction. However, I've often been confused by explanations of how to use export import.
This was written up nicely and provides value for me. Couple of things I'm wondering about: 1) which version(s) of JS does this work in? 2) is this the same syntax you would use in NodeJS?
Thanks

Collapse
 
kiranrajvjd profile image
Kiran Raj R
  1. ES modules are defined in the ES2015 specification. Import And exports are not supported in Internet explorer, for browser compatibility you can use "caniuse.com".
  2. Modules was partially supported from Node.js v8.5 , CommonJS modules are used in node by default which do the same functions of ECMAScript module . Currently node support ECMAScript module fully. You can find the syntax in node documentation. Hope this will help you to some extent, thank you for asking the questions.
Collapse
 
evankapantais profile image
Evan Kapantais

I think you forgot to mention that vanilla JS doesn't support ES6 imports / exports without the use of a bundler like Babel or Webpack.

Collapse
 
kiranrajvjd profile image
Kiran Raj R

Yes, and if i am not mistaken, we can use it without babel by setting the type="module" in the script tag, right?
ex: <script src="./file.js" type="module"></script>
I think I need to dig deep into that, thanks for pointing out.
Appreciated

Collapse
 
thevinitgupta profile image
Vinit Gupta

Is this really possible?
I have been thinking of using this but couldn't figure out the right way.

Collapse
 
kiranrajvjd profile image
Kiran Raj R

Thank you, appreciated

Collapse
 
pupdoggify profile image
Comment marked as low quality/non-constructive by the community. View Code of Conduct
Paul Davis

Don't just thank Niki, you should make the edit as per the suggestion to make it easier to read.

Thread Thread
 
kiranrajvjd profile image
Kiran Raj R

i was going to.. thought of doing in morning

Some comments may only be visible to logged-in visitors. Sign in to view all comments.