NodeJS virtual environments to the rescue for more productivity

I started having difficulties running Harp on my Mac, after some OSX El Capitan software update that affected my NodeJS installation.

I was getting the following error when trying to re-install Harp:

...
npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/Cellar/node/6.2.0/bin/node" "/usr/local/bin/npm" "install" "harp"
npm ERR! node v6.2.0
npm ERR! npm  v3.8.9
npm ERR! code ELIFECYCLE

npm ERR! node-sass@3.4.2 postinstall: `node scripts/build.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the node-sass@3.4.2 postinstall script 'node scripts/build.js'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
...

So what happened is that my installed Node was upgraded at some point to version 6.2, and that was problematic to the installation of some Harp dependencies such as node-sass.

After some thinking, I decided to try nodeenv as a solution to run the different NodeJS and NPM versions that are required by the different applications or development frameworks I need to support and the tools I need to test on a regular basis.

It's what I am already used to doing for my Python development work. It brings a huge productivity advantage and, after a few years of practice, I now know the tricks.

Setup of a virtual environment using nodeenv

The nodeenv tool requires Python. You may install it globally on the system using pip:

/usr/local/bin/pip install nodeenv

Collecting nodeenv
  Downloading nodeenv-0.13.6.tar.gz
Building wheels for collected packages: nodeenv
  Running setup.py bdist_wheel for nodeenv ... done
  Stored in directory: /Users/kamon/Library/Caches/pip/wheels/f4/b1/75/b4e87d2453c1d51780d43745f8f9a3127899867d87078ed4de
Successfully built nodeenv
Installing collected packages: nodeenv
Successfully installed nodeenv-0.13.6

We can now run it to check available versions of Node:

$ nodeenv --list
...
0.12.12    0.12.13    0.12.14    0.12.15    4.0.0    4.1.0    4.1.1    4.1.2
4.2.0    4.2.1    4.2.2    4.2.3    4.2.4    4.2.5    4.2.6    4.3.0
4.3.1    4.3.2    4.4.0    4.4.1    4.4.2    4.4.3    4.4.4    4.4.5
4.4.6    4.4.7    5.0.0    5.1.0    5.1.1    5.2.0    5.3.0    5.4.0
5.4.1    5.5.0    5.6.0    5.7.0    5.7.1    5.8.0    5.9.0    5.9.1
5.10.0    5.10.1    5.11.0    5.11.1    5.12.0    6.0.0    6.1.0    6.2.0
6.2.1    6.2.2    6.3.0    6.3.1

Next I created my new NodeJS environment, under a special directory where I want to group all my virtual environments, i.e. /Users/kamon/.nodeenvs, using version 4.4.7. As suggested by the nodeenv documentation, I used the prebuilt option so it is faster to install.

$ nodeenv --node=4.4.7 --prebuilt /Users/kamon/.nodeenvs/env-harp-prebuilt
* Install node (4.4.7)... done.

$ . /Users/kamon/.nodeenvs/env-harp-prebuilt/bin/activate 
(env-harp-prebuilt) $

The version of NPM installed is a compatible one for my needs related to Harp:

(env-harp-prebuilt) $ npm -v
2.15.8

We are now ready to install the Harp software, the new way, with isolation.

Note that anytime you want to deactivate the environment, you would use the deactivate_node command:

(env-harp-prebuilt) $ deactivate_node
$

Install Harp in the Node virtual environment

As usual, we can install globally with NPM, but this time the installation is based on a virtual Node environment.

(env-harp-prebuilt) $ npm install -g harp
...
-
> spawn-sync@1.0.15 postinstall /Users/kamon/.nodeenvs/env-harp-prebuilt/lib/node_modules/harp/node_modules/terraform/node_modules/node-sass/node_modules/cross-spawn/node_modules/spawn-sync
> node postinstall

-
> node-sass@3.4.2 install /Users/kamon/.nodeenvs/env-harp-prebuilt/lib/node_modules/harp/node_modules/terraform/node_modules/node-sass
> node scripts/install.js

Binary downloaded and installed at /Users/kamon/.nodeenvs/env-harp-prebuilt/lib/node_modules/harp/node_modules/terraform/node_modules/node-sass/vendor/darwin-x64-46/binding.node

> node-sass@3.4.2 postinstall /Users/kamon/.nodeenvs/env-harp-prebuilt/lib/node_modules/harp/node_modules/terraform/node_modules/node-sass
> node scripts/build.js

` /Users/kamon/.nodeenvs/env-harp-prebuilt/lib/node_modules/harp/node_modules/terraform/node_modules/node-sass/vendor/darwin-x64-46/binding.node ` exists. 
 testing binary.
Binary is fine; exiting.
/Users/kamon/.nodeenvs/env-harp-prebuilt/bin/harp -> /Users/kamon/.nodeenvs/env-harp-prebuilt/lib/node_modules/harp/bin/harp
harp@0.20.3 /Users/kamon/.nodeenvs/env-harp-prebuilt/lib/node_modules/harp
├── escape-html@1.0.3
├── commander@2.0.0
├── pause@0.1.0
├── parseurl@1.3.0
├── async@0.2.9
├── envy-json@0.2.1
├── mime@1.2.11
├── send@0.13.0 (destroy@1.0.3, escape-html@1.0.2, fresh@0.3.0, etag@1.7.0, statuses@1.2.1, range-parser@1.0.3, ms@0.7.1, depd@1.0.1, mime@1.3.4, debug@2.2.0, http-errors@1.3.1, on-finished@2.3.0)
├── fs-extra@0.18.2 (jsonfile@2.3.1, graceful-fs@3.0.9, rimraf@2.5.4)
├── connect@2.30.2 (cookie@0.1.3, bytes@2.1.0, cookie-signature@1.0.6, utils-merge@1.0.0, on-headers@1.0.1, fresh@0.3.0, vhost@3.0.2, content-type@1.0.2, response-time@2.3.1, basic-auth-connect@1.0.0, cookie-parser@1.3.5, depd@1.0.1, qs@4.0.0, serve-favicon@2.3.0, connect-timeout@1.6.2, http-errors@1.3.1, method-override@2.3.6, debug@2.2.0, morgan@1.6.1, finalhandler@0.4.0, express-session@1.11.3, type-is@1.6.13, serve-static@1.10.3, multiparty@3.3.2, csurf@1.8.3, errorhandler@1.4.3, compression@1.5.2, body-parser@1.13.3, serve-index@1.7.3)
├── download-github-repo@0.1.3 (download@0.1.19)
└── terraform@0.13.2 (lru-cache@2.7.0, marked@0.3.5, coffee-script@1.10.0, ejs@2.3.4, postcss@5.0.12, stylus@0.47.3, harp-minify@0.3.3, harp-jade@1.9.3-bc.4, lodash@3.10.1, autoprefixer@6.1.0, less@2.5.3, node-sass@3.4.2)

Start the Harp server

Let's start our static site generator and server.

(env-harp-prebuilt) $ harp --help

  Usage: harp [options] [command]
  ...  

(env-harp-prebuilt) $ harp server

Done! I am back to being productive with my Harp-based projects, and when needed, I am able to create new isolated environments to work on other NodeJS projects.

comments powered by Disqus

Need help for your project?

I can contribute to your project, working on a specific task, or doing all the coding based on your specifications using a web framework / CMS.