~/
Modules: CommonJS vs ESM
Quiz
...

Modules: CommonJS vs ESM

beginner · updated Tue Sep 22 2026Contribute

Split code into modules with require or import/export.

Modules: CommonJS vs ESM

A module is a file that exports values other files can import. Node has two module systems: the older CommonJS and the modern ES Modules (ESM).

CommonJS (the classic way)

CommonJS uses require and module.exports:

// math.js
function add(a, b) {
  return a + b;
}

module.exports = { add };
// app.js
const { add } = require("./math.js");
console.log(add(2, 3));

Node treats .js as CommonJS unless you opt into ESM.

ES Modules (the modern way)

ESM uses import and export — the same syntax as the browser:

// math.mjs
export function add(a, b) {
  return a + b;
}
// app.mjs
import { add } from "./math.mjs";
console.log(add(2, 3));

Enable ESM for a whole package by setting the type in package.json:

{ "type": "module" }

Then any .js file uses import/export.

Named vs Default Exports

export const name = "Ada";        // named
export default function greet() {} // default
import greet, { name } from "./lib.js";

Prefer named exports — they rename safely and are easier to discover.

Built-in Modules

Node ships modules you import with the node: prefix:

import { readFile } from "node:fs/promises";
import path from "node:path";
import os from "node:os";

Importing npm Packages

Bare names resolve from node_modules:

import express from "express";

Relative paths need ./ or ../. Without them, Node looks in node_modules.

Best Practices

  1. Prefer ESM — It is the standard and works in browsers too.
  2. Use node: for built-ins — Clearer and collision-proof.
  3. One module, one job — Keep files focused.
  4. Use named exports — Avoid default exports in shared libraries.

Common Mistakes

  1. Forgetting ./import "./math.js", not import "math.js".
  2. Mixing systems — ESM cannot require; CommonJS needs dynamic import() for ESM.
  3. Omitting the extension in ESM — Node requires ./math.js, not ./math.
  4. Circular imports — Modules that import each other can load as undefined.