How to Install Packages with npm: A Complete Guide

npm (Node Package Manager) is the default package manager for Node.js and one of the most widely used tools in modern web development. Whether you're adding a utility library, a front-end framework, or a build tool to your project, npm handles the installation and dependency management automatically. Here's everything you need to understand about how npm installation works — and what affects the outcome on your specific setup.

What npm Actually Does When You Install Something

When you run an npm install command, npm does several things at once:

  1. Resolves dependencies — it reads what you've requested, then traces all the packages that package depends on
  2. Fetches packages from the npm registry (registry.npmjs.org by default)
  3. Writes files into a node_modules folder in your project directory
  4. Updates package.json and package-lock.json to record what was installed

The package-lock.json file is particularly important — it locks dependency versions so every developer on a team installs the exact same code.

Prerequisites Before You Install Anything

Before any npm command works, you need Node.js installed on your machine. npm ships bundled with Node.js, so installing Node automatically gives you npm.

You can verify both are available by running:

node --version npm --version 

If either command returns an error, Node.js isn't installed or isn't on your system's PATH. Operating system matters here — installation steps differ between Windows, macOS, and Linux, and some Linux distributions require manual PATH configuration after installation.

The Core npm Install Commands

Installing a Package into a Project

npm install package-name 

This installs the package locally — meaning it's added to the node_modules folder inside your current project directory and recorded under "dependencies" in your package.json.

Installing as a Development Dependency

npm install package-name --save-dev 

Use this for tools only needed during development — test runners, linters, bundlers, and transpilers. These get recorded under "devDependencies" and won't be included in production builds (depending on your build configuration).

Installing Globally

npm install -g package-name 

Global installs make a package available as a command-line tool across your entire system — not tied to any single project. CLI tools like create-react-app, nodemon, or typescript are often installed globally. 🌐

Installing All Project Dependencies at Once

npm install 

Run this inside a project folder that already has a package.json. npm reads that file and installs everything listed under both dependencies and devDependencies. This is the standard step after cloning a repository.

Installing a Specific Version

npm install [email protected] 

Version pinning matters when you need to match an existing team setup, avoid a known bug in a newer release, or maintain compatibility with other dependencies.

Key Flags and Options Worth Understanding

FlagWhat It Does
--save-dev / -DSaves as a dev dependency
--global / -gInstalls system-wide, not project-scoped
--save-exact / -EPins the exact version with no version range
--legacy-peer-depsBypasses peer dependency conflicts (older behavior)
--omit=devSkips dev dependencies (useful for production environments)

What Can Go Wrong — and Why

npm installation failures are common and usually fall into a few categories:

Permission errors occur most often with global installs on macOS and Linux. Running npm install -g without the right permissions triggers an EACCES error. The fix depends on your system — some developers adjust npm's default directory, others use a version manager like nvm (Node Version Manager) to avoid needing elevated permissions entirely.

Peer dependency conflicts happen when two packages in your project require incompatible versions of a shared dependency. npm v7 and later treats peer dependency conflicts as hard errors by default, where earlier versions only issued warnings. The --legacy-peer-deps flag restores the older, more permissive behavior.

Network and proxy issues appear in corporate or restricted environments where outbound traffic to the npm registry is blocked or routed through a proxy. npm's configuration supports proxy settings via npm config set.

Corrupted node_modules sometimes cause cascading errors. Deleting the node_modules folder and package-lock.json, then running npm install fresh, resolves a large percentage of unexplained install failures.

Local vs. Global: Choosing the Right Scope 🔧

The local vs. global distinction trips up many developers new to npm. A useful mental model:

  • Local installs are for packages your code imports — React, Lodash, Express
  • Global installs are for tools you run — CLI utilities you invoke from the terminal

Installing a library globally and trying to import it inside a project typically doesn't work as expected, because Node.js resolves require() and import statements from the local node_modules folder, not the global directory.

How npm Version and Node Version Interact

Different versions of npm behave differently. npm v5 introduced package-lock.json. npm v7 changed how peer dependencies are handled. npm v9 and later made additional changes to the install algorithm and configuration defaults.

The Node.js version you're running determines which npm version ships with it, and some packages declare a minimum Node.js version they support. If you maintain multiple projects with different Node.js requirements, a version manager like nvm (macOS/Linux) or nvm-windows makes switching between Node versions straightforward.

The Variables That Shape Your Experience

How smooth or complicated npm installation feels depends on several overlapping factors:

  • Your operating system and how Node.js was originally installed
  • npm version — behaviors around peer dependencies, lockfiles, and permissions shifted across major releases
  • The package itself — some packages include native C++ bindings that require build tools (node-gyp, Python, Visual Studio Build Tools on Windows)
  • Your network environment — open internet vs. proxied corporate network vs. private registry
  • Project age — older projects may pin to older package versions that conflict with newer dependencies

A straightforward npm install react in a fresh project on a modern setup takes seconds. The same command inside a three-year-old project with dozens of interdependent packages and a specific Node version requirement is a different experience entirely — and what works cleanly in one setup may require flags, workarounds, or tooling changes in another.