What Does npm install Do? A Clear Guide for Web Developers

If you've ever cloned a JavaScript project from GitHub and seen a folder full of code but nothing actually running, chances are someone told you to "just run npm install first." But what does that command actually do — and why does it matter so much in modern web development?

The Short Answer

npm install reads your project's package.json file and downloads every dependency listed there into a local folder called node_modules. It's essentially the setup step that turns a bare project skeleton into a working codebase.

Without it, your project has no access to the external libraries, frameworks, or tools it was built to use.

What Is npm, Exactly?

npm stands for Node Package Manager. It ships automatically with Node.js and serves as the default tool for managing JavaScript packages — both for front-end frameworks like React or Vue and for back-end Node.js applications.

A package is just a reusable chunk of code published by another developer (or team). Instead of writing everything from scratch, developers declare dependencies — packages their project needs — and npm handles fetching and organizing them.

What Happens When You Run npm install

Here's the step-by-step of what npm actually does under the hood:

  1. Reads package.json — This file lists your project's dependencies under two main keys: dependencies (needed in production) and devDependencies (needed only during development, like testing tools or bundlers).

  2. Checks for a package-lock.json file — If one exists, npm uses it to install the exact versions previously recorded, ensuring consistent installs across machines. If not, npm resolves the latest versions that satisfy the version ranges listed in package.json.

  3. Downloads packages from the npm registry — By default, this is the public registry at npmjs.com, though private registries can be configured.

  4. Builds the node_modules folder — All downloaded packages (and their own dependencies) are stored here. This folder can easily contain thousands of files, which is why it's almost always excluded from version control via .gitignore.

  5. Updates or creates package-lock.json — This lockfile records the precise version tree installed, so future runs produce identical results.

Common Variations of the Command

npm install isn't one-size-fits-all. The command has several useful flags and forms:

CommandWhat It Does
npm installInstalls all dependencies listed in package.json
npm install [package-name]Installs a specific package and adds it to dependencies
npm install [package-name] --save-devInstalls a package as a devDependency
npm install --productionInstalls only dependencies, skipping devDependencies
npm install -g [package-name]Installs a package globally on your system
npm ciInstalls strictly from package-lock.json — common in CI/CD pipelines

The distinction between npm install and npm ci matters in team or automated environments. npm ci is faster and stricter — it deletes node_modules first and installs exactly what the lockfile specifies, making it predictable for build servers.

Why node_modules Gets So Large 🗂️

One of the first things new developers notice is that node_modules can balloon to hundreds of megabytes — sometimes gigabytes — for relatively modest projects. This happens because of transitive dependencies: the packages you install also have their own dependencies, which have their own, and so on.

For example, installing a single testing framework might pull in dozens of supporting packages. npm handles this dependency tree automatically, which is convenient but means the folder grows fast.

This is also why node_modules is never committed to Git. Anyone cloning your project simply runs npm install to regenerate it.

What Can Go Wrong

A few common issues developers encounter:

  • Version conflicts — Two packages require incompatible versions of a shared dependency. npm handles many of these automatically, but some require manual resolution.
  • Missing package.json — Running npm install outside a project directory (or in one without a package.json) will either error out or create a bare install.
  • Network or registry issues — Corporate firewalls, proxy settings, or registry misconfigurations can block downloads.
  • Corrupted node_modules — Sometimes deleting the folder entirely and re-running npm install resolves strange build errors.

The Variables That Shape Your Experience 🔧

How npm install behaves — and how long it takes — varies considerably based on:

  • Project size and dependency count — A simple utility script installs in seconds; a large enterprise app with hundreds of dependencies may take minutes.
  • Node.js and npm version — Older versions of npm handle dependency resolution and lockfiles differently than current releases. npm v7+ introduced significant changes to how peer dependencies are handled.
  • Network speed — First-time installs hit the registry; subsequent installs often use a local cache, which is much faster.
  • Operating system — Some packages include native modules that must be compiled locally. These can behave differently on macOS, Linux, and Windows — and may require additional build tools like Python or a C++ compiler.
  • Whether a lockfile exists — A project without package-lock.json can produce different installs across machines if dependency version ranges are loose.

Global vs. Local Installation

When you run npm install [package] inside a project, the package is installed locally — only that project can use it. When you add the -g flag, the package is installed globally and becomes available as a system command from any directory.

Most developer tools like bundlers, linters, or CLI utilities (e.g., create-react-app, typescript) are often installed globally, while libraries your code imports directly are installed locally.

Whether global installation makes sense depends on your workflow, whether you're working across multiple projects with different version requirements, and how your system's Node.js environment is managed — particularly if you're using a version manager like nvm or fnm.