jump to navigation

Don’t use NPM install -g inside Vagrant October 20, 2015

Posted by willhlaw in Development.
Tags: , , ,
add a comment

Using Vagrant for your node.js projects makes sense if you want an environment that can be reliably and repeatedly built by any one of your team members and new ones without going through the hassle of writing Getting Started instructions for getting elasticsearch installed for Windows, Mac, and other *nix. I highly recommend it…or it’s up and coming predecessor, Otto (which actually uses Vagrant under the hood, but hides a lot of the complexity and uses best practices).

However, you cannot have the same start up process each and every time if you install dependencies without pinning or locking in the specific version. So rather than running:

>npm install -g grunt-cli@0.1.13

Instead, install grunt-cli locally as a dev-dependency and the `grunt` command will be available as npm scripts in your package.json’s script {} block.

>npm install grunt-cli@01.1.13 save-dep
>npm shrinkwrap --dev

We capture the version npm grabbed and stored in package.json under the devDependencies {} block by running `npm shrinkwrap` with the ‘dev’ flag. This locks your entire (local) dependency tree from your package.json, and creates an npm-shrinkwrap.json file. Npm-shrinkwrap.json files are not used for global installs. So next time your team member starts work on your project and runs `vagrant up` and then `npm install`, the locked dependencies will be read from npm-shrinkwrap.json (instead ofpackage.json) and your team member’s node_modules/ directory will behave just like yours.

npm-shrinkwrap.json files are not used for global installs — npm issues

So how then exactly do we run `grunt` from the command line since we don’t install it globally?

In package.json, we add some scripts:

{
  "name": "myProject",
  "version": "0.0.1",
  "devDependency": {
    "grunt-cli": "^0.1.13"
  },
  "scripts": {
    "grunt": "grunt",
    "test": "grunt test"
  }
}

And from the command line or another script, you run it with:

>npm run test  ## executes `grunt test`
>npm run grunt -- --help  ## executes `grunt --help`

The two extra dashes is npm’s way of allowing you to pass any grunt parameters after it.

To conclude, use npm-shrinkwrap within Vagrant for repeatable and reliable npm environment for your node.js project and install global packages locally and call them using `npm run <scripts.name>`.