JavaScript Module System Explained (with Examples)

Published: (January 13, 2026 at 04:08 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Topics Covered

  • import and export
    • 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 🚀

Back to Blog

Related posts

Read more »

Introduction to WebAssembly (Wasm)

Unleash the Web's Inner Speed Demon: A Friendly Dive into WebAssembly Wasm Ever feel like your web browser, while amazing, is sometimes wrestling with heavy li...