Category Archives: npm

Node.js apps: what’s the difference between installing npm packages locally and globally?

You don’t need to spend too much time with Google to realise that there’s some amount of confusion about the purpose of global packages. Local packages people seem to grasp easily. Global packages… well, confusion. And if you’re one of those confuse people, don’t feel alone: I was confused too.

Ironic, considering I’m working on the npm support in Node Tools for Visual Studio. But, up until recently, global packages really weren’t that important in the implementation. We gave you a way to install and uninstall them in the alpha, but that was about it. Not much further thought given really:

Managing global packages in NTVS's npm Package Management dialog.

More recently I’ve been improving the way you interact with npm packages, and global packages are back in the frame. And the question is, what are they for? When (and how) should you use them? And when shouldn’t you?

Let’s take a step back. You might already be familiar with the outline structure of a node.js app:

Structure of a node.js app

On the left we’ve got the Explorer tree, and I’ve highlighted the root ExpressApp2 folder of my app (I was just using this for testing). The ExpressApp2 folder you can see above that is the Visual Studio solution folder.

On the right you can see the contents of my Node.js app, which is pretty sparse, along with the Visual Studio ExpressApp2.njsproj project file.

We also have the node_modules folder, where locally installed npm packages are stored. You can see that I’ve got angular, express, jade, and stylus installed locally.

If I want to use one of these modules in my code, I’d write something like:

var express = require('express');

No surprises so far. But what if express wasn’t there, but was instead installed globally? Could I still use it?

Well, yes, and no.

You see the global package installation folder (for such it is) is not just a big bucket of miscellaneous stuff that’s visible and accessible to all your node applications. There’s no way you can say in package.json, “please get this from (or install it to) the globally installed packages”. And if you try to require it in your code, well, that won’t work either.

And this makes sense, right? I mean you could have anything in your global packages so you probably don’t want all of them visible in all your node.js apps. The potential for problems would be significant.

So, back on point, what are global packages for?

Global packages are for anything that you need to access from the shell. By contrast local packages are for using within your apps.

So you’ll often find yourself installing frameworky or infrastructurey things in your global packages. Installed globally they’ll be on your PATH so you can use them anywhere.

A good example is Yeoman and its generators. You’ll use yo from the command line to scaffold out projects in a variety of places, so both Yeoman and the generators you want to use must be globally accessible.

Going back to express, this is an example of a package that you’ll often want to use in your node apps, so you’d normally install it locally. Except that it also has a command line interface… so you’ll want to install it globally?

Well, you can actually do both, and this might be the easiest option.

But, as I said earlier, you can use that global install in your apps. Maybe you have a lot of apps and you want to use the same version of express in all of them. That way, when you upgrade express, you only have to upgrade it globally and all your apps will get the upgrade. Nice, right?

If you wanted to do this, you’d need to link express into your node apps. To try this out, execute the commands below from the shell in a convenient folder. Couple of points:

  • On Windows you’ll need to run the Command Prompt as administrator, or you won’t be able to create the link,
  • For the npm init command, which will scaffold out a basic package.json for you, just accept all the default suggestions.
mkdir linktest
cd linktest
npm init
npm install express -g
npm link express

Unfortunately, unlike the npm install command, there’s no way to save express into your package.json dependencies list. You’ll need to edit the file and add it yourself. However, you should find that your linktest folder now contains a node_modules folder. Within that, you’ll find a symbolic link to your global express install. You can obviously drill into that folder just as if it were really in the linktest folder.

Now, as I said, if you update your global install of express your linktest node app will also get the update.

Hopefully that clears up the differences between local and global packages.

TAKE-HOME MESSAGE: always try to use local packages unless there’s a very good reason not to! (I.e., you need to use the package from the command line.)