Pages

Monday, September 12, 2016

Inmadusa.com [Part 3]: Use gulp to automatically compile handlebar templates on save

On my previous post I described how to use the handlebars cli to compile multiple templates into a single javascript file. Running the compiler by hand after every change is a pain, so the next natural thing that you would want is some form of file watcher that automatically runs it.

There are probably many tools to accomplish this, but I chose gulp.js because I knew I would need do other build processing besides compile templates and I like gulp as a build system. The gulp task to compile the templates looks like this:
var gulp = require('gulp');
var handlebars = require('gulp-handlebars');
var wrap = require('gulp-wrap');
var declare = require('gulp-declare');
var concat = require('gulp-concat');

gulp.task('templates', function() {
    return gulp.src('templates/*.hbs')
    .pipe(handlebars({
      handlebars: require('handlebars')
    }))
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare({
      namespace: 'Inmadusa.templates',
    }))
    .pipe(concat('templates.js'))
    .pipe(gulp.dest('js/'));
});

Gulp creates a stream of files that you pipe through a set of processors. In this case a stream is created with all the files with the .hbs extension and the process goes like this:

  1. Each file is compiled using handlebars.
  2. The result is wrapped within a javascript call to Handlebars.template(). Note that the function is not executed, the code will eventually be written to the output file. It will execute when the browser loads it.
  3. Then, this piece of javascript will be assigned to a namespace called 'Inmadusa.templates'. So, if the file is called Inicio.hbs, the resulting file will have this object hierarchy: this['Inmadusa']['templates']['Inicio'] = Handlebars.template(<CONTENT>);
  4. Next, all such declarations (one per .hbs file) will be concatenated together into a file named 'templates.js'
  5. Finally, the file will be written into a folder named 'js'.

Notice that there is a weird part in step #2: handlebars: require('handlebars'). We imported the 'gulp-handlebars' package at the top of the file, and now we imported the 'handlebars' package here? This is to ensure that the same version of handlebars that is used on the page is used to compile the templates.

With this in place, all that is left is to add a watch task to recompile the files when they change:
gulp.task('watch', function() {
    gulp.watch('templates/*.hbs', ['templates']);
});

This solution requires developers to install the gulp-ci as a global package on their systems. On a subsequent post I will cover how we can use npm scripts to kick off the build process so that the project does not rely on a global packages.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.