Skip to main content

Automatic Handlebars template compilation in WebStorm

Using WebStorm with EmberJS, I needed to precompile my Handlebars templates on the go. The Handlebars precompiler works, but using it with EmberJS requires some additional modifications, and getting it to work with directories seemed to be a bit problematic(a wildcard File Watchers issue in WebStorm). I tried to install Ember-Precompile but, being currently on Windows, I gave up because of node-gyp.js rebuild issues. Eventually I found the excellent ember-template-compiler module that did the trick for me.

Setup

There are a couple of dependencies that needs to be installed to get this to work:

  1. WebStorm and NodeJS of course.
  2. EmberJS - this is not actually a dependency, but definitely a requirement.
  3. Handlebars@1.1 - an ember-template-compiler dependency.
  4. Walk - used to traverse the directories where the templates are situated.
My template file structure looks like the following:


I needed to compile those templates into a single templates.js file to be included in my project. To do that I created the following compile.js file in the root directory of my project:

var compiler = require('ember-template-compiler');
var compiler = require('ember-template-compiler');
var fs = require('fs');
var walk = require('walk');
var templatesjs = "js/app/templates.js";

var walker  = walk.walk('js/app/templates', { followLinks: false });

fs.writeFile(templatesjs, '//NOTE: This is a generated file. Please do not edit. Your changes will be overridden!\n\n');

String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

walker.on('file', function(root, stat, next) {
    if(stat.name.endsWith(".hbs")){
        var template = fs.readFileSync(root + '/' + stat.name).toString();
        var input = compiler.precompile(template).toString();
        var output = "Ember.TEMPLATES['" + stat.name.replace(".hbs", "") + "'] = Ember.Handlebars.template(" + input + ");";
        fs.appendFile(templatesjs, output + "\n");
    }

    next();
});


File Watchers

In WebStorm, select File Watchers under Settings, and click on the Add button.

You will be presented with the following window:



  • Under File type choose Handlebars/Mustache.
  • Scope needs to be create and I will show you how in just a moment.
  • Program points to your NodeJS executable
  • Argument is the compile.js script we created above.
  • The Working directory points to your project directory
  • And of course Name is the name of the watcher.
By clicking on the ... button beside the Scope dropdown, the following window will open:


Click on the Add button to create a new scope. The scope allows the Watcher to observe a specific folder for specific files, in other words our templates folder for our *.hbs files.
  • Name is the name of the scope - just an identifier.
  • Pattern is the files that needs to be matched and observed: file:js/app/templates/*.hbs 
Thats it. Click on OK and under the Scope dropdown, select the scope you just created.

Now every time you modify one of your templates, it will automatically be precompiled. Just remeber to include template.js.



Popular posts from this blog

EmberJS development using the esapiserver

I started out using the fixture and local storage adapters in EmberJS, but experienced that the limitations that these adapters have, would turn out be a pain later when it was time to release my app - I wanted to make sure that what I test, was consistant with what I would release, hence the esapiserver. InstallationInstall the gem $ gem install esapiserver Start up your mongoDB server $ mongoD Start the Ember Sinatra/MongoDB API server $ easapiserver EmberJS To get EmberJS and the esapiserver to play together, we need to configure our RESTAdapter App.ApplicationAdapter = DS.RESTAdapter.extend namespace: 'api' host: 'http://127.0.0.1:4567' corsWithCredentials: true Because we are using an "external server", we have to enable CORS support in EmberJS. (more about that here) Now, lets assume that we have the following model setup in EmberJS: App.Post = DS.Model.extend content: DS.attr('string') comments: DS.hasMany(&#…