Tour of npm

Hello and welcome to the npm tour!

npm stands for Node Package Manager, written by Isaac Schlueter - it is the program you use to install third party Node modules. As of Node 0.6.x, you no longer have to install npm separately - it comes with Node! Thanks to that, we will skip the installation step.

Part I: Installing Things

Installing packages is npm's primary job. But before even doing anything, you should understand the difference between installing locally vs installing globally.

Installing Locally

npm always assumes you are working within the project directory of a Node project, let's call this directory the project root. When you are installing packages locally (this is the default behavior)

npm install <package name>

The installed package goes under

<project root>/node_modules

The way npm determines your project root is the following (paraphrasing from npm help folders)

Starting at the current directory, npm will walk up the folder tree checking for a folder that contains either a package.json file, or a node_modules folder. If such a directory is found, then that is treated as the effective "project root" for the purpose of running npm commands.

If no such directory is found, then fallback to using the current directory as the project root.

In the case that the project root does not already have a node_modules directory, one will be created for you when you next install a package.

If you are not confident what the current project root is, type

npm prefix

to find out.

Installing Globally

Installing a package globally puts the package into a global location, usually /usr/local/lib/node_modules for unix, and for Windows it's the node_modules directory under the same place where node.exe is installed. In order to install packages globally, you have to use the -g flag.

npm install <package name> -g

Should I install Locally or Globally?

The recommendation is to always install locally the libraries you require() - doing this keeps separate the dependencies of different projects, so that the requirements of one project can never interfere with another (npm actually prevents you from requiring packages that are not installed locally). Install globally command line utilities you commonly use such as coffeescript and docco - they will generally be installed to /usr/local/bin.

Examples of Installing

The most common usage of npm is to install a package that's been published to the npm registry. For example to install express, you'd do

npm install express

If you want a specific version of express, do like this

npm install express@2.4.0

You could also install by tag name

npm install express@latest

Or restrict the version by range

npm install express@">=2.4.7"

You can install private packages too. Any directory containing a valid package.json file (more on that later) is a valid npm package

npm install ~/mypackage

Same goes for a tarball that contains the contents of the above directory

npm install mypackage.tgz

or a github repo that contains that directory

npm install git://github.com/airportyh/mypackage.git

Last, but definitely not least

npm install

Will install all the packages that are required by your current project as defined in your package.json.

I highly recommend reading the output of npm help install and npm help folders.

Part II: Making Things

These section will cover various useful commands npm has to help you with developing a Node program or library - in both of these cases you'd be making a Node package.

package.json

I have mentioned package.json a couple of times, and now finally I will explain what it is. This file is a manifest of your Node project and should be placed at your project root. It contains various information that is specific to your project. Among these things are

A very basic package.json looks like this

{
   "name": "Blerg",
   "description": "Blerg blerg blerg.",
   "version": "0.0.1",
   "author": {
      "name" : "John Doe", 
      "email" : "john.doe@gmail.com"
   },
   "repository": {
       "type": "git",
       "url": "http://github.com/johndoe/blerg.git"
   },
   "engines": [
       "node >= 0.6.2"
   ],
   "license" : "MIT",
   "dependencies": {
       "express": ">= 2.5.6",
       "mustache": "0.4.0",
       "commander": "0.5.2"
   },
   "bin" : {
       "blerg" : "./cli.js"
   }
}

To save you some typing when creating a new package.json initially,

npm init

will ask you a series of questions and generate a package.json for you based on your answers.

Dependencies

Of particular interest is the "dependencies" property in package.json. This is a set of key/value pairs

"dependencies": {
    "express": ">= 2.5.6",
    "mustache": "0.4.0",
    "commander": "*"
},

On the left is the name of the package and on the right is a version specification, which could specify a specific version(0.5.2), a range of versions(>= 2.5.6) or any version(*). When you do

npm install

in your project, this is what npm looks at to install all of your project's dependencies.

For more on the semantics of package.json read npm help json

Updating a Package

npm update <package name>

will update a package to its current latest version, or the latest version that is allowable by the version specification defined in package.json.

List Installed Packages

npm list

Will show you all the packages you have currently installed for your project as well a their sub-packages, visually formatted as a nested tree

