Marcus' Homepage

Revisiting my watch-script (gulp scripts with global modules)

A long time ago I wrote a post about how I used a bash-script to compile my stylesheets and JavaScripts. Since then I’ve changed my workflow and replaced bash with Node.js and Gulp instead. Gulp is one of the big task runners that are available for Node.js, and I’m using it since I prefer their way of setting up my tasks.

On my own projects I normally embed my Gulp tasks into the server application (look at my recently updated VodkaKit for an example), but it’s also possible to write separate scripts that you can run even in projects that aren’t using Node.js, which is actually more common than you might think since a lot of front-end modules are written for Node.js.

Running gulp with global modules

Today I worked on a project where I had to extend some CSS in an existing template. The project was already using sass, but I also wanted to use autoprefixer so I don’t have to think about vendor prefixes and such in my CSS. I looked into adding either Grunt or Gulp, but I quickly realized that both are built to run with their modules installed locally.

This means that I would have to create a package.json, add dependencies, install them with npm install and then I can start working on my gulpfile. I wanted to add as few files as possible in this project, so I started looking into if I could use globally installed node-modules instead. Turns out it’s pretty simple since require works with full paths (at least on *nix-systems).

Behold, my single-file gulpfile:

var nodedir = process.env.NODE_DIR || "/usr/local/lib/node_modules",
    gulp = require(nodedir+'/gulp'),
    autoprefixer = require(nodedir+'/gulp-autoprefixer'),
    cssGlobbing = require(nodedir+'/gulp-css-globbing'),
    sass = require(nodedir+'/gulp-sass');

var cssDir = __dirname + '/extended.sass'

gulp.task('styles', function() {
  console.log('Frontend changes: Compiling stylesheets');
  return gulp.src(cssDir)
    .pipe(cssGlobbing({ extensions: ['.css', '.scss', '.sass'] }))
    .pipe(sass({ indentedSyntax: true }))
    .pipe(autoprefixer())
    .pipe(gulp.dest('.'))
})

gulp.watch(cssDir, ['styles']);

I won’t go into detail on what this script is doing, it’s pretty much a regular gulpfile and their documentation will probably help you more. The only magic here is the first line:

var nodedir = process.env.NODE_DIR || "/usr/local/lib/node_modules",

It’s the path to the folder where npm installs global node modules, I’ve set the default to where it’s located on a default installation on OS X, but it can easily be overrided either with an environment variable (or by editing the script). I then prefix all requires with this. I then prefix all my require's with this variable and run the script via node (the gulp command won’t work since it still tries to find a locally installed gulp).

Thanks for reading if you made it this far!