CommonJS Modules (require / module.exports)
Node.js uses a module system to organize code into separate files. The traditional module system is CommonJS, which uses require() to import and module.exports to export. Each file in Node.js is treated as a separate module with its own scope.
When you require a module, Node.js looks for it in three places: built-in modules (like fs, path), node_modules folder (installed packages), and local files (using relative paths like ./myModule).
// math.js — Exporting a module
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
module.exports = { add, multiply };
// app.js — Importing the module
const { add, multiply } = require('./math');
console.log(add(5, 3)); // 8
console.log(multiply(4, 2)); // 8
// You can also export a single value
// module.exports = function greet(name) {
// return `Hello, ${name}!`;
// }; - require() — Import modules, packages, or local files
- module.exports — Export values from a module
- exports.name — Shorthand for adding properties to module.exports
- Each file is a module — Variables are scoped to the file, not global
- Modules are cached — require() only runs the file once, then caches the result
- Always use relative paths (./file) for local modules. Without the ./ prefix, Node.js looks for built-in or node_modules packages.
ES Modules (import / export)
Modern Node.js also supports ES Modules (ESM), the same import/export syntax used in frontend JavaScript. To use ES modules, either set "type": "module" in your package.json or use the .mjs file extension.
ES Modules are the future of JavaScript modules. They support top-level await, static analysis, and tree-shaking. However, many existing npm packages still use CommonJS, so understanding both systems is important.
// First, add to package.json: "type": "module"
// math.mjs — Named exports
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// app.mjs — Importing named exports
import { add, multiply } from './math.mjs';
console.log(add(5, 3)); // 8
// Default export
export default class Calculator {
add(a, b) { return a + b; }
}
// Importing default export
import Calculator from './Calculator.mjs'; - import / export — Modern ES Module syntax
- "type": "module" — Add to package.json to enable ESM in .js files
- .mjs extension — Use ES Modules without changing package.json
- Named exports — Export multiple values by name
- Default export — Export a single main value from a module
- You cannot mix require() and import in the same file. Choose one module system per file.
Built-in Modules
Node.js comes with many built-in modules that provide essential functionality without installing any packages. These modules cover file system operations, networking, cryptography, and more.
You can import built-in modules using just their name — no file path or installation needed.
// Common built-in modules
const fs = require('fs'); // File system operations
const path = require('path'); // File path utilities
const http = require('http'); // HTTP server and client
const os = require('os'); // Operating system info
const crypto = require('crypto'); // Cryptographic functions
const url = require('url'); // URL parsing
const events = require('events'); // Event emitter
// Example: Generate a random ID
const id = crypto.randomUUID();
console.log('Random ID:', id);
// Random ID: 550e8400-e29b-41d4-a716-446655440000
// Example: Get system info
console.log('Home Directory:', os.homedir());
console.log('Hostname:', os.hostname()); - In modern Node.js, you can use the 'node:' prefix for built-in modules: require('node:fs'). This makes it clear you are importing a built-in module.
