Running gulp tasks with make
One of my goals when developing anything is to make other devs' lives easier. I want them to be able to clone a repo and with a single command be ready to go.
Make has been around for quite some time now and it is still pretty handy.
I have some toy projects using Node.js, and one thing I like about
npm is that you can have all your dependencies within the scope (directory) of your project under
node_modules. Some of these dev dependencies are meant to be installed as global modules (
npm install -g <module>), requiring you to have them installed beforehand – and this is what I strive to avoid.
If you simply run
npm install all your runtime and dev dependencies will be installed under that
node_modules directory, and every package that was meant to be installed globally will have an executable under
node_modules/.bin. Knowing that, you can write very simple
Makefiles with goals like
test:;@node_modules/.bin/mocha¹. NPM itself provides a way to run scripts, but it is somewhat limiting.
The project that I'm currently working on is using gulp to build our web client assets and it is essentially a command-line module, requiring it to be installed globally so one could run
gulp run or
gulp test, for example. In the spirit of trying to avoid external dependencies to the project, I thought it would be nice if we could run gulp tasks without having it installed globally or having to prepend
node_modules/.bin every time. So, although we are not using the following
Makefile on our project yet, I found the exercise of writing a
make "wrapper" for
gulp very interesting.
bin = node_modules/.bin/gulp
files=$(filter-out Makefile,$(wildcard *))
install:; @npm install
$(files) %:;@$(bin) $@
.PHONY: install $(files)
bin = node_modules/.bin/gulp: this points to gulp's executable under
node_modules/.bin – it could be
grunt-cli if you will.
files=$(filter-out Makefile,$(wildcard *)): this selects every file, but the Makefile itself, in the root directory.
install:; @npm install: defines a default goal; when running just
npm install all your dependencies.
$(files) %:;@$(bin) $@: Here's where the actual wrapper lives, it simply redirects all calls to whatever is defined as
.PHONY: install $(files): tells make that
install and all existing filenames are not associated with files.
For sure there's room for improvement, but this has suited my needs so far.