Skip to main content

Command Palette

Search for a command to run...

Modules & the package ecosystem (CommonJS vs ESM, package.json)

Updated
4 min read

In this particular blog, we’ll dive into the nodejs ecosystem, all things that are tightly knit together
and provide a smooth development experience.

NPM(unofficially node package manager)

When you install nodejs on your machine, npm comes along with it. It doesn’t have any full form
but its the standard package manager for nodejs. There are several other in the market, for instance
pnpm, yarn, bun(also a runtime), all having their respective pros and cons.

NPM is the tool that helps you install, update and manage all the dependencies(packages) in your project.
In very simple words packages are nothing but a pre-written piece of code that we use in our application
to work. Like chalk is a library that is used for stylin terminal applications. You can find millions of libraries
on npmjs.com, which is a registry of all npm libraries and packages.

How do we initialize a nodejs project

npm init

This command initializes an empty nodejs application with a package.json file, that contains important information about the project. when you run this command in the terminal it asks you to fill these details

  • name: The name of your project.

  • version: The initial version of your project (default is “1.0.0”).

  • description: A brief description of what your project does.

  • entry point: The main file of your project (default index.js).

  • git repository: The URL of your project’s Git repository.

  • keywords: An array of keywords to help people find your project.

  • author: The name of the project’s author.

  • license: The type of license for your project (default is “ISC”).

If you wish to skip answering these promps initially and start with all the default values, that can be done by running a simple command.

npm init -y

A package.json file with all the default values will be created in the root directory. Now we can easily install and manage any package/library that we wish to use in our application.

Installing packages and versioning

npm install express@5

This command simply installs express as a dependency in my project, which will reflect inside our package.json file. And the @5 means the latest version of 5 series will be installed. Lets see how is the versioning actually done. At the time of writing, the latest express version is 5.2.1, which means when i run this command npm install express@5 in my terminal I’'ll get this 5.2.1 version. Now lets say i want a slightly older version of express, just for more stablility of my project, I can just run npm install express@4 and it will install the latest version of 4 series of express i.e. 4.21.1. We follow semantic versioning specification(SemVer), for versioning our applications/packages. It looks something like MAJOR.MINOR.PATCH.

  1. MAJOR version when you make incompatible API changes

  2. MINOR version when you add functionality in a backward compatible manner

  3. PATCH version when you make backward compatible bug fixes

Common JS vs ES modules

CommonJS is the old-school way Node.js has been handling modules since forever. When you write const fs = require('fs') that require() function is the heart of it. You basically pull/require whatever you need from other files or npm packages, and you export stuff using module.exports. It's synchronous, meaning Node waits for the file to load completely before moving on. Super straightforward, works great for server-side stuff where you're not sending code to a browser.

// math.js
module.exports.sum = (a,b) => a+b;
// usage
const {sum} = require('./math.cjs');

ESM (ES Modules) is the newer way that JavaScript officially supports, the same import and export syntax you might use in modern frontend frameworks like React or Vue. It looks cleaner: import fs from 'fs' instead of require(). ESM is asynchronous which can be faster for loading lots of files, and it's the future-proof approach since it's native to JavaScript itself, not just a Node.js thing. You need to set "type": "module" in your package.json to tell Node you're using it.

// math.mjs or .js with "type":"module"
export const sum = (a,b) => a+b;
// usage
import { sum } from './math.js';

In 2026, ESM is the way to go, its cleaner, asynchronous and makes syntax same on both backend and the frontend codebases.