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}`);
}
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}`);}
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};
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.
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'
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';
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})
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 };
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 };
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
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.
Top comments (8)
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
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.
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
Is this really possible?
I have been thinking of using this but couldn't figure out the right way.
Thank you, appreciated
Don't just thank Niki, you should make the edit as per the suggestion to make it easier to read.
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.