Skip to main content

Modules in JavaScript (ES Modules)

As your application grows in size, putting thousands of lines of code into a single .js file becomes impossible to maintain.

Modern JavaScript solves this with Modules. A module allows you to separate your code into multiple smaller, purpose-specific files, and import pieces of code from one file to another as you need them.

For this to work in browsers, the <script> tags in HTML must declare type="module", or more frequently, you will use bundlers like Vite, Webpack, or frameworks like React/Next.js or NodeJS.

Named Exports (export)

You can export multiple functions, variables, or classes from a single file. You have to use the exact name when importing them.

File: math.js

// Exporting at the time of declaration (Usually pure math utilities)
export const pi = 3.14159;

export function add(a, b) {
return a + b;
}

const subtract = (a, b) => a - b;
export { subtract }; // Export after declaring

File: main.js (Consuming the math)

// Using 'import { exact names } from "./path"'
import { add, pi, subtract } from './math.js';

console.log(`The value of PI is ${pi}`);
console.log(`2 + 2 = ${add(2, 2)}`);

Default Export (export default)

Used when a file has a single main function or class to export (very common in React components or main classes). There can only be ONE default per file. It does not require using curly braces {} when importing, and in fact you can rename it freely when importing it.

File: User.js

export default class User {
constructor(name) {
this.name = name;
}

greet() {
console.log(`Hello, I am ${this.name}`);
}
}

// Note: You cannot directly export variables declared with let/const as default on the same line.

File: app.js (Consuming the class)

// No braces because it is a 'default export'. 
// "UserClass" is an arbitrary alias that I chose here.
import UserClass from './User.js';

const newUser = new UserClass("Anna");
newUser.greet(); // Hello, I am Anna

Combining Both

It is possible (and very useful) for a file to have a default export AND named exports at the same time.

/* File: utils.js */
export const helperOne = "Data 1";
export const helperTwo = "Data 2";
export default function mainFunction() { ... }

/* File: app.js */
import defaultFunc, { helperOne, helperTwo } from './utils.js';

Separating responsibilities through ECMAScript modules (ESM) is the fundamental basis of how we organize the architecture of robust JS projects today.