This is how you can detect existing Node.js and npm, or automatically install a temporary Node.js if none is already installed. About the only things needed are
git, which are usually available on all development / CI machines.
(I’m planning to work around the requirements for
git, so those won’t even be needed in the future.)
Put this at the top of your
SHELL := /bin/bash NODE_PATH = $(shell ./find-node-or-install) PATH := $(NODE_PATH):$(shell echo $$PATH)
Then download the
find-node-or-install script to the same directory:
$ curl https://raw.github.com/hugojosefson/find-node-or-install/master/find-node-or-install -o find-node-or-install $ chmod +x find-node-or-install
Now you will have access to
npm inside the
Makefile, and can use them just like normal. The script runs very quickly if you already have
node on your path, or if the script has run before. If no
node is found, it automatically uses nvm to install the latest 0.10.x version of Node.js to the user’s temp directory.
Doing this can be good for when you want to use some npm module in your build, for example Component package manager, Yeoman, Grunt or Bower, and you don’t want to bother your colleagues in the team and force them to install Node.js. Or for example make it a lot smoother to get the build running on any Continuous Integration server.
Example with locally installed npm module, rather than
npm install -g
While it is tempting to expect other people to
npm install -g whatever tools you need before building, it’s not very polite to those who have to figure out what they need to do before they can run
make like they expect. Also, you have to document what they have to do.
A better way, in my opinion, is to do that documentation in the form of additions to the
Makefile. What I mean is that if you have to specify in documentation what is needed to run the build, you can instead specify it to the computer, and the computer can install the necessary tools automatically.
Let me show you how for example the Component package manager can be used in a
Makefile, while not forcing other developers to globally install the npm module for it.
The first step is to declare a variable in the
Makefile, which points to where the
component executable is located when its npm module is installed locally in
node_modules. To find out where, first install it locally:
$ npm install component
Then look inside
./node_modules/component/ and find the executable. Usually there is some directory named
bin or similar. In this case, I found it at
node_modules/component/bin/component. That’s what I put in my
COMPONENT_BIN = node_modules/component/bin/component
Then I use that variable in place of the word
component whenever I need to call it. For example, instead of:
components: component.json component install --dev
components: $(COMPONENT_BIN) component.json $(COMPONENT_BIN) install --dev
As you may notice, I also added
$(COMPONENT_BIN) as a dependency to all targets which need it. This way I can specify how to install it to
$(COMPONENT_BIN): npm install email@example.com
The full example of this, in combination with
find-node-or-install, is at github.com/hugojosefson/find-node-or-install. I found details on how dependencies and targets in
Makefiles work at www-personal.umich.edu/~ppannuto/writings/makefiles.html.
Showing the cool stuff you can do with things written for Node.js, is probably a better way to get other people on your side, than forcing them to install tools before they can even see what good it does! :)