Modules

Split Code Across Files With `import` and `export`

Modules

Modules let your code grow past one file. Each `.mjs` (or `"type":"module"` `.js`) is its own module.

3 min read Level 1/5 #nodejs#modules#esm
What you'll learn
  • Author and import an ES module
  • Use named and default exports
  • Know the file extension rules

Every JS file in Node is a module. Each has its own scope — variables declared in one don’t leak into another. You expose values with export, consume them with import.

A Module

// math.mjs
export function add(a, b) { return a + b; }
export const PI = 3.14159;

Importing

// app.mjs
import { add, PI } from "./math.mjs";

console.log(add(2, 3));   // 5
console.log(PI);          // 3.14159

Default Exports

// greeter.mjs
export default function greet(name) {
  return `Hello, ${name}!`;
}
import greet from "./greeter.mjs";   // any name, no braces
greet("Ada");

Both

// logger.mjs
export default function log(msg) { console.log(msg); }
export function warn(msg) { console.warn(msg); }
import log, { warn } from "./logger.mjs";

File Extensions

In Node ESM, you must include the extension:

import { add } from "./math.mjs";    // ✓
import { add } from "./math";        // ✗ ERR_MODULE_NOT_FOUND

(Bundlers like Vite/webpack are more forgiving, but raw Node isn’t.)

Importing Built-ins

Prefix Node built-ins with node::

import { readFileSync } from "node:fs";
import { join }         from "node:path";
import { createServer } from "node:http";

The prefix is the modern, unambiguous way — never collides with an npm package of the same name.

Importing npm Packages

After npm install lodash:

import { chunk } from "lodash";

Node finds it in node_modules/. We cover npm next.

Up Next

ESM vs the older CommonJS — and why both exist.

ESM vs CJS →