JavaScript Modules allow you to break your code into separate, reusable files.
Each module has its own scope, which helps in:
- Avoiding global variable pollution
- Improving code organization
- Making code reusable and maintainable
- Collaborating on large projects
// main.js - Everything in one file
let count = 0;
let user = {};
let product = {};
function increment() { }
function decrementCount() { }
function getUser() { }
function updateUser() { }
function getProduct() { }
function updateProduct() { }
// Messy, hard to maintain, name conflicts possibleProject/
βββ counter.js (counter logic)
βββ user.js (user logic)
βββ product.js (product logic)
βββ main.js (combines everything)
Each file is focused and reusable!
// math.js
module.exports = { add, subtract };
// app.js
const math = require('./math');Used in: Node.js, older JavaScript projects
// math.js
export const add = (a, b) => a + b;
// app.js
import { add } from './math.js';Used in: Modern JavaScript, browsers, modern Node.js
ES Modules are the modern standard and recommended approach.
You can export multiple things from a file.
// math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
export const multiply = (a, b) => a * b;
export function divide(a, b) {
return a / b;
}Multiple exports from one file β
Only one default export per file.
// greet.js
export default function greet(name) {
return `Hello, ${name}`;
}Or with variable:
// config.js
const API_URL = "https://api.example.com";
export default API_URL;// constants.js
export const PI = 3.14159;
export const E = 2.71828;
export let count = 0;
export function increment() {
count++;
}// app.js
import { add, subtract } from './math.js';
console.log(add(2, 3)); // 5
console.log(subtract(5, 2)); // 3Import specific items β
// app.js
import greet from './greet.js';
console.log(greet("Sandhya")); // Hello, SandhyaImport the default β
// app.js
import * as math from './math.js';
console.log(math.add(2, 3)); // 5
console.log(math.subtract(5, 2)); // 3
console.log(math.multiply(4, 5)); // 20Import all exports as object β
// app.js
import { add as sum, subtract as diff } from './math.js';
console.log(sum(4, 5)); // 9
console.log(diff(10, 3)); // 7Avoid naming conflicts β
export const PI = 3.14;
export const E = 2.71;
export default function square(x) {
return x * x;
}import square, { PI, E } from './utils.js';
console.log(square(4)); // 16
console.log(PI); // 3.14
console.log(E); // 2.71Import both default and named β
File: user.js
export class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
getInfo() {
return `${this.name} (${this.email})`;
}
}
export function validateEmail(email) {
return email.includes("@");
}
export const defaultUser = {
name: "Guest",
email: "guest@example.com"
};File: app.js
import { User, validateEmail, defaultUser } from './user.js';
const user = new User("Sandhya", "sandhya@example.com");
console.log(user.getInfo()); // Sandhya (sandhya@example.com)
console.log(validateEmail("test@gmail.com")); // true
console.log(validateEmail("invalid")); // falseFile: api.js
const BASE_URL = "https://jsonplaceholder.typicode.com";
export async function fetchPosts() {
const response = await fetch(`${BASE_URL}/posts`);
return await response.json();
}
export async function fetchUser(id) {
const response = await fetch(`${BASE_URL}/users/${id}`);
return await response.json();
}
export async function createPost(data) {
const response = await fetch(`${BASE_URL}/posts`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data)
});
return await response.json();
}File: main.js
import { fetchPosts, fetchUser, createPost } from './api.js';
async function main() {
const posts = await fetchPosts();
console.log("Posts:", posts);
const user = await fetchUser(1);
console.log("User:", user);
const newPost = await createPost({ title: "New", body: "Content", userId: 1 });
console.log("Created:", newPost);
}
main();File: helpers.js
export function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}
export function reverseString(str) {
return str.split('').reverse().join('');
}
export function removeDuplicates(arr) {
return [...new Set(arr)];
}
export const mathUtils = {
sum: (a, b) => a + b,
product: (a, b) => a * b,
power: (a, b) => Math.pow(a, b)
};File: script.js
import { capitalize, reverseString, removeDuplicates, mathUtils } from './helpers.js';
console.log(capitalize("hello")); // Hello
console.log(reverseString("javascript")); // tpircsavaj
console.log(removeDuplicates([1, 2, 2, 3])); // [1, 2, 3]
console.log(mathUtils.sum(5, 3)); // 8
console.log(mathUtils.power(2, 8)); // 256project/
βββ index.html
βββ src/
β βββ main.js (entry point)
β βββ modules/
β β βββ user.js (user logic)
β β βββ product.js (product logic)
β β βββ api.js (API calls)
β β βββ utils.js (utility functions)
β βββ components/
β βββ navbar.js (navbar component)
β βββ header.js (header component)
β βββ footer.js (footer component)
βββ package.json
Modules can import from other modules:
File: helpers.js
export const add = (a, b) => a + b;File: calculator.js
import { add } from './helpers.js';
export function addThree(a, b, c) {
return add(add(a, b), c);
}File: main.js
import { addThree } from './calculator.js';
console.log(addThree(1, 2, 3)); // 6// β
CORRECT - Include .js
import { add } from './math.js';
// β INCORRECT - Will fail in browser
import { add } from './math';// user.js
let message = "Private"; // Only in this file
export const name = "John"; // Exported, accessible
// app.js
import { name } from './user.js';
console.log(name); // "John" β
console.log(message); // ReferenceError β// logger.js
console.log("Module loaded");
// app.js
import './logger.js'; // "Module loaded" (first time)
import './logger.js'; // Nothing (cached, runs only once)<!DOCTYPE html>
<html>
<head>
<title>My App</title>
</head>
<body>
<h1>JavaScript Modules Demo</h1>
<!-- Type "module" is required -->
<script type="module" src="src/main.js"></script>
</body>
</html>Important: Always use type="module" attribute!
For production, use bundlers:
npm install webpack webpack-cli --save-devnpm create vite@latest my-app -- --template vanillanpm install -g parcel-bundler
parcel src/index.html// a.js
import { funcB } from './b.js';
export function funcA() {
return funcB();
}
// b.js
import { funcA } from './a.js'; // β Circular!
export function funcB() {
return funcA();
}Fix: Restructure code to avoid circular imports.
// β WRONG
import { add } from './math';
// β
CORRECT
import { add } from './math.js';// utils.js
function add(a, b) {
return a + b;
}
// β Not exported!
// app.js
import { add } from './utils.js'; // Error: add not foundFix:
// utils.js
export function add(a, b) { // β
Now exported
return a + b;
}π Modern JavaScript module system using import/export for code organization.
π Default: One per file, imported without braces. Named: Multiple per file, imported with braces.
π Use import * as name from './file.js'
π Yes, in the same file.
π Use import { original as alias } from './file.js'
π No, they run once and are cached. Subsequent imports use cached version.
π Better organization, reusability, avoiding global scope pollution, easier maintenance.
- β Named Export: Export multiple, import with braces
- β Default Export: One per file, import without braces
- β Combine Both: Use default + named together
- β
Aliasing: Rename imports with
as - β
Namespace: Import everything with
import * as - β Scope: Each module has own scope (encapsulation)
- β Cached: Modules run once, cached for future imports
- β .js Extension: Required in browser (optional in Node.js)
- Use meaningful module names
- Keep modules focused on single responsibility
- Export only what's needed
- Use named exports for related functions
- Use default export for main feature
- Organize modules in logical folders
- Avoid circular dependencies
- Document module exports
- Use bundlers for production
- Keep module dependencies simple
| Feature | CommonJS | ES Modules |
|---|---|---|
| Export | module.exports |
export |
| Import | require() |
import |
| Async | Sync only | Async |
| Used in | Node.js | Modern JS, Browsers |
| Status | Legacy | β Standard |
Happy Coding! π
Master modules and your codebase will be organized, scalable, and maintainable!