npm install downloads the code your project depends on

When you run npm install in your project folder, npm reads a file called package.json that lists every library and tool your project needs. It then downloads all of those libraries from the npm registry — a public repository of code — and stores them in a folder called node_modules inside your project.

Think of it like a grocery list. Your package.json says "I need React version 18, and I need a tool called Webpack." npm install is the act of going to the store and bringing home everything on that list. Without running it, your project has the shopping list but not the actual groceries.

The first time you run npm install on a new project, it can take a minute or two because it has to read everything. After that, if you run it again without changing package.json, it runs much faster because the code is already there.

Key Takeaways

  • npm install reads your package.json file and downloads all the libraries your project lists there into a node_modules folder.
  • You run npm install once when you first clone or read a project, because node_modules is not usually stored in version control.
  • A file called package-lock.json records the exact versions that were installed, so everyone on your team gets the same code.
  • If you add a new library with npm install [library-name], npm updates both package.json and package-lock.json automatically.

Why you do not store node_modules in version control

The node_modules folder can contain thousands of files and take up hundreds of megabytes of disk space. Storing it in Git or another version control system would make your repository huge and slow to clone. Instead, you store only package.json and package-lock.json — the instructions for what to read — and let npm install recreate node_modules on each machine.

This is why the first thing you do after cloning a project from GitHub is run npm install. The project folder exists, but node_modules does not yet. npm install builds it for you based on what package.json says you need.

The difference between npm install and npm ci

There are two commands that read your dependencies: npm install and npm ci (which stands for "clean install"). On your own machine during development, you use npm install. On a server or in automated testing, you usually use npm ci.

npm install is flexible — it will update to newer versions of libraries if they are available, as long as they match the version ranges in your package.json. npm ci is strict — it installs the exact versions recorded in package-lock.json, with no flexibility. This matters because on a server, you want the same code to run every time, not a slightly newer version of a library that might behave differently.

What happens when you add a new library

When you run npm install react-router (or any other library name), npm downloads that library and all of its own dependencies, adds the library name to package.json, and updates package-lock.json with the exact version installed. You then commit both files to version control.

When a teammate pulls your changes and runs npm install, they get the same version of react-router that you installed, because npm reads package-lock.json and respects the exact versions listed there. This is how teams stay in sync.

What to do if npm install fails

Sometimes npm install stops with an error. The most common cause is a version conflict — two libraries you are trying to use need different versions of the same underlying code, and npm cannot satisfy both demands. The error message usually tells you which libraries are in conflict.

If you hit a conflict, you have a few options: update one of the conflicting libraries to a newer version that works with the other, remove one of them if you do not actually need both, or ask the library maintainers to update their code. You can also try deleting package-lock.json and running npm install again, which tells npm to recalculate the best versions — but this can introduce unexpected changes, so do it only if you understand the risk.

Another common issue is running out of disk space or hitting network timeouts on slow connections. If npm install keeps timing out, you can increase the timeout with npm install --legacy-peer-deps or npm config set fetch-timeout 120000 (the number is in milliseconds).

How npm install relates to your development workflow

npm install is a one-time setup step, not something you run constantly while coding. You run it once when you start working on a project, and again whenever a teammate updates package.json or package-lock.json. Most of the time, you are running your actual development server with a command like npm start or npm run dev, which assumes npm install has already happened.

If you are new to a project and not sure whether to run npm install, the safe answer is yes — running it when node_modules already exists just verifies that everything is up to date and does not hurt anything.

Frequently Asked Questions

Do I need to run npm install every time I start coding?

No. You run it once when you first clone a project or when a teammate has updated package.json. After that, your libraries stay in node_modules until you delete the folder or change what libraries you need. Running it again when nothing has changed just takes time.

What is the difference between npm install and npm update?

npm install gets the exact versions listed in package-lock.json. npm update checks for newer versions that match your package.json rules and installs them if they exist. Use npm update only when you intentionally want to upgrade your libraries.

Can I delete node_modules and run npm install again?

Yes, and it is often a good troubleshooting step. Deleting node_modules and running npm install recreates it from scratch based on package-lock.json. This can fix corruption or conflicts. Your package.json and package-lock.json are what matter — node_modules is always replaceable.

Why is npm install taking so long?

Large projects with many dependencies can take several minutes, especially on slow internet. If it is taking much longer than that, you may have a network issue or a very large dependency tree. You can see what npm is doing with npm install --verbose, which prints detailed output as it downloads.

What if I want to install only development tools, not libraries my users need?

Use npm install --save-dev [library-name] to install a library as a development dependency. It goes into package.json under "devDependencies" instead of "dependencies," and npm skips it when installing for production. This keeps your production code smaller.