Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

ES modules and CommonJS

A module is a file that exposes part of its code to others. You know how import and export work from the tutorial. Node.js has two module systems: modern ES modules and the older CommonJS with require. New projects use ES modules, but CommonJS appears in older code and documentation, so you need to recognise it.

Your own module

Create the folder src and in it the file posts.js — a module with the blog's posts:

// src/posts.js
export const posts = [
  { id: 1, title: 'Hello, Node.js' },
  { id: 2, title: 'Working with files' },
];
 
export function findPost(id) {
  return posts.find((post) => post.id === id);
}

Import it in app.js in the project root:

// app.js
import { posts, findPost } from './src/posts.js';
 
console.log(posts.length);       // 2
console.log(findPost(2).title);  // Working with files

node app.js prints 2 and the title of the second post. A path to your own module starts with ./ or ../ and must include the .js extension.

Built-in modules

Node.js built-in modules are imported by name with the node: prefix — it shows that the module is built in, not downloaded from npm:

import os from 'node:os';
import path from 'node:path';
 
console.log(path.extname('posts.json')); // .json
console.log(os.EOL === '\n' || os.EOL === '\r\n'); // true

os.EOL is the line ending of the current system.

CommonJS

In CommonJS you write require() instead of import and assign to module.exports instead of export:

const path = require('node:path');
 
function fileName(file) {
  return path.basename(file);
}
 
module.exports = { fileName };
console.log(fileName('/data/posts.json')); // posts.json

This is how projects without "type": "module" in package.json and files with the .cjs extension work.

Comparison

ES modulesCommonJS
Importingimport x from '...'const x = require('...')
Exportingexport, export defaultmodule.exports = ...
Enabled by"type": "module" or .mjsDefault, or .cjs
await outside a functionAllowedNot allowed
Path to your own fileExtension requiredExtension optional

Common mistake

The two systems cannot be mixed in one file. Copy a line with require from an old article into a project with "type": "module", and the program fails:

ReferenceError: require is not defined in ES module scope

Replace require with import: const fs = require('node:fs') becomes import fs from 'node:fs'. The opposite happens too: without the "type" field Node.js 22 still detects import by itself but prints a MODULE_TYPELESS_PACKAGE_JSON warning. To remove it, set the field with npm pkg set type=module.

Thanks for reading!

Donate to the site — we work hard for you.