What Package Management Is — What npm install Installs, and Where

This article is part of the IT Foundations course, which builds up from scratch the practical IT knowledge you need at a minimum for programming and vibe coding.
When you type npm install react, a node_modules folder appears in my-app and one line is added to package.json. The diagrams follow what that single line sets in motion.

This article covers package management.

It is the mechanism that fetches an external library by name with a single line such as npm install and puts it in a fixed place.

What the single line npm install react puts where
Typenpm install reactnpm fetches itfrom the registryA folder appearsin node_modulesOne line is addedto package.jsonapp.js doesnot change
The line on the left passes to npm in the middle, and the result is left in the two places on the right. The app.js you wrote yourself does not change.

You type only the one line on the left, and the two things on the right are what get added.

All that grows is the node_modules folder and one line in package.json; the app.js you wrote yourself does not change by a single character.

What a package is — an external library you fetch by name

An external library bundled into a form you can fetch by name is a package, and the number that identifies its contents at that point is the version.

When you want to display dates in a readable form in the booking app my-app, you can write that processing yourself, but it is also distributed as a package.

Displaying dates: writing it yourself versus fetching it
You want to showdates readablyWrite it yourselfUse a packageWrite dozens oflines, fix errorsFetch it by name,call in one lineThe same displayappears on screen
From top to bottom the flow splits in two and comes back together at the end. What differs is how much you write; the screen that comes out is the same.

On the left, all the lines you wrote are yours; on the right, you just call what you fetched in one line.

What is inside the single package called react
The package react
Name
  • The string you specify when fetching
  • Identifies exactly one thing in the registry
Version
  • A new number is added with each revision
  • Older numbers remain available
Source code files
  • The program itself, which runs when called
  • You do not edit these yourself
Names of other packages it needs
  • What react cannot run without is listed here
  • They come along when you fetch it
The outer box is one package, react. What you specify when fetching is the name and the version, and the files inside come along together.

What you specify when fetching is only the name at the top.

The "names of other packages it needs" at the bottom are what increase the number of folders later.

A package is an external library you can fetch by name

A package is a program someone else wrote, given a name and put into a form that can be distributed.

Specifying the name brings its contents onto your computer, and the version is the number that tells revisions apart within the same name.

What appears inside my-app when you type npm install react

The thing that fetches by name is the package manager — a program that fetches packages and puts them in a fixed place — and the JavaScript one is npm.

Each is a single line in the terminal, and both assume you are typing inside my-app.

# Move into the my-app folder first
cd my-app

# Fetch one package by the name react
npm install react

# Fetch all the names listed in the manifest file at once
npm install

Fetched packages go into node_modules — the folder npm creates inside my-app to hold the packages it fetched.

Inside my-app: what you write and what npm creates
my-app (the booking app folder)
Files you write
  • app.js — the source code for the booking processing
  • package.json — the file listing the names to fetch
node_modules (created by npm)
react
  • The source code of the fetched package
  • This is what you call
Packages the fetched one needs
  • One folder is created per name
  • If it needs nothing, this does not grow
The outer box is the my-app folder. The upper frame holds the files you write; the lower frame is the folder npm creates and npm rewrites.

The files you write and the folder npm creates sit separately inside the same my-app.

Even for the same one line, the result changes depending on how you type it and on whether the name is misspelled.

The line you typedWhat npm doesResult inside my-app
npm install reactFetches that name and its dependenciesFolders appear in node_modules
npm installFetches all names in package.json at onceThe whole node_modules is created
npm install reacttttLooks for it and does not find it404 Not Found; nothing is added

As in the third row, if a mistyped name does not exist in the registry, nothing is installed.

If a mistyped name happens to exist, something else gets installed, so copy names from the official page.

Why fetching one package adds many folders
npm install expressexpressPackages expressneedsPackages thoseneedPackages beyondthoseDozens of foldersin node_modules
It spreads from top to bottom and comes together at the end. What the fetched package needs, and what those need in turn, come along with it. For a package that needs nothing, like react, there stays just one folder.

The packages react needs, and the packages those need in turn, all come along.

Not having to look up that whole set and fetch it one by one is the reason to use a package manager.

Fetching one package does not mean only one folder is created in node_modules.

The registry is another computer on the far side of the Internet.

The only place fetched packages are put is node_modules inside the my-app folder.

The app.js you wrote calls the packages in there and uses them.

What you fetch goes into node_modules

What you fetch goes into the node_modules folder created inside my-app.

The app.js you wrote does not change, and there are more folders than the number you named because what the fetched package needs comes along too.

package.json — the manifest file listing the names of the packages you fetched

The contents of node_modules are created by npm, and you do not edit them yourself.

The only thing you manage is the single file that lists the names you fetched.

That is the manifest file — package.json in JavaScript — which records the names of the packages the app needs in order to run, and each name listed there is called a dependency, a package your own code needs in order to run.

{
  "name": "my-app",
  "dependencies": {
    "react": "^19.0.0",
    "express": "^5.1.0"
  }
}

The two entries listed under dependencies are this my-app's dependencies.

The right-hand side specifies the version to fetch; the numbers are for this example, and in practice whatever was current when you fetched goes in.

The leading ^ marks that "newer versions compatible with the number written here are also allowed."

Besides dependencies, package.json records other things too.

What is listed inside package.json
package.json
name
  • The name of the app itself
  • It says my-app
dependencies
  • Lists the names of the packages needed to run
  • npm install reads this part
  • Fetching react adds one line
scripts
  • Where you give short names to commands you type often
  • Called like npm run start
The outer box is the single file package.json. What npm install reads is the dependencies part in the middle.

What npm install reads is the dependencies part in the middle.

One and the same thing has three names, depending on where you look at it from.

The same one thing is called by different names depending on where you look
==In the registryPackageStored with a nameand a versionIn package.jsonDependencyListed as a namemy-app needs to runIn app.jsExternal libraryA program you calland use
The left is where you are looking, the middle is the name used there, and the right is how it is treated there. The three joined by double lines are the same thing.

Because the manifest file exists, you do not have to hand node_modules to anyone.

What you handed to another computerWhen they type npm installDoes my-app run?
app.js and package.jsonFetches every name in the listThe same set is there and it runs
app.js onlyNo way to know which names to fetchThe call raises an error
app.js and node_modulesThe contents are there without typing itIt runs, but you hand over hundreds of folders

You hand over app.js and package.json, and the other person types npm install once.

npm reads only the dependencies in package.json, fetches the names listed there from the registry, and rebuilds node_modules.

There is no need to hand over node_modules itself.

With the list of names alone, the contents can be rebuilt

package.json is the file that lists the names of the packages this my-app needs in order to run.

npm install reads this file and fetches all the names at once, so node_modules can be rebuilt at any time and never has to be handed to anyone.

The same in Python — pip, requirements.txt, and virtual environments that separate where packages go

So far we have looked at this with JavaScript names.

In Python the names differ, but what is being done is the same.

What plays the same role in JavaScript and Python
===JavaScriptnpmpackage.jsonnode_modulesPythonpiprequirements.txtsite-packagesRoleFetch byspecifying a nameKeep a list ofnames to fetchWhere fetchedpackages go
The top row is JavaScript, the middle row is the Python names, and the bottom row is the role. The two joined by a double line differ only in name; the role is the same.

pip is what fetches, and requirements.txt is the manifest file that lists the names.

Since the roles are the same, learning one lets you read the other the same way.

The one thing that differs is where packages go: without a virtual environment, pip installs them system-wide.

What you create to avoid this is a virtual environment — a mechanism that creates a folder holding the packages for that app alone.

Where packages go, separated per app
Your computer
my-app (the booking app)
  • node_modules — dependencies go in here
  • Not visible from another app
other-app (a different app)
  • Has its own node_modules
  • Different versions of the same name do not collide
A Python app with no virtual environment
  • There is only one site-packages for the whole computer
  • If another app requires a different version, they collide
The outer box is your computer. The top two keep their packages inside their own folder; only the bottom one shares a single location across the whole computer.

When the folders are separate per app, different versions of the same name can sit side by side without colliding.

Setup instructions have you create a virtual environment first in order to make that separation.

The three roles are the same across languages

Every language has a program that fetches, a manifest file that lists the names, and a place where what arrives is kept.

In JavaScript that is npm, package.json, and node_modules; in Python it is pip and requirements.txt, and in Python alone the packages go system-wide unless you create a virtual environment.

QUIZ

Knowledge Check

Answer each question one by one.

Q1When you type npm install react in the my-app folder, where does the fetched package go?

Q2When running the same my-app on another computer, why do you not have to hand over node_modules?

Q3Why can fetching a single package create more than one folder in node_modules?