Node.js Modules

Node.js modules let you split code into separate files and reuse it. Each file is its own module with its own scope; nothing leaks out unless you export it. Node supports two module systems: modern ES modules (import/export) and the older CommonJS (require). New code should use ES modules.

Exporting and Importing (ES Modules)

Named exports are imported in braces with the same name. A module can also have one default export, imported with any name you choose. With ES modules you must include the .js extension in relative imports.

// math.js
export const PI = 3.14159;
export function area(r) {
  return PI * r * r;
}
export default function add(a, b) {
  return a + b;
}

// app.js
import add, { area, PI } from './math.js';
console.log(add(2, 3));
console.log(area(2).toFixed(2));
console.log(PI);
5
12.57
3.14159

Built-in Modules

Node ships with core modules for common tasks. Import them with the node: prefix, which makes it clear they are built in.

import os from 'node:os';
import { randomUUID } from 'node:crypto';

console.log('CPU cores:', os.cpus().length);
console.log('Free memory (MB):', Math.round(os.freemem() / 1024 / 1024));
console.log('ID:', randomUUID());
CPU cores: 8
Free memory (MB): 6120
ID: 3b241101-e2bb-4255-8caf-4136c566a962

Common Core Modules

  • node:fs and node:fs/promises — read and write files
  • node:path — build and parse file paths
  • node:http — create web servers
  • node:events — the EventEmitter class
  • node:os — information about the operating system
  • node:crypto — hashing, random values, UUIDs
  • node:url — parse URLs and convert file URLs

CommonJS (require)

You will see CommonJS in older projects and tutorials. Files use require and module.exports. It is the default when package.json has no "type": "module", or for .cjs files.

// greet.cjs
module.exports = function greet(name) {
  return 'Hi ' + name;
};

// main.cjs
const greet = require('./greet.cjs');
console.log(greet('Bilal'));
Hi Bilal

__dirname in ES Modules

CommonJS gives you __dirname and __filename automatically. In ES modules, use import.meta (Node 20.11+ has import.meta.dirname and import.meta.filename built in).

console.log(import.meta.filename);
console.log(import.meta.dirname);

// Older Node versions:
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
/home/naeem/node-app/app.js
/home/naeem/node-app

Frequently asked questions

Should I use import or require in Node.js?

Use import (ES modules) for new projects. It is the JavaScript standard, works in browsers too, and supports top-level await. require is still supported for CommonJS code.

How do I enable ES modules in Node.js?

Add "type": "module" to package.json, or name your files with the .mjs extension.

Why do I get "ReferenceError: __dirname is not defined"?

You are in an ES module, where __dirname does not exist. Use import.meta.dirname in Node 20.11+, or derive it from import.meta.url.