Introduction
Almost no JavaScript project is written from scratch: you build on libraries — React, Express, lodash — written by other people. npm (Node Package Manager) is how those libraries reach your project: it is both the world's largest software registry (millions of packages) and the command-line tool that installs and manages them. If you use Node.js (the Node.js post), you already have npm.
Install: dependencies, and where they live
Installing a package is one command:
npm install react
That downloads React into node_modules/ and records it in package.json, the manifest every JavaScript project carries:
{
"dependencies": {
"react": "^18.2.0"
}
}
The caret means "compatible updates allowed" — version 18.3 is fine, 19.0 is not. Development-only tools (test runners, linters like ESLint) go in devDependencies instead, so production installs skip them. And node_modules/ itself is never committed to Git — it can contain tens of thousands of files — which is why a fresh clone starts with npm install and rebuilds it.
Scripts and the lockfile: the two files that save teams
package.json also holds scripts — named commands that standardise how a project runs:
{
"scripts": {
"start": "node server.js",
"test": "jest",
"build": "webpack"
}
}
Now npm test means the same thing on every machine, for every developer. The other lifesaver is package-lock.json: it records the exact version of every package and every transitive dependency (dependencies of dependencies) that was installed. Without it, two developers installing on different days could get different versions and different bugs; with it, installs are reproducible. Commit the lockfile, always — it is the difference between "works on my machine" and "works everywhere."
The honest trade
npm's scale is also its risk: the registry's openness means supply-chain attacks (a compromised package) are a real concern, which is why teams audit dependencies and lock versions. And node_modules bloat is legendary — a small project can pull in hundreds of transitive packages. Alternatives like Yarn and pnpm exist and improve on speed and disk usage, but npm remains the default, and its concepts (manifest, lockfile, scripts, registry) are shared by every package manager in every language.
Takeaway
npm installs packages into node_modules, records them in package.json, standardises commands with scripts, and guarantees reproducibility with the lockfile. It is the unglamorous infrastructure that makes modern JavaScript's reuse possible — and the lockfile is the single habit that saves the most team arguments.
Originally published at https://practicaldevblog.blogspot.com/2026/10/npm-explained-package-manager-behind.html
Top comments (0)