Watch, coffee, node, and make

Watchers such as nodemon are great tools for easing the pain of testing, but they tend to be oriented towards specific tasks. nodemon, for instance, Really Wants to be watching a directory and restarting an application script when it changes:

$ npm install nodemon
$ nodemon app.js

One of my recent projects opted to use coffeescript for across the front-end/back-end spectrum, with the caveat that only compiled javascript would actually be served up to the client side. We created a simple makefile to ensure that client side files are compiled before the test server is run:

# Run the test server
run: generate-js

# Compile .coffee files in public/
  @find public -name '*.coffee' | xargs coffee -c

# Uglify/compress generated javascript
generate-js: compile-coffee
  @find public -name '*.js' | xargs uglifyjs --overwrite

On my first pass, we tried to take advantage of nodemon‘s convenient -x, --exec flag for running scripts through alternative interpreters. And the good news is that make counts. So long as the options passed to -x are in the form [app] [script], nodemon will happily run non-node applications

$ nodemon -x "make run -f" Makefile

Take Two.

Simple enough, right? It should be. But even though nodemon is happy to run make, it isn’t so good about terminating the child processes spawned by make. Outside of Windows, nodemon uses child_process.kill to restart the application. That’s good enough to get make, but it won’t actually kill the coffee process started in the Makefile.

Our second attempt opted for the inelegant strategy of compiling from within the app. This time, we patched the main script (we’re using express) to run make when the script is run inside the development environment:

# in
app.configure 'development', ->
  child_process  = require 'child_process'
  child_process.exec 'make', ['generate-js']```

Ugly, but functional. The final step was to ensure that the javascript files compiled by the app would not trigger a restart loop when they were updated. The easiest solution was to just update `.nodemonignore` to overlook the compiled files in `public/`:

spec/ node_modules/ public/javascripts/*.js```

Coffee compiles. App launches. Ship it.