A Deep Dive into ES6 Modules

A Deep Dive into ES6 Modules

posted 3 min read

A Deep Dive into ES6 Modules

In 2025, as a web developer, knowledge of ES6+ syntax is no longer optional. In this article, we'll take a closer look at ES6 Modules.

What is a Module?

A module in JavaScript is simply a file containing code that you would like to include in another file. For instance, let's say we define a sum function in a file called math.js, we can include this file in another file as a module.

// math.js
function sum(x, y) {
    return x + y;
}
// app.js
let result = sum(1, 2);
console.log(result);

Prior to ES6 Modules, to use a module, you had to include the file before the file that uses it so the browser would load it first.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="math.js"></script>
    <script src="app.js"></script>
</body>
</html>

And if you wanted to use modules outside a browser environment, like in Node.js, you would use the CommonJS syntax.

// math.js
function sum(x, y) {
    return x + y;
}
module.exports = sum;
// app.js
const sum = require('./math.js');

What Are ES Modules?

ES6 Modules (ESM) are part of the standard defined in the ECMAScript 6 specification. They provide a standardized way of exporting and importing variables, functions, classes, and other custom code from files.

Let's rewrite our example using ES Modules syntax:

// math.js
function sum(x, y) {
    return x + y;
}

export default sum;

And in app.js:

// app.js
import sum from './math.js';

let result = sum(1, 2);
console.log(result);

Named Exports and Imports

Besides default exports, ES Modules allow named exports, which let you export multiple functions or variables from a single file.

// math.js
export function sum(x, y) {
    return x + y;
}

export function subtract(x, y) {
    return x - y;
}

And in app.js, we can import specific functions:

// app.js
import { sum, subtract } from './math.js';

console.log(sum(3, 2)); // 5
console.log(subtract(5, 2)); // 3

Importing Everything as an Object

Instead of importing specific functions, you can import all exported values as an object:

// app.js
import * as math from './math.js';

console.log(math.sum(3, 2)); // 5
console.log(math.subtract(5, 2)); // 3

Using ES Modules in the Browser

To use ES Modules in the browser, you need to add type="module" to the script tag:

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

Unlike traditional scripts, ES Modules are loaded in strict mode by default, and they support deferred loading, meaning they wait for the DOM to load before execution.

ES Modules in Node.js

ES Modules are also supported in Node.js using .mjs files or by adding "type": "module" in your package.json.

Using .mjs

// math.mjs
export function sum(x, y) {
    return x + y;
}
// app.mjs
import { sum } from './math.mjs';
console.log(sum(4, 2));

Run it using:

node app.mjs

Using package.json

If you prefer using .js files, add the following to package.json:

{
  "type": "module"
}

Now you can use ES Modules in .js files without requiring .mjs.

Dynamic Imports

ES Modules also support dynamic imports using import(), which allows loading modules on demand.

// app.js
async function loadMath() {
    const math = await import('./math.js');
    console.log(math.sum(6, 3));
}

loadMath();

This is useful for code splitting and lazy loading.

ES Modules vs CommonJS

Feature ES Modules (ESM) CommonJS (CJS)
Syntax import / export require() / module.exports
Default Exports export default module.exports = ...
Named Exports export { func } exports.func = ...
Async Behavior Always async Synchronous
Usage in Browsers Yes No
Usage in Node.js Yes (with .mjs or type: module) Yes (default)

Conclusion

ES Modules bring a more structured and modern approach to modularization in JavaScript. While CommonJS is still widely used in Node.js, ES Modules are now the standard for both frontend and backend development. Adopting ES6 Modules ensures better compatibility, maintainability, and future-proofing of your JavaScript projects.

Share your thoughts inthe comments below.

I'm a full stack JS/TS developer, feel free to reach out to me for next project

If you read this far, tweet to the author to show them you care. Tweet a Thanks

nice article! You did an awesome job breaking down ES6 Modules and the differences between ESM and CommonJS. Quick question though—when using import() for dynamic imports, do you think it has any performance overhead in large apps compared to static imports? Would love to hear your thoughts on that. Keep it up!

Thanks ❤. I appreciate.

Dynamic imports actually help to reduce overhead because that way, you only import the module when you need it. Say for example, your webpage has an animation that relies on Phaser.js nut that animation is on another page, dynamic imports allow you to load only the scripts necessary for the current page thereby reducing blocking time used to execute JavaScript.
It's what frameworks like Next.js use to implement code splitting and lazy loading under the hood.

More Posts

A deep dive into Next.js Rendering for Performance and SEO

harshit_rwt - Feb 8

What Happens When You Type a URL Into Your Browser? (Interview Question Guide)

Khiilara - Jan 2

JavaScript to Python Mastery Guide: Syntax, Data Structures, OOP, Modules, Async...

Hossam Gouda - Mar 30

A Deep Dive into Decentralized Provenance Tracking and Smart Contracts

Web3Dev - Mar 28

Titans: A Deep Dive into Next-Generation AI Memory Architecture

Mohit Goyal - Feb 5
chevron_left