NPM Tutorial - Node Package Manager Guide
What Is npm?
npm stands for Node Package Manager. It is the default package manager that comes with Node.js and is used to install, update, remove, and manage packages for Node.js projects. A package can be a framework like Express, a utility library like Lodash, a testing tool like Jest, a formatter like Prettier, or even a command-line tool used only during development. In practical terms, npm is what makes the Node.js ecosystem so powerful, because it gives developers access to a very large collection of reusable modules instead of forcing them to write everything from scratch.
npm is both a registry and a command-line tool. The registry is the online collection of published packages. The CLI is the npm command you run in the terminal to work with those packages. When you install a dependency, npm downloads it from the registry, stores its version in your project files, and places the package inside node_modules. This workflow is a central part of almost every Node.js project.
Checking npm Version
Since npm is installed with Node.js, the first thing many developers do is confirm that both Node.js and npm are available on the system.
node -v
npm -v
If both commands print version numbers, your environment is ready. If node works but npm does not, your installation may be incomplete or your terminal path may need correction.
Initializing a Project with package.json
One of npm's most important roles is managing project metadata through a file named package.json. This file describes the project name, version, entry point, scripts, dependencies, and other details. It acts as the main manifest for a Node.js project. If someone else clones your project, they can run npm install and npm will read package.json to install the packages your application needs.
To create this file quickly, use the following command inside your project folder:
npm init -y
The -y flag accepts the default values automatically. Without it, npm asks a series of questions about the project name, version, author, and entry point.
{
"name": "my-node-app",
"version": "1.0.0",
"description": "A simple Node.js npm demo project",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "node index.js",
"test": "echo \"No tests yet\""
},
"author": "Tutorials Logic",
"license": "ISC"
}
At first, this file may seem small, but it becomes extremely important as the project grows. It is the place where npm records dependencies, useful scripts, and configuration that your whole team can share.
Installing Packages
npm can install packages in different ways depending on how they are used. In most application projects, packages are installed locally so they belong only to that specific project. A package used in many projects as a command-line tool can sometimes be installed globally, but developers today often prefer npx for one-time commands instead of relying heavily on global installs.
npm install express
npm install lodash
npm install --save-dev nodemon
npm install -g typescript
In modern npm versions, npm install express automatically saves Express in dependencies. The --save-dev flag stores tools in devDependencies, which means they are needed during development but not required to run the app in production. nodemon, eslint, jest, and prettier are common examples of development dependencies.
Dependencies vs devDependencies
This distinction is one of the most important npm concepts. If a package is required when your application is running in production, it belongs in dependencies. If it is only needed while developing, building, testing, or linting the project, it belongs in devDependencies.
| Type | Purpose | Examples |
|---|---|---|
dependencies |
Packages required to run the application | express, axios, mongoose, dotenv |
devDependencies |
Packages used only during development or testing | nodemon, jest, eslint, typescript |
For example, if you build an API with Express, then Express is required in production, so it belongs in dependencies. If you use Nodemon to restart the server automatically while coding, then Nodemon belongs in devDependencies because production servers do not usually need it.
Installing All Project Dependencies
When you clone a Node.js project from GitHub or receive it from another developer, you normally do not get the node_modules folder. Instead, you install all required packages from the manifest files:
npm install
This command reads package.json and package-lock.json, downloads the required packages, and recreates node_modules. This is one reason Node.js projects are easy to share: the dependencies are described in files instead of being manually copied.
Using npm Scripts
npm is not only for installing packages. It also provides project scripts through the scripts section of package.json. Scripts let you define reusable commands for starting the app, running tests, building files, formatting code, or launching development mode. This keeps project commands consistent for everyone working on the codebase.
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js",
"test": "jest",
"lint": "eslint ."
}
}
npm start
npm run dev
npm test
npm run lint
Notice that start and test have shortcut forms, but custom names like dev and lint are usually run with npm run. Scripts make projects easier to use because developers do not have to remember long commands each time.
What Is package-lock.json?
Whenever npm installs packages, it also creates or updates a file named package-lock.json. This file records the exact versions of installed packages and their nested dependencies. Even if package.json says a project accepts a version range, the lock file preserves the exact dependency tree that worked during installation. This makes builds more consistent across machines and environments.
For example, two developers may both install a project on different days. Without a lock file, they might receive slightly different dependency versions that still match the version range. With package-lock.json, npm knows the exact versions to install, which reduces the chance of "it works on my machine" problems. In most projects, this file should be committed to version control.
Version Ranges and Semantic Versioning
npm uses semantic versioning for most packages. A version like 2.4.7 usually means major.minor.patch. Major updates may include breaking changes, minor updates usually add backward-compatible features, and patch updates usually contain bug fixes. npm also uses prefixes such as ^ and ~ in package.json to define allowed update ranges.
| Version Syntax | Meaning |
|---|---|
1.2.3 | Install exactly version 1.2.3 |
^1.2.3 | Allow patch and minor updates, but not major 2.x.x |
~1.2.3 | Allow patch updates only within 1.2.x |
latest | Install the latest published version |
Understanding this helps you update packages more safely. If a package introduces a breaking change in a new major release, a version range like ^1.2.3 protects you from automatically jumping to 2.x.x during a normal install.
Updating and Removing Packages
npm also helps maintain dependencies over time. You can check outdated packages, update them within allowed version ranges, or uninstall packages you no longer need.
npm outdated
npm update
npm uninstall lodash
npm uninstall --save-dev nodemon
A healthy project periodically reviews outdated packages, especially if they contain bug fixes or security improvements. Still, updating blindly can break an application, so it is good practice to run tests after upgrading important dependencies.
What Is npx?
npx is a helper that comes with npm and allows you to run package binaries without installing them globally yourself. This is especially useful for scaffolding tools, one-time commands, or project-local binaries. Instead of installing a CLI globally just to use it once, you can call it directly with npx.
npx create-react-app myapp
npx eslint .
npx jest
npx npm-check-updates -u
This approach reduces clutter from unnecessary global installations and makes it easier to run tools at the version intended by the project.
Security and Auditing
Because npm projects depend on many external packages, security matters. npm includes an audit feature that checks installed dependencies against known vulnerability databases. This helps you spot packages that may need updates or manual review.
npm audit
npm audit fix
The npm audit fix command can resolve some issues automatically, but you should still review important updates carefully. Security fixes can sometimes include version changes that affect application behavior.
Popular npm Packages and What They Are For
The npm ecosystem is huge, so it helps to understand a few common package categories instead of memorizing isolated names. Here are some frequently used examples and why developers use them:
A Practical Example Project Setup
Suppose you want to create a small Express application with automatic restart during development. A typical npm-based setup might look like this:
mkdir my-api
cd my-api
npm init -y
npm install express
npm install --save-dev nodemon
Then you might define scripts like this inside package.json:
{
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
}
}
Now the app can be started with npm start, while development mode can be launched with npm run dev. This is a very common real-world pattern in Node.js projects.
Common Beginner Mistakes
One common mistake is committing the entire node_modules folder to version control. Usually this folder should be ignored because it can be rebuilt by running npm install. Another mistake is putting every package in dependencies instead of separating development-only tools into devDependencies. A third mistake is relying heavily on global installs for tools that really belong to the project. Using project-local dependencies and npm scripts usually leads to more predictable results across different machines.
Beginners also sometimes treat npm commands as magic without understanding the files involved. It helps to remember the core relationship: package.json describes the project, package-lock.json locks exact versions, and node_modules contains the installed code. Once that model is clear, npm becomes much easier to use confidently.
- npm is the default package manager for Node.js and is used to manage packages, scripts, and project metadata.
-
npm init -ycreates apackage.jsonfile for a new project. -
Use
dependenciesfor packages needed in production anddevDependenciesfor development tools. -
npm installinstalls all project dependencies, whilenpm uninstallremoves a package. -
package-lock.jsonrecords exact installed versions and should usually be committed to version control. -
npxruns package binaries without requiring a permanent global install. - npm scripts help standardize common project commands like start, dev, test, and lint.
Frequently Asked Questions
Level Up Your Node js Skills
Master Node js with these hand-picked resources