JavaScript Module System Explained (with Examples)
Source: Dev.to
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:
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 include code splitting, lazy loading, and 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 exactly.
- 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 🚀