This step-by-step guide will show you how to install npm, and master common commands in the Node Package Manager (npm) command-line interface.
Node.js makes it possible to write applications in JavaScript on the server. It’s built on the V8 JavaScript runtime and written in C++ — so it’s fast. Originally, it was intended as a server environment for applications, but developers started using it to create tools to aid them in local task automation. Since then, a whole new ecosystem of Node-based tools (such as Grunt, Gulp and webpack) has evolved to transform the face of front-end development.
To make use of these tools (or packages) in Node.js, we need to be able to install and manage them in a useful way. This is where npm, the Node package manager, comes in. It installs the packages you want to use and provides a useful interface to work with them.
In this guide, we’re going to look at the basics of working with npm. We’ll show you how to install packages in local and global mode, as well as delete, update and install a certain version of a package. We’ll also show you how to work with package.json
to manage a project’s dependencies. If you’re more of a video person, why not sign up for SitePoint Premium and watch our free screencast: What is npm and How Can I Use It?
But before we can start using npm, we first have to install Node.js on our system. Let’s do that now.
Install npm with Node.js
Head to the Node.js download page and grab the version you need. There are Windows and Mac installers available, as well as pre-compiled Linux binaries and source code. For Linux, you can also install Node via the package manager, as outlined here.
For this tutorial, we’re going to use v12.15.0. At the time of writing, this is the current Long Term Support (LTS) version of Node.
Tip: You might also consider installing Node using a version manager. This negates the permissions issue raised in the next section.
Let’s see where node was installed and check the version:
$ which node
/usr/bin/node
$ node --version
v12.15.0
To verify that your installation was successful, let’s give Node’s REPL a try:
$ node
> console.log('Node is running');
Node is running
> .help
.break Sometimes you get stuck, this gets you out
.clear Alias for .break
.editor Enter editor mode
.exit Exit the repl
.help Print this help message
.load Load JS from a file into the REPL session
.save Save all evaluated commands in this REPL session to a file
Press ^C to abort current expression, ^D to exit the repl
The Node.js installation worked, so we can now focus our attention on npm, which was included in the install:
$ which npm
/usr/bin/npm
$ npm --version
6.13.7
Install npm Updates
npm, which originally stood for Node Package Manager, is a separate project from Node.js. It tends to be updated more frequently. You can check the latest available npm version on this page. If you realize you have an older version, you can update as follows.
For Linux and Mac users, use the following command:
npm install -g npm@latest
For Windows users, the process might be slightly more complicated. This is what it says on the project’s home page:
Many improvements for Windows users have been made in npm 3 – you will have a better experience if you run a recent version of npm. To upgrade, either use Microsoft’s upgrade tool, download a new version of Node, or follow the Windows upgrade instructions in the Installing/upgrading npm post.
For most users, the upgrade tool will be the best bet. To use it, you’ll need to open PowerShell as administrator and execute the following command:
Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force
This will ensure you can execute scripts on your system. Next, you’ll need to install the npm-windows-upgrade tool. After you’ve installed the tool, you need to run it so that it can update npm for you. Do all this within the elevated PowerShell console:
npm install --global --production npm-windows-upgrade
npm-windows-upgrade --npm-version latest
Node Packaged Modules
npm can install packages in local or global mode. In local mode, it installs the package in a node_modules
folder in your parent working directory. This location is owned by the current user.
If you’re not using a version manager (which you probably should be), global packages are installed in {prefix}/lib/node_modules/
, which is owned by root (where {prefix}
is usually /usr/
or /usr/local
). This means you would have to use sudo
to install packages globally, which could cause permission errors when resolving third-party dependencies, as well as being a security concern.
Let’s change that!
![Parcel delivery company](https://uploads.sitepoint.com/wp-content/uploads/2015/03/1426064914package_manager-1024x682.jpg)
Change the Location of npm Global Packages
Let’s see what output npm config
gives us:
$ npm config list
; cli configs
metrics-registry = "https://registry.npmjs.org/"
scope = ""
user-agent = "npm/6.13.7 node/v12.15.0 linux x64"
; node bin location = /usr/bin/nodejs
; cwd = /home/sitepoint
; HOME = /home/sitepoint
; "npm config ls -l" to show all defaults.
This gives us information about our install. For now, it’s important to get the current global location:
$ npm config get prefix
/usr
This is the prefix we want to change, in order to install global packages in our home directory. To do that create a new directory in your home folder:
$ cd ~ && mkdir .node_modules_global
$ npm config set prefix=$HOME/.node_modules_global
With this simple configuration change, we’ve altered the location to which global Node packages are installed. This also creates a .npmrc
file in our home directory:
$ npm config get prefix
/home/sitepoint/.node_modules_global
$ cat .npmrc
prefix=/home/sitepoint/.node_modules_global
We still have npm installed in a location owned by root. But because we changed our global package location, we can take advantage of that. We need to install npm again, but this time in the new, user-owned location. This will also install the latest version of npm:
npm install npm@latest -g
Finally, we need to add .node_modules_global/bin
to our $PATH
environment variable, so that we can run global packages from the command line. Do this by appending the following line to your .profile
, .bash_profile
or .bashrc
and restarting your terminal:
export PATH="$HOME/.node_modules_global/bin:$PATH"
Now our .node_modules_global/bin
will be found first and the correct version of npm will be used:
$ which npm
/home/sitepoint/.node_modules_global/bin/npm
$ npm --version
6.13.7
Tip: you can avoid all of this if you use a Node version manager. Check out this tutorial to find out how: Installing Multiple Versions of Node.js Using nvm.
Install npm Packages in Global Mode
At the moment, we only have one package installed globally — the npm package itself. So let’s change that and install UglifyJS (a JavaScript minification tool). We use the --global
flag, but this can be abbreviated to -g
:
$ npm install uglify-js --global
/home/sitepoint/.node_modules_global/bin/uglifyjs -> /home/sitepoint/.node_modules_global/lib/node_modules/uglify-js/bin/uglifyjs
+ uglify-js@3.7.7
added 3 packages from 38 contributors in 0.259s
As you can see from the output, additional packages are installed. These are UglifyJS’s dependencies.
List npm’s Installed Global Packages
We can list the global packages we’ve installed with the npm list
command:
$ npm list --global
home/sitepoint/.node_modules_global/lib
├─┬ npm@6.9.0
│ ├── abbrev@1.1.1
│ ├── ansicolors@0.3.2
│ ├── ansistyles@0.1.3
│ ├── aproba@2.0.0
│ ├── archy@1.0.0
....................
└─┬ uglify-js@3.5.3
├── commander@2.19.0
└── source-map@0.6.1
The output, however, is rather verbose. We can change that with the --depth=0
option:
$ npm list -g --depth=0
/home/sitepoint/.node_modules_global/lib
├── npm@6.13.7
└── uglify-js@3.7.7
That’s better; now we see just the packages we’ve installed along with their version numbers.
Any packages installed globally will become available from the command line. For example, here’s how you would use the Uglify package to minify example.js
into example.min.js
:
$ uglifyjs example.js -o example.min.js
Install npm Packages in Local Mode
When you install packages locally, you normally do so using a package.json
file. Let’s go ahead and create one:
$ mkdir project && cd project
$ npm init
package name: (project)
version: (1.0.0)
description: Demo of package.json
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
Press Return to accept the defaults, then press it again to confirm your choices. This will create a package.json
file at the root of the project:
{
"name": "project",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Tip: If you want a quicker way to generate a package.json
file use npm init --y
.
The fields are hopefully pretty self-explanatory, with the exception of main
and scripts
. The main
field is the primary entry point to your program, and the scripts
field lets you specify script commands that are run at various times in the life cycle of your package. We can leave these as they are for now, but if you’d like to find out more, see the package.json documentation on npm and this article on using npm as a build tool.
Now let’s try and install Underscore:
$ npm install underscore
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN project@1.0.0 No repository field.
+ underscore@1.9.2
added 1 package from 1 contributor and audited 1 package in 0.412s
found 0 vulnerabilities
Note that a lockfile is created. We’ll be coming back to this later.
Now if we have a look in package.json
, we’ll see that a dependencies
field has been added:
{
...
"dependencies": {
"underscore": "^1.9.2"
}
}
Manage npm Dependencies with package.json
As you can see, Underscore v1.9.2 was installed in our project. The caret (^
) at the front of the version number indicates that when installing, npm will pull in the highest version of the package it can find where only the major version has to match (unless a package-lock.json
file is present). In our case, that would be anything below v2.0.0. This method of versioning dependencies (major.minor.patch) is known as semantic versioning. You can read more about it here: Semantic Versioning: Why You Should Be Using it.
Also notice that Underscore was saved as a property of the dependencies
field. This has become the default in the latest version of npm and is used for packages (like Underscore) required for the application to run. It would also be possible to save a package as a devDependency
by specifying a --save-dev
flag. devDependencies
are packages used for development purposes — for example, for running tests or transpiling code.
Tip: you can also add private: true
to package.json
to prevent accidental publication of private repositories, as well as suppressing any warnings generated when running npm install
.
Far and away the biggest reason for using package.json
to specify a project’s dependencies is portability. For example, when you clone someone else’s code, all you have to do is run npm i
in the project root and npm will resolve and fetch all of the necessary packages for you to run the app. We’ll look at this in more detail later.
Before finishing this section, let’s quickly check that Underscore is working. Create a file called test.js
in the project root and add the following:
const _ = require("underscore");
console.log(_.range(5));
Run the file using node test.js
and you should see [0, 1, 2, 3, 4]
output to the screen.
Uninstall npm Local Packages
npm is a package manager, so it must be able to remove a package. Let’s assume that the current Underscore package is causing us compatibility problems. We can remove the package and install an older version, like so:
$ npm uninstall underscore
removed 1 package in 0.386s
$ npm list
project@1.0.0 /home/sitepoint/project
└── (empty)
Install a Specific Version of an npm Package
We can now install the Underscore package in the version we want. We do that by using the @ sign to append a version number:
$ npm install underscore@1.9.1
+ underscore@1.9.1
added 1 package in 1.574s
$ npm list
project@1.0.0 /home/sitepoint/project
└── underscore@1.9.1
Update an npm Package
Let’s check if there’s an update for the Underscore package:
$ npm outdated
Package Current Wanted Latest Location
underscore 1.9.1 1.9.2 1.9.2 project
The Current column shows us the version that is installed locally. The Latest column tells us the latest version of the package. And the Wanted column tells us the latest version of the package we can upgrade to without breaking our existing code.
Remember the package-lock.json
file from earlier? Introduced in npm v5, the purpose of this file is to ensure that the dependencies remain exactly the same on all machines the project is installed on. It’s automatically generated for any operations where npm modifies either the node_modules
folder or the package.json
file.
You can go ahead and try this out if you like. Delete the node_modules
folder, then re-run npm i
(this is short for npm install
). npm will re-install Underscore v1.9.1, even though we just saw that v1.9.2 is available. This is because we specified version 1.9.1 in the package-lock.json
file:
{
"name": "project",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"underscore": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz",
"integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg=="
}
}
}
Prior to the emergence of the package-lock.json
file, inconsistent package versions proved a big headache for developers. This was normally solved by using an npm-shrinkwrap.json
file, which had to be manually created.
Now, let’s assume the latest version of Underscore fixed the bug we had earlier and we want to update our package to that version:
$ npm update underscore
+ underscore@1.9.2
updated 1 package in 0.236s
$ npm list
project@1.0.0 /home/sitepoint/project
└── underscore@1.9.2
Tip: for this to work, Underscore has to be listed as a dependency in package.json
. We can also execute npm update
if we have many outdated modules we want to update.
Search for npm Packages
We’ve used the mkdir
command a couple of times in this tutorial. Is there a Node package that has this functionality? Let’s use npm search
:
$ npm search mkdir
NAME | DESCRIPTION | AUTHOR | DATE
mkdir | Directory creation… | =joehewitt | 2012-04-17
fs-extra | fs-extra contains… | =jprichardson… | 2019-06-28
mkdirp | Recursively mkdir,… | =isaacs… | 2020-01-24
make-dir | Make a directory… | =sindresorhus | 2019-04-01
...
There’s (mkdirp). Let’s install it:
$ npm install mkdirp
+ mkdirp@1.0.3
added 1 package and audited 2 packages in 0.384s
Now create a mkdir.js
fie and copy–paste this code:
const mkdirp = require('mkdirp');
const made = mkdirp.sync('/tmp/foo/bar/baz');
console.log(`made directories, starting with ${made}`);
Next, run it from the terminal:
$ node mkdir.js
made directories, starting with /tmp/foo
Use npm to Re-install Project Dependencies
Let’s first install one more package:
$ npm install request
+ request@2.88.0
added 48 packages from 59 contributors and audited 65 packages in 2.73s
found 0 vulnerabilities
Check the package.json
:
"dependencies": {
"mkdirp": "^1.0.3",
"request": "^2.88.0",
"underscore": "^1.9.2"
},
Note the dependencies list got updated automatically. If you wanted to install a package without saving it in package.json
, just use the --no-save
argument.
Let’s assume you’ve cloned your project source code to a another machine and we want to install the dependencies. Let’s delete the node_modules
folder first, then execute npm install
:
$ rm -R node_modules
$ npm list --depth=0
project@1.0.0 /home/sitepoint/project
├── UNMET DEPENDENCY mkdirp@1.0.3
├─┬ UNMET DEPENDENCY request@2.88.0
...
└── UNMET DEPENDENCY underscore@1.9.2
npm ERR! missing: mkdirp@1.0.3, required by project@1.0.0
npm ERR! missing: request@2.88.0, required by project@1.0.0
npm ERR! missing: underscore@1.9.2, required by project@1.0.0
...
$ npm install
added 50 packages from 60 contributors and audited 65 packages in 1.051s
found 0 vulnerabilities
If you look at your node_modules
folder, you’ll see that it gets recreated again. This way, you can easily share your code with others without bloating your project and source repositories with dependencies.
Manage npm’s Cache
When npm installs a package, it keeps a copy, so the next time you want to install that package, it doesn’t need to hit the network. The copies are cached in the .npm
directory in your home path:
$ ls ~/.npm
anonymous-cli-metrics.json _cacache index-v5 _locks _logs node-sass
This directory will get cluttered with old packages over time, so it’s useful to clean it up occasionally:
$ npm cache clean --force
You can also purge all node_module
folders from your workspace if you have multiple node projects on your system you want to clean up:
find . -name "node_modules" -type d -exec rm -rf '{}' +
Use npm Audit to Scan Dependencies for Vulnerabilities
Have you noticed all of those found 0 vulnerabilities
scattered throughout the CLI output? The reason for this is that a new feature was introduced in npm that allows developers to scan the dependencies for known security vulnerabilities.
Let’s try out this feature by installing an old version of express
:
$ npm install express@4.8.0
express@4.8.0
added 36 packages from 24 contributors and audited 123 packages in 2.224s
found 21 vulnerabilities (8 low, 9 moderate, 4 high)
run `npm audit fix` to fix them, or `npm audit` for details
As soon as we finish installing, we get a quick report that multiple vulnerabilities have been found. You can run the command npm audit
to view more details:
$ npm audit
=== npm audit security report ===
# Run npm install express@4.17.1 to resolve 21 vulnerabilities
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ High │ Regular Expression Denial of Service │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ negotiator │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ express │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ express > accepts > negotiator │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ https://nodesecurity.io/advisories/106 │
└───────────────┴──────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Moderate │ Timing Attack │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ cookie-signature │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ express │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ express > cookie-signature │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ https://nodesecurity.io/advisories/134 │
└───────────────┴──────────────────────────────────────────────────────────────┘
You’ll get a detailed list of packages that have vulnerabilities. If you look at the Path
field, it shows the dependency path. For example, the Path express > accepts > negotiator
means Express depends on the Accepts
package. The Accepts
package depends on the the negotiator
package, which contains the vulnerability.
There are two ways of fixing all these problems. We can either execute the command npm install express@4.17.1
as suggested, or run npm audit fix
. Let’s do the latter:
$ npm audit fix
+ express@4.17.1
added 20 packages from 14 contributors, removed 7 packages and updated 29 packages in 1.382s
fixed 21 of 21 vulnerabilities in 122 scanned packages
The command npm audit fix
automatically installs any compatible updates to vulnerable dependencies. While this might seem like magic, do note that vulnerabilities can’t always be fixed automatically. This could happen if you’re using a package that’s undergone a major change which could break your current project if updated. For situations such as this, you’ll have to review your code and manually apply the fix.
You can also run npm audit fix --force
if you don’t mind upgrading packages with breaking changes. After you’ve executed the command, run npm audit
to ensure that all vulnerabilities have been resolved.
npm Aliases
As you may have noticed, there are multiple ways of running npm commands. Here’s a brief list of some of the commonly used npm aliases:
npm i <package>
: install local packagenpm i -g <package>
: install global packagenpm un <package>
: uninstall local packagenpm up
: npm update packagesnpm t
: run testsnpm ls
: list installed modulesnpm ll
ornpm la
: print additional package information while listing modules
You can also install multiple packages at once like this:
$ npm i express momemt lodash mongoose body-parser webpack
If you want to view all the common npm commands, just execute npm help
for the full list. You can also learn more in our article 10 Tips and Tricks That Will Make You an npm Ninja.
Execute Packages with npx
You might also hear talk of npx on your travels. Don’t confuse this with npm. As we’ve learned, npm is a tool for managing your packages, whereas npx is a tool for executing packages. It comes bundled with npm version 5.2+.
A typical use of npx is for executing one-off commands. For example, imagine you wanted to spin up a simple HTTP server. You could install the http-server package globally on your system, which is great if you’ll be using http-server
on a regular basis. But if you just want to test the package, or would like to keep your globally installed modules to a minimum, you can change into the directory where you’d like to run it, then execute the following command:
npx http-server
And this will spin up the server without installing anything globally.
You can read more about npx here.
Conclusion
In this tutorial, we’ve covered the basics of working with npm. We’ve demonstrated how to install Node.js from the project’s download page, how to alter the location of global packages (so we can avoid using sudo
), and how to install packages in local and global mode. We also covered deleting, updating and installing a certain version of a package, as well as managing a project’s dependencies.
From here, you might compare npm and Yarn to find out which suits your needs best. You can handle more complex needs using nvm, the Node Version Manager, or learn how to host and publish private npm packages. And if you’re feeling like exploring the next generation of JavaScript runtimes, you can learn Deno and read up on how Deno package management works.
With every new release, npm is making huge strides into the world of front-end development. According to its co-founder, its user base is changing and most of those using it are not using it to write Node at all. Rather, it’s becoming a tool that people use to put JavaScript together on the front end (seriously, you can use it to install just about anything) and one which is becoming an integral part of writing modern JavaScript.