DEV Community

Cover image for ES Module
Srishti Prasad
Srishti Prasad

Posted on

ES Module

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:

  1. keeping file the extension as .mjs instead of .js
  2. 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}`);
    }
}
Enter fullscreen mode Exit fullscreen mode

If we want to import entities from a module we can use the import keyword

import * as loggerModule from './logger.js'
console.log(loggerModule)
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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')
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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!";
Enter fullscreen mode Exit fullscreen mode

Import specific named exports from the module

import { greet, farewell } from './myModule.js';
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Import the default export from the module

import greet from './myDefaultModule.js';
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

Import the default export and named exports

import greet, { greeting, farewell } from './myCombinedModule.js';
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
ddebajyati profile image
Debajyati Dey

So, there is actually no benefit of writing common JS syntax over ES Module syntax?

Collapse
 
srishtikprasad profile image
Srishti Prasad

@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.

Collapse
 
ddebajyati profile image
Debajyati Dey

Thanks for clarifying ☺️