As JavaScript applications grow, putting everything into one file quickly becomes unmanageable.
That’s where the JavaScript module system comes in.
Modules allow us to split code into reusable files, control visibility, and load only what we need. Modern JavaScript uses ES Modules (ESM), which are now the standard for both browsers and Node.js.
Topics Covered
-
importandexport - Named exports & imports
- Default exports & imports
- Aliasing
- Namespace imports
- Combined imports
- Dynamic imports
- Multiple dynamic imports using
Promise.all
What Is a JavaScript Module?
A JavaScript module is simply a file that:
- Has its own scope
- Can export variables, functions, or classes
- Can import values from other modules
To enable modules in the browser:
<script type="module" src="main.js"></script>
Named Export
Named exports allow you to export multiple values from a single file.
math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
Named Import
When importing named exports, the names must match exactly.
main.js
import { add, subtract } from "./math.js";
console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
Default Export
A module can have only one default export.
This is useful when a file exposes one main feature.
logger.js
export default function log(message) {
console.log("Log:", message);
}
Default Import
You can import a default export using any variable name.
main.js
import logger from "./logger.js";
logger("Hello Dev.to!");
Aliasing (Renaming Imports)
Aliasing helps avoid naming conflicts or improve readability.
math.js
export const multiply = (a, b) => a * b;
main.js
import { multiply as mul } from "./math.js";
console.log(mul(4, 5)); // 20
Namespace Import (* as)
If a module exports many values, you can import everything as an object.
math.js
export const add = (a, b) => a + b;
export const subtract = (a, b) => a - b;
main.js
import * as MathUtils from "./math.js";
console.log(MathUtils.add(10, 5)); // 15
console.log(MathUtils.subtract(10, 5)); // 5
Combined Import (Default + Named)
You can combine default and named imports in a single statement.
user.js
export default function getUser() {
return { name: "Rayan", role: "Developer" };
}
export const isAdmin = false;
main.js
import getUser, { isAdmin } from "./user.js";
console.log(getUser());
console.log(isAdmin);
Dynamic Import (import())
Dynamic imports load modules at runtime instead of at page load.
Common use cases:
- Code splitting
- Lazy loading
- Performance optimization
math.js
export const add = (a, b) => a + b;
main.js
async function loadMath() {
const math = await import("./math.js");
console.log(math.add(2, 3)); // 5
}
loadMath();
⚠️
import()always returns a Promise.
Multiple Dynamic Imports Using Promise.all
To load multiple modules in parallel, use Promise.all.
math.js
export const add = (a, b) => a + b;
string.js
export const upper = (text) => text.toUpperCase();
main.js
async function loadModules() {
const [math, string] = await Promise.all([
import("./math.js"),
import("./string.js")
]);
console.log(math.add(3, 4)); // 7
console.log(string.upper("hello")); // HELLO
}
loadModules();
Key Rules to Remember
- One file can have multiple named exports
- One file can have only one default export
- Named imports must match export names
- Default imports can be renamed freely
- Dynamic imports always return a Promise
Final Thoughts
The JavaScript module system is the foundation of modern development.
Frameworks like React, Vue, and Node.js rely heavily on it.
Once you master import and export, your code becomes:
- Easier to maintain
- More scalable
- Better organized
Happy coding 🚀
Top comments (0)