This recipe shows how to set up Handlebars to precompile your templates, including LiveReload integration.
Install some gulp plugins:
$ npm install --save-dev gulp-handlebars gulp-define-module gulp-declare gulp-wrap gulp-concat
- gulp-handlebars precompiles raw
.hbs
templates into JavaScript - gulp-define-module and gulp-declare are used together to package up the compiled JavaScript template into a namespaced module
Install Handlebars as a bower component:
$ bower install --save handlebars
- You need this so you can include the Handlebars runtime in your page – even compiled templates depend on this. (You won't need to include the entire Handlebars library though.)
// bower.json
{
"name": "MyApp",
"dependencies": {
...
},
"devDependencies": {
...
},
"overrides": {
"handlebars": {
"main": ["handlebars.runtime.js"]
}
}
}
- It's a good idea to verify you've installed the same version of Handlebars as the one used by internally by gulp-handlebars, to guarantee compatibility between the runtime and your compiled templates. Look in
node_modules/gulp-handlebars/package.json
under"dependencies"
and check the handlebars version – if necessary, you can ask bower to install that specific version, e.g.bower install --save handlebars#^1.3.0
.
gulp.task('templates', () => {
return gulp.src('app/templates/*.hbs')
.pipe($.plumber())
.pipe($.handlebars())
.pipe($.defineModule('plain'))
.pipe($.declare({
namespace: 'MyApp.templates' // change this to whatever you want
}))
.pipe($.concat('templates.js'))
.pipe(gulp.dest('.tmp/templates'));
});
This compiles .hbs
files into templates.js
file in the .tmp/templates
directory.
gulp.task('partials', function() {
return gulp.src('app/templates/partials/*.hbs')
.pipe($.plumber())
.pipe($.handlebars())
.pipe($.wrap('Handlebars.registerPartial(<%= processPartialName(file.relative) %>, Handlebars.template(<%= contents %>));', {}, {
imports: {
processPartialName: function(fileName) {
// Escape the output with JSON.stringify
return JSON.stringify(path.basename(fileName, '.js'));
}
}
}))
.pipe($.concat('partials.js'))
.pipe(gulp.dest('.tmp/templates'));
});
This compiles the .hbs
files inside the templates/partials
directory into partials.js
file in the .tmp/templates
directory.
gulp.task('html', ['styles', 'templates', 'partials', 'scripts'], () => {
...
gulp.task('serve', ['styles', 'templates', 'partials', 'scripts', 'fonts'], () => {
...
Edit your serve
task so that (a) editing an .hbs
file triggers the templates
task, and (b) the browser is reloaded whenever a .js
file is generated in .tmp/templates
:
gulp.task('serve', () => {
- runSequence(['clean', 'wiredep'], ['styles', 'scripts', 'fonts'], () => {
+ runSequence(['clean', 'wiredep'], ['styles', 'scripts', 'templates', 'partials', 'fonts'], () => {
...
gulp.watch([
'app/*.html',
'app/images/**/*',
'.tmp/fonts/**/*',
+ '.tmp/templates/**/*.js',
]).on('change', reload);
gulp.watch('app/styles/**/*.scss', ['styles']);
+ gulp.watch('app/templates/*.hbs', ['templates']);
+ gulp.watch('app/templates/partials/*.hbs', ['partials']);
gulp.watch('app/scripts/**/*.js', ['scripts']);
gulp.watch('app/fonts/**/*', ['fonts']);
gulp.watch('bower.json', ['wiredep', 'fonts']);
});
});
Put your .hbs
files in app/templates
and app/templates/partials
(if you using partials), and include in your HTML after the bower components:
<!-- build:js scripts/vendor.js -->
<!-- bower:js -->
...
<!-- endbower -->
<!-- endbuild -->
<!-- build:js scripts/main.js -->
+ <script src="templates/templates.js"></script>
+ <script src="templates/partials.js"></script>
<script src="scripts/main.js"></script>
<!-- endbuild -->
You would then render the template like this:
var html = MyApp.templates.foo();
The MyApp.templates
namespace can be anything you want – change it in the templates
task.