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 and Gulp) 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. But before we can start using npm, we first have to install Node.js on our system.

Installing Node.js

More from this author

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 is outlined here.

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

.exit  Exit the repl

.help  Show repl options

.load  Load JS from a file into the REPL session

.save  Save all evaluated commands in this REPL session to a file

> .exit

The Node.js installation worked, so we can now focus our attention on npm, which was included in the install.

$ npm -v

1.4.28

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. 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. Lets change that:

Changing the Location of Global Packages

Let's see what output npm config gives us.

$ npm config list

; cli configs

registry = "https://registry.npmjs.org/"

user-agent = "npm/2.6.0 node/v0.10.36 linux x64"

; node bin location = /usr/local/bin/node

; 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/local

This is the prefix we want to change, so as 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 have 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 --global

npm@2.6.0 /home/sitepoint/.node_modules_global/lib/node_modules/npm

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 or .bash_profile 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 -v

2.6.0

Installing Packages in Global Mode

At the moment we only have one package installed globally — that is 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

uglify-js@2.4.16 node_modules/uglify-js

├── uglify-to-browserify@1.0.2

├── async@0.2.10

├── optimist@0.3.7 (wordwrap@0.0.2)

└── source-map@0.1.34 (amdefine@0.1.0)

As you can see from the output, four additional packages that are installed – these are uglify-js's dependencies.

Listing Global Packages

We can list the global packages we have installed with the npm list command.

$ npm list --global

├─┬ npm@2.6.0
│ ├── abbrev@1.0.5
│ ├── ansi@0.3.0
....................

└─┬ uglify-js@2.4.16
  ├── async@0.2.10
  ├─┬ optimist@0.3.7
  │ └── wordwrap@0.0.2
  ├─┬ source-map@0.1.34
  │ └── amdefine@0.1.0
  └── uglify-to-browserify@1.0.2

The output however, is rather verbose. We can change that with the --depth=0 option.

$ npm list -g --depth=0

├── npm@2.1.11
└── uglify-js@2.4.16

That's better — just the packages we have installed along with their version numbers.

At this point you can parse JavaScript files in the terminal with uglifyjs. For example the following command would minify example.js into example.min.js:

$ uglifyjs example.js -o example.min.js

Installing Packages in Local Mode

Installing packages in local mode is done without the --global flag. The package will be installed in your parent working directory in a node_modules folder. Let's create a project folder in our home directory:

$ mkdir ~/project && cd ~/project

$ npm install underscore

underscore@1.8.2 node_modules/underscore

$ ls

node_modules

$ ls node_modules

underscore

Listing Local Packages

Just like global packages we can list local packages with the npm list command.

$ npm list

/home/sitepoint/project
└── underscore@1.8.2

As you can see we are able to install local packages wherever we want. This also means that we can create another directory and install a different version of underscore.

Uninstalling Local Packages

npm is a package manager so it must be able to delete a package. Let's assume that the current underscore package is causing us compatibility problems. We can delete the package and install an older version, like so:

$ npm uninstall underscore

unbuild underscore@1.8.2

$ npm list

/home/sitepoint/project
└── (empty)

Installing a Specific Version of a 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.7.0

underscore@1.7.0 node_modules/underscore

$ npm list

/home/sitepoint/project
└── underscore@1.7.0

Updating a Package

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.8.2 node_modules/underscore

$ npm list

/home/sitepoint/project
└── underscore@1.8.2

Searching for Packages

We’ve used the mkdir command a couple of times in this tutorial. Is there a node package that does the same?

$ npm search mkdir

npm WARN Building the local index for the first time, please be patient

mkdirp

There is. Let's install it.

$ npm install mkdirp

mkdirp@0.5.0 node_modules/mkdirp
└── minimist@0.0.8

Now create a file mkdir.js:

var mkdirp = require('mkdirp');

mkdirp('foo', function (err) {

    if (err) console.error(err)

    else console.log('Directory created!')

});

And run it from the terminal:

$ node. mkdir.js

Directory created!

Managing the 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

npm  registry.npmjs.org  underscore ...

This directory will get cluttered with old packages over time, so it's useful to clean it up occasionally.

$ npm cache clean

Managing Dependencies

At the moment we only have two packages installed in our project directory, but that can grow very quickly. Installing dependencies by hand is unwieldy, so we can use a package.json file in our project directory to manage them instead. This can be created with the command npm init

$ npm init

This utility will walk you through creating a package.json file.

Press ^C at any time to quit.

name: (project) demo

version: (1.0.0)

description: Demo of package.json

entry point: (main.js)

test command:

git repository:

keywords:

author: Sitepoint

license: (ISC)

This creates the following file in our project root:

{

  "name": "demo",

  "version": "1.0.0",

  "description": "Demo package.json",

  "main": "main.js",

  "dependencies": {

    "mkdirp": "^0.5.0",

    "underscore": "^1.8.2"

  },

  "devDependencies": {},

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "author": "Sitepoint",

  "license": "ISC"

}

You can also add private: true to prevent accidental publication of private repositories as well as suppressing any warnings generated when running npm install. Let's create a new directory and use our package.json file to install our dependencies.

$ mkdir ~/demo && cd ~/demo

$ cp ~/project/package.json ~/demo

$ npm install

$ npm list

demo@1.0.0 /home/sitepoint/demo

├─┬ mkdirp@0.5.0
│ └── minimist@0.0.8
└── underscore@1.8.2

That showed how easily we can install the packages we need in another directory based on our package.json file. But how do we keep it up to date when we install new packages? Well, we can use the --save flag.

$ npm install request --save

$ npm list --depth=0

demo@1.0.0 /home/sitepoint/demo

├── mkdirp@0.5.0
├── request@2.53.0
└── underscore@1.8.2

And our package.json has also been updated:

"dependencies": {

  "mkdirp": "^0.5.0",

  "request": "^2.53.0",

  "underscore": "^1.8.2"

}

Conclusion

In this tutorial, I have covered the basics of working with npm. I have 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. I also covered deleting, updating and installing a certain version of a package, as well as managing a project's dependencies.

Are you using npm in your projects? There are thousands of packages on the npm registry and with announcement that jQuery plugins should be published there too, this number will only keep growing. Which ones couldn't you live without?