gulp-handlebars

Handlebars plugin for gulp

gulp-handlebars

Handlebars plugin for gulp 3

Install gulp-handlebars as a development dependency:

npm install --save-dev gulp-handlebars

gulp-declare and gulp-wrap can be used to safely declare template namespaces and make templates available for use in the browser.

First, install development dependencies:

npm install --save-dev gulp-handlebars gulp-wrap gulp-declare gulp-concat

Given the following directory structure:

├── gulpfile.js              # Your gulpfile
└── source/                  # Your application's source files
    └── templates/           # A folder containing templates named with dot notation
        └── home.header.hbs  # A template that will be available as MyApp.templates.home.header

To compile all templates in source/templates/ to build/js/templates.js under the MyApp.templates namespace:

var handlebars = require('gulp-handlebars');
var wrap = require('gulp-wrap');
var declare = require('gulp-declare');
var concat = require('gulp-concat');
 
gulp.task('templates', function(){
  gulp.src('source/templates/*.hbs')
    .pipe(handlebars())
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare({
      namespace: 'MyApp.templates',
      noRedeclare: true, // Avoid duplicate declarations 
    }))
    .pipe(concat('templates.js'))
    .pipe(gulp.dest('build/js/'));
});

The template's filename is combined with the namespace, so the resulting build/js/templates.js would look like:

this["MyApp"] = this["MyApp"] || {};
this["MyApp"]["templates"] = this["MyApp"]["templates"] || {};
this["MyApp"]["templates"]["home"] = this["MyApp"]["templates"]["home"] || {};
this["MyApp"]["templates"]["home"]["header"] = Handlebars.template(function() { /* compiled template function */ });

See the namespaceByDirectory example if you'd like to compile templates with a mapping that looks like this:

File pathNamespace path
source/templates/App.hbsMyApp.templates.App
source/templates/App/header.hbsMyApp.templates.App.header
source/templates/App/footer.hbsMyApp.templates.App.footer
source/templates/Other.item.hbsMyApp.templates.Other.item

See the gulp-define-module documentation for details on how to define templates as AMD, Node, CommonJS, and hybrid modules.

See the amd example for a full example of compiling templates to AMD modules.

gulp-handlebars makes the following available for use in gulp-define-module's wrapper template option:

  • <%= handlebars %> - The Handlebars template, wrapped in a call to Handlebars.template()
  • <%= contents %> - The bare Handlebars template (not wrapped).

gulp-handlebars also sets a default options.require of { Handlebars: 'handlebars' } for gulp-define-module so Handlebars will be present in when defining AMD, Node, CommonJS, or hybrid modules. You can change this by passing a different options.require when you invoke gulp-define-module.

See the ember example for a full example of compiling templates for Ember.

You can use ember-handlebars to compile templates for use within Ember:

gulp.task('templates', function(){
  gulp.src('source/templates/*.hbs')
    .pipe(handlebars({
      handlebars: require('ember-handlebars')
    }))
    .pipe(wrap('Ember.Handlebars.template(<%= contents %>)'))
    .pipe(declare({
      namespace: 'Ember.TEMPLATES',
      noRedeclare: true, // Avoid duplicate declarations 
    }))
    .pipe(concat('templates.js'))
    .pipe(gulp.dest('build/js/'));
});

Note: When compiling Ember templates to a module using gulp-define-module, be sure to set options.context.handlebars accordingly:

gulp.task('templates', function(){
  gulp.src('source/templates/*.hbs')
    .pipe(handlebars({
      handlebars: require('ember-handlebars')
    }))
    .pipe(defineModule('amd', {
      context: {
        handlebars: 'Ember.Handlebars.template(<%= contents %>)'
      }
    }))
    .pipe(gulp.dest('build/js/'));
});

You can use different versions of Handlebars by specifying the version in your package.json and passing it as options.handlebars:

{
  "devDependencies": {
    "handlebars": "^1.3.0"
  }
}
gulp.task('templates', function(){
  gulp.src('source/templates/*.hbs')
    .pipe(handlebars({
      handlebars: require('handlebars')
    }))
    .pipe(wrap('Handlebars.template(<%= contents %>)'))
    .pipe(declare({
      namespace: 'MyApp.templates',
      noRedeclare: true, // Avoid duplicate declarations 
    }))
    .pipe(concat('templates.js'))
    .pipe(gulp.dest('build/js/'));
});

The runtime you include on the client side MUST match the version you compile templates with. You cannot use the the 2.x runtime with 1.x templates. The handlebars1 example copies the runtime from node_modules/handlebars/dist/handlebars.runtime.js and uses that on the client side. Follow a similar pattern in your application to keep the runtime up to date with the compiler.

This example will make templates available for loading via Node's require:

var handlebars = require('gulp-handlebars');
var defineModule = require('gulp-define-module');
 
gulp.task('templates', function(){
  gulp.src(['templates/*.hbs'])
    .pipe(handlebars())
    .pipe(defineModule('node'))
    .pipe(gulp.dest('build/templates/'));
});

Templates can then be used within Node as such:

var appTemplate = require('./build/templates/App.Header.js');
var html = appTemplate(data);

See the singleModule example if you'd like to have a single module that contains all of your templates that can be used like so:

var templates = require('./templates');
var output = templates.App.header();

The example below removes any partial and replaces it with the text foo.

handlebars({
  processASTfunction(ast) {
    ast.statements.forEach(function(statementi) {
      if (statement.type === 'partial') {
        ast.statements[i] = { type: 'content', string: 'foo' };
      }
    });
  }
})

Type: Object

Compiler options to pass to Handlebars.precompile().

Type: Function

A function which will be passed the parsed Handlebars Abstract Syntax Tree. You can modify the AST in place or return a new AST to change the source of the precompiled template.

Type: Object

Handlebars library to use for precompilation. By default, the latest stable version of Handlebars is used.