This blog is continuation with previous, The Module System commonJS module. In this blog post I'll be covering ES Module and difference between ESM and CommonJS Module.
ES Module System
How to tell Node js interpreter to consider a given module as ES module rather than CommonJs module:
- keeping file the extension as
.mjs
instead of.js
- adding
"type":"module"
a field in nearest parent package.json
Named exports & imports
Note - the ES module uses the singular word export as opposed to the plural (exports and module.exports) used by commonJS module.
In an ES module everything is private by-default and only exported entities are publicly accessible from other modules.
The export keyword can be used in front of the entities that we want to make available to the module users.
//export a function
export function log(message){
console.log(message);
}
//export a constant
export const DEFAULT_LEVEL='info'
//export an object as 'LEVELS'
export const LEVELS={
error:0,
debug:1,
warn:2,
data:3,
info:4
}
//export class as logger
export class logger{
constructor(name){
this.name=name;
}
log(message){
console.log(`${this.name} ${message}`);
}
}
If we want to import entities from a module we can use the import keyword
import * as loggerModule from './logger.js'
console.log(loggerModule)
PS: We can use ES module syntax (i.e., import and export statements) in Node.js with files that have a
.js
extension, but you need to make sure Node.js is configured to support ES modules.
In ES module , it is important to specify extension of imported modules unlike CommonJS module.
If we are using a large module,most often we don't want to import all of its functionality,but only one or few entities.
import {log} from './logger.js'
If we want to import more than one entity, this is how we would do that:
import {log,logger} from './logger.js'
console.log('hello world')
gives error :
SyntaxError: Identifier 'log' has already been declared
if this type of import statement, the entities imported into the current scope, so there is a risk of a name clash.
We can tackle in this way
import {log as log2} from './logger.js'
here we are changing the original name and then using this in module.
Named Export
Named exports allow you to export multiple values from a module. Each value is exported with a specific name, and these names must be used when importing.
export const greeting = "Hello, World!";
export function greet(name) {
return `${greeting}, ${name}`;
}
export const farewell = "Goodbye!";
Import specific named exports from the module
import { greet, farewell } from './myModule.js';
Key Points
- Multiple exports can be defined.
- Import statements must use the exact names of the exported values.
- Named exports can be imported selectively.
Default Exports
Default exports are used to export a single primary value or functionality from a module. This value is considered the default export and does not need to be imported with a specific name.
// Define a function
function greet(name) {
return `Hello, ${name}`;
}
// Export the function as the default export
export default greet;
Import the default export from the module
import greet from './myDefaultModule.js';
Key Points:
- Only one default export is allowed per module.
- The imported name can be chosen freely by the importer.
- Simplifies importing when the module has a single primary export.
Mixed export
A module can have both named exports and a default export.
// Define variables and functions
const greeting = "Hello, World!";
function greet(name) {
return `${greeting}, ${name}`;
}
const farewell = "Goodbye!";
// Export named and default exports
export { greeting, farewell };
export default greet;
Import the default export and named exports
import greet, { greeting, farewell } from './myCombinedModule.js';
Although, I have explained various methods to import & export in order to explain various way but a good practice is exporting a single object that encapsulates all exports, it improve maintainability and readability. This method allows developers to see all available exports in one place, reducing the risk of incorrect usage and making the module's API more predictable.
ES Module & commonJS diffrence
ESM runs in strict mode
- ES Module uses strict mode implicitly in strict mode, meaning we don't have to explicitly add the
"use strict"
statement at beginning of every file. So, we have only two options either strict mode or non-strict mode. But using strict mode is definitely safer execution as it doesn't allow developer to use undeclared variable.
There are yet many things to learn application of "use strict", will cover in separate blog.
That's it for now! Thanks for reading till here. Hope you enjoy learning this and cleared some common doubts.
Let me know in comment , what did you liked in this blog any suggestion is welcome.
If you have any query don't hesitate to ask me in comments, I'll try my best to answer to the best of my knowledge ❤️.
Top comments (3)
So, there is actually no benefit of writing common JS syntax over ES Module syntax?
@ddebajyati , So there are some benefits offered by commonJS module, but most of them are already covered in ES module . Some of benefits -
It is loaded and executed immediately, which can be beneficial for certain types of applications that need immediate access to the module's functionality. Whereas imports in ES module are asynchronous in nature.
But asynchronous nature has its own benefits , it won't block your code execution
commonJs module is simple and easy to use
There is no major benefit of using commonJS. If you are starting to build a project from scratch I would suggest you to go with ES module, it offers variety of benefits over commonJS.
Thanks for clarifying ☺️