NVM And NPX For Multi Project Environments

February 11, 2021

Intro

It is common to see build tooling installed for a project at global level in a workspace or VM.

For example: one version of Node and a global package installation of a specific version of Gulp. This works fine when there is only one project in the VM but falls apart when we have multiple projects in one environment that each use different versions of the packages in their respective build toolchains.

We try our best to keep one environment per project at Fishtank, but it doesn't always work out that way. If we have more than one project there is a good chance that we may also need to manage more than one set of build tools.

A great example of this is a normal Sitecore 9 instance with Node 8.x and Gulp 3.x alongside a another project built with Node 15.x and Gulp 4.x Both projects build using Node and Gulp but use different versions.

Version Managers

Node Version Manager (or NVM for Windows) is a tool that allows us to manage multiple Node installations in a single environment. It provides easy command line tooling for installing different versions of Node and switching which is active. Both Windows and Unix versions of NVM have clear installation and usage instructions so I will not cover that here.

Global Vs. Local JavaScript Package Installations

There are two ways to install a package:

globalnpm install -g gulp-cli
localnpm install gulp-cli

Note the -g flag in the global installation command. This installs the package into a place where it can be shared with the entire environment. You can read more about global vs. local node installations here. When the -g flag is supplied the package is installed at the global level. This is often done so that a package command such as

 > gulp build

can be run from the command line without a prefix because the global Node packages path is present in our PATH environment variable.

We may need more than one version of a particular build tool for each different project which immediately rules out global Node packages. I generally recommend against global Node packages anyway, but it's possible to find this in legacy environments.

How can we get around this?

Enter NPX

NPX is a tool to run locally installed packages. This is how we can get around the challenges. You can read more about npx on the freeCodeCamp website. To install and run Gulp as a local package instead of globally, we'd do the following:

> npm install gulp-cli@2.3.0
# configure gulp and write your code

> npx gulp # running your gulp build script with the local version of gulp!

NPM Scripts

There is a section in package.json where scripts can be defined. Binaries of locally installed packages are made available in the PATH, so you can run them by name instead of pointing to node_modules/.bin/name or using NPX.

This is my preferred method for specifying node scripts for a project because the command is now checked in to version control and doesn't need to live in a single developer's memory. We can also specify permutations of our scripts such as in the example below.

{
    "name": "coveo-search-ui-seed",
    "scripts": {
        "buildProd": "gulp -f ./gulp.prod.js",
        "buildDev": "gulp -f ./gulp.dev.js",
        "buildDevVerbose": "gulp -f ./gulp.dev.js -LLLL"
    },
    "devDependencies": {
        "gulp-cli": "^2.3.0"
    },
    "dependencies": {...}
}

We can call this build script by running the command

> npm run buildDev

and we'll be using the locally installed version of our Gulp package.

Summary

It is common to see build tooling installed for a project at global level in a workspace or VM. This works fine when there is only one project in the VM but falls apart when we have multiple projects in one environment that require different versions of the same build tools.

By leveraging local packages with the scripts section of our package.json (or npx $myPackage), and a version manager such as NVM we can easily manage multiple projects in the same environment.