As JavaScript applications grow, keeping everything inside one huge JavaScript file can quickly become difficult to manage.
Imagine a project with hundreds or thousands of lines of code containing:
User authentication
Shopping cart logic
API functions
Form validation
Utility functions
UI code
Putting everything into one file would make the project messy.
This is where JavaScript modules come in.
What is a JavaScript Module?
A module is a JavaScript file that contains code which can be exported and imported by other JavaScript files.
Instead of putting everything into one file, we can split our application into smaller, focused files.
For example:
project/
│
├── app.js
├── math.js
├── users.js
└── utils.jsEach file can contain code related to a particular responsibility.
math.js → Mathematical functions
users.js → User-related code
utils.js → Utility functions
app.js → Main applicationThis makes our code easier to understand, maintain, and reuse.
Why Do We Need Modules?
Without modules, a large application might look like this:
app.js
├── Login code
├── User code
├── Payment code
├── API code
├── Validation code
├── Utility functions
└── UI codeAs the project grows, finding and modifying code becomes difficult.
With modules:
auth.js → Authentication
users.js → Users
payments.js → Payments
api.js → API calls
validation.js → Validation
utils.js → UtilitiesEach file has a clearer purpose.
Some major benefits are:
Better code organization
Code reuse
Easier maintenance
Better separation of responsibilities
Avoiding unnecessary global variables
Exporting Code
Before another file can use something from a module, we need to export it.
Suppose we have a file called math.js:
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}Here, both functions are exported.
Now another JavaScript file can use them.
Importing Code
Suppose our main file is app.js.
We can import the functions like this:
import { add, subtract } from "./math.js";
console.log(add(10, 5));
console.log(subtract(10, 5));Output:
15
5The basic idea is:
math.js
↓
export
↓
app.js
↓
import
↓
Use the functionsNamed Exports
When we export specific values by name, they are called named exports.
For example:
export const pi = 3.14159;
export function square(number) {
return number * number;
}We can import them:
import { pi, square } from "./math.js";
console.log(pi);
console.log(square(5));Output:
3.14159
25The names used during import must correspond to the exported names unless we rename them.
Renaming Named Imports
We can rename an imported value using as.
import { square as calculateSquare } from "./math.js";
console.log(calculateSquare(5));Here:
square
↓
calculateSquareThe original exported function is still called square; we've simply given it another local name in this file.
Exporting at the End
We don't have to put export directly before every declaration.
For example:
function add(a, b) {
return a + b;
}
function subtract(a, b) {
return a - b;
}
export { add, subtract };This does the same thing as:
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}Choose whichever style makes the module easier to read.
Default Export
A module can also have one default export.
For example:
export default function greet(name) {
return `Hello, ${name}!`;
}We can import it without curly braces:
import greet from "./greet.js";
console.log(greet("John"));Output:
Hello, John!Notice the difference:
// Named import
import { add } from "./math.js";
// Default import
import greet from "./greet.js";Renaming a Default Import
Default imports can be given any local name.
For example:
import sayHello from "./greet.js";This is perfectly valid even if the function was originally named greet.
That's because a module can have only one default export, and the importing file chooses the local name.
Named vs Default Exports
The difference is important:
Named Export | Default Export |
|---|---|
Can have multiple | One default export per module |
Uses | Doesn't use |
Import name normally matches export name | Import name can be chosen |
|
|
|
|
For example:
// Named
export function add() {}// Import
import { add } from "./math.js";And:
// Default
export default function add() {}// Import
import add from "./math.js";Importing Everything
We can import all named exports from a module using *.
For example:
import * as math from "./math.js";
console.log(math.add(10, 5));
console.log(math.subtract(10, 5));Here, math becomes an object containing the exported members.
Conceptually:
math
├── add
└── subtractThis can be useful when a module contains a group of related functions.
Modules in HTML
When using JavaScript modules directly in a browser, we need to tell the browser that the script is a module.
<script type="module" src="app.js"></script>Without type="module", browser JavaScript won't treat the file as an ES module.
Then app.js can import another module:
import { add } from "./math.js";
console.log(add(10, 20));And math.js can contain:
export function add(a, b) {
return a + b;
}Module File Paths
When importing local modules in the browser, it's common to specify the file path explicitly:
import { add } from "./math.js";Here:
./math.jsmeans math.js is in the same directory.
If it's inside a folder:
import { add } from "./utils/math.js";And:
../math.jsmeans the file is in the parent directory.
Modules Have Their Own Scope
One major benefit of modules is that variables declared inside a module aren't automatically placed into the global scope.
For example, math.js:
const secretNumber = 42;
export function getNumber() {
return secretNumber;
}Another file cannot directly access:
console.log(secretNumber);because secretNumber belongs to the module's own scope.
It can access the value through the exported function:
import { getNumber } from "./math.js";
console.log(getNumber());Output:
42This helps keep internal implementation details private.
Reusing Modules
One of the biggest advantages of modules is code reuse.
Suppose we create:
utils.jsexport function formatCurrency(price) {
return `₹${price.toFixed(2)}`;
}Now different files can reuse it.
import { formatCurrency } from "./utils.js";
console.log(formatCurrency(500));Another file can also use the same function:
import { formatCurrency } from "./utils.js";
console.log(formatCurrency(1250));Instead of rewriting the same function in multiple places, we define it once and reuse it.
A Practical Example
Imagine we're building a small shopping application.
We can organize it like this:
project/
│
├── app.js
├── cart.js
├── products.js
└── utils.jsproducts.js
export const products = [
{
name: "Laptop",
price: 50000
},
{
name: "Mouse",
price: 1000
}
];cart.js
export function calculateTotal(cart) {
return cart.reduce((total, product) => {
return total + product.price;
}, 0);
}app.js
import { products } from "./products.js";
import { calculateTotal } from "./cart.js";
const total = calculateTotal(products);
console.log(`Total: ₹${total}`);Now each file has a clear responsibility:
products.js
↓
Product data
cart.js
↓
Cart logic
app.js
↓
Application entry pointThis structure becomes extremely useful as applications grow.
Modules and Third-Party Packages
The module system is also the foundation of modern JavaScript package management.
For example, in a Node.js or frontend project, you might see:
import express from "express";or:
import React from "react";Here, JavaScript is importing functionality provided by external packages.
Tools such as npm and modern build systems make it easy to manage these dependencies.
You don't need to understand package management yet. The important thing is to recognize that the same import and export concepts are used throughout the JavaScript ecosystem.
Conclusion
JavaScript modules allow us to split a large application into smaller, organized, reusable files.
The two most important concepts are:
Export
export function add(a, b) {
return a + b;
}Import
import { add } from "./math.js";You should also remember:
Named exports use
{}when importing.Default exports don't use
{}.A module can have multiple named exports but only one default export.
Modules have their own scope.
Modules make code easier to organize and reuse.
Browser modules are loaded using
<script type="module">.
The basic flow is:
Create module
↓
Export code
↓
Import code
↓
Use it in another fileOnce you understand modules, you're ready to work with larger JavaScript projects where code is divided into multiple files instead of keeping everything inside one giant script.