express@3.0.0alpha1-pre /Users/airportyh/Home/Code/express
├── commander@0.5.1 
├─┬ connect@2.0.0alpha1 
│ ├── formidable@1.0.8 
│ └── qs@0.4.2 
├─┬ connect-redis@1.2.0 
│ └── redis@0.7.1 
├── debug@0.5.0 
├── ejs@0.6.1 
├── jade@0.20.1 
├── mime@1.2.4 
├── mkdirp@0.3.0 
├─┬ mocha@0.12.0 
│ └── growl@1.4.1 
├── should@0.5.1 
└─┬ stylus@0.23.0 
  ├── cssom@0.2.1 
  ├── growl@1.1.0 
  └── mkdirp@0.0.7 

List Outdated Packages

npm outdated

will tell you which of the packages that you have installed is outdated with respect to what is current in the npm registry but allowable by the version definition in package.json.

Prune Unneeded Packages

npm prune

Will you remove any packages you have installed but is not depended on by your project according to your package.json.

Link

npm link ../myothernodeproject

The link command installs a package not by copying its contents, but rather by creating a symlink to a directory that contains the package. This is quite useful for when you are concurrently working on more than one Node project. It does not work on Windows, however.

Rebuild Native Modules

Some Node packages contain native code that's written in C++, which require compilation. If you ever need to recompile them - often the case when you upgrade to a new version of Node, do

npm rebuild

Commands

You can tell npm about commonly used shell scripts in your project via the scripts property in package.json. For example, writing this

"scripts": {
    "myscript": "node myscript.js"
}

will allow me to run node myscript.js by saying

npm run-script myscript

Four common tasks that are common to many projects - start, stop, test and restart - are made even easier to get to. If you have a script specified for start, for example, then you can run it by typing

npm start

Pack a Tarball

npm pack

The pack command packages your project into a tarball - good for if you need to email someone your package.

Part III: Becoming Famous

This section will cover commands for publishing and managing your Node package in the public npm registry.

In order to publish a package to the registery, you first need to register yourself as a user.

npm adduser

This will prompt for a username, a password and an email address. You'd also use this command to login to an existing user account in the case you are on a machine that does not have your npm login information yet (the info is saved in ~/.npmrc).

Once you are logged in, you can publish your package. In your project root directory do

npm publish

will do the trick. If your package name has already been taken, this won't work - you'll have to use another name. To publish again, use npm version <version> or update the version number by hand in package.json and then publish again.

It is possible to remove your package from the registry

npm unpublish <package name>[@<version>]

But this is discouraged. The better alternative is to deprecate it

npm deprecate <package name>[@<version>] <message>

which will show a deprecation warning message to anyone who installs it.

npm tag <name>@<version> [<tag>]

will give a particular version of a package a tag - which is a string, so that now people can install it via the tag name, such as

npm install blerg@stable

The author command manages the list of users that can publish a particular package.

npm author ls blerg

Lists the users who admin the blerg package.

npm author add johndoe blerg

Adds johndoe to the blerg package.

npm author rm johndoe blerg

Removes johndoe from the blerg package.

Part IV: Discovery

npm also has facilities for discovering public packages in the registry.

npm search <search term>

Will list all packages whose name, description, or keywords match the provided search term.

npm home <package name>

Will open the project's home page in your browser.

npm has social features too, you can star and unstar a package

npm [star|unstar] <package name>

At the moment, social data is not used on the npm web site, but it will be at some point to make discovering good packages easier.

Part V: Getting Help

npm

lists all available commands. Note: some of those listed are aliases.

npm help <command>

To get help on a particular command.

npm help-search <word>

searches all the command help pages for occurrence of a particular word, reverse sorted by the frequency of word occurrence. If you use npm help <command> and the command does not exist, it will fallback to help-search, so actually you'd be okay just using npm help.

And, last not least

npm faq

Bonus Tip

npm completion

Outputs some shell script which you can put into your .bashrc or .bash_profile to enable tab completion of npm commands.

Online Resources

Ever feel like you are wasting your life away debugging?
It doesn't have to be this way. Check out my debugging course.
blog comments powered by Disqus