Modules (ESM)
Organising JavaScript into reusable files — import, export, named vs default, and ESM vs CommonJS.
In Node's ES modules, an import path is a URL, not a search. import { add } from "./math" doesn't try ./math.js, ./math/index.js or anything else: Node looks for a file named exactly math, finds nothing, and stops before running a single line. It catches people because bundlers such as webpack and Vite, and many TypeScript setups, do fill in the extension, so the same import works in one project and fails in the next.
// package.json: { "type": "module" }
// math.js
export function add(a, b) {
return a + b;
}
// app.js
import { add } from "./math"; // no extension
console.log(add(2, 3));
// $ node app.js
// Error [ERR_MODULE_NOT_FOUND]: Cannot find module '.../math' imported from .../app.js
// Did you mean to import "./math.js"?Splitting code into reusable files
As programs grow, putting everything in one file becomes unmanageable.
Modules let you split code into focused files — one file for maths utilities,
one for user-related functions, one for API calls — and connect them with
import and export.
Exporting from a module
// math.js — a module that exports useful maths functions
// Named exports — you can have many:
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
export function multiply(a, b) { return a * b; }
export const PI = 3.14159265;
// Or export at the bottom (equivalent):
function divide(a, b) {
if (b === 0) throw new Error("Cannot divide by zero");
return a / b;
}
export { divide };// user.js — a module with a default export
// Default export — only ONE per module:
export default class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
greet() { return `Hello, I'm ${this.name}`; }
}
// You can mix default and named exports:
export const ROLES = ["admin", "user", "viewer"];Importing from a module
// app.js — using the modules above
// Named imports — curly braces, exact names:
import { add, multiply, PI } from "./math.js";
console.log(add(2, 3)); // 5
console.log(multiply(PI, 2)); // 6.28...
// Default import — no curly braces, any name you choose:
import User from "./user.js";
const alice = new User("Alice", "alice@example.com");
console.log(alice.greet()); // "Hello, I'm Alice"
// Import both default and named:
import User, { ROLES } from "./user.js";
console.log(ROLES); // ["admin", "user", "viewer"]
// Import everything as a namespace object:
import * as Math from "./math.js";
console.log(Math.add(2, 3)); // 5
console.log(Math.PI); // 3.14159265
// Rename on import (avoid naming conflicts):
import { add as mathAdd } from "./math.js";
import { add as vectorAdd } from "./vectors.js";Using modules in the browser
<!-- Use type="module" on your script tag -->
<script type="module" src="app.js"></script>
<!-- Inline module -->
<script type="module">
import { add } from "./math.js";
console.log(add(1, 2));
</script>Important: modules are always in strict mode automatically. They have their own
scope — variables don't leak to the global window. They're deferred by
default (like defer attribute).
Using modules in Node.js
// Option 1: use .mjs extension
// math.mjs — same export syntax as above
// Option 2: add "type": "module" to package.json
// {
// "type": "module"
// }
// Then .js files use ESM syntax
// With "type": "module" in package.json:
// math.js uses: export function add...
// app.js uses: import { add } from "./math.js"That's why the Node.js example above writes "./math.js" in full. For relative imports, Node's ES module loader uses the path exactly as written, so the file name has to include its extension (and a folder import has to name its file, as in "./utils/index.js"). Recent versions of Node print a Did you mean hint, as shown above, but they still refuse to guess:
// app.js
import { add } from "./math.js"; // full file name, extension included
console.log(add(2, 3));
// $ node app.js
// 5Official Sources
- MDN Web Docs — JavaScript modules
- MDN Web Docs — import
- MDN Web Docs — export
- ECMAScript 2024 — Modules (§16)
- Node.js Docs — ECMAScript modules
The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.