SailsJS with Handlebars



Update: Sails 0.12+ ships with Handlebars support out of the box. You just need to pass in the --viewEngine option when generating a new Sails App. So don’t worry about anything written below. Just do something like this:

sails new myApp --viewEngine handlebars

The information below is just for posterity. 🙂

The Problem

I like SailsJS. I’ve been using it for a pet project recently and it’s a great way to create all the boilerplate for a webserver. I definitely prefer it over starting an ExpressJS server from scratch.

Sails has a lot of pros. I love the model/controller scaffolding, Waterline, using middleware as policies, and enforcing API-driven development. However, I’m a big fan of Handlebars and I really don’t like EJS so I thought that was going to be a blocker for me.

Fortunately, I have a little hack which lets me use Handlebars with Sails. Before starting down this path, I took a look at the StackOverflow answers on how to get SailsJS working with Handlebars. None of the replies seemed suitable to me. Most require you to pass in your layout and partials properties to every res.view() call. There isn’t much information on using Handlebars Helpers either. What I wanted was to just do this:


res.view();

And I want it to pull the correct layout and all the available partials. I also want it to be able to read in the correct Handlebars Helpers. All the benefits that Sails + EJS gives you, except using Handlebars instead.

The Solution

The solution was hidden inside Christopher Pappas’ closed pull request. I used his code to modify Sails Core to use express3-handlebars. If you want to use Handlebars as your view engine, modify your config/views.js to this:


module.exports = {
  engine: 'handlebars',
  layout: 'main.handlebars', //whatever your default layout is
  helpers: require('./helpers') //pull in your helpers (I store it in config/helpers.js)
}

Here’s how you should structure your views/ directory:


views/
  layouts/
    main.handlebars

  partials/
    partial1.handlebars
    partial2.handlebars

  controller1/
    action1.handlebars
    action2.handlebars

All the partials within the root partials/ directory will be available for use in any view.

Installation

Remember that this is a hack that has only been tested in Sails 0.9.9. Sails 0.10+ introduces some changes to how view engines are created, so this code won’t work there as-is, but it shouldn’t be hard to port over.

In terms of installation, I am pulling in Sails from my Handlebars branch. Here’s what my package.json looks like:


//within package.json
"sails": "git://github.com/tilomitra/sails.git#handlebars"

Then, instead of installing Sails globally via npm -g install sails, I install it locally via npm install sails. This pulls in my Handlebars-enabled version of Sails from GitHub.

I know this isn’t acceptable for a lot of people, but it did the job for me. One notable flaw is the inability to update as Sails updates. However, the only file that I modified was hooks/views/index.js, so it’s not hard to port it over. I will be trying out Sails 0.10.x eventually because it has support for model associations (something which I badly need), so I’ll post an update to this post if I am able to get Handlebars working with Sails 0.10.x.

Happy Coding!


Credit to Christopher Pappas who wrote the original code that made this possible, and to Balderdash for creating Sails.

  1. hi, thanks for this man ! I do not want to use the cluttery EJS templating.. 😀
    i am trying to do this fix on v0.10 because it has some nice things .. did you ever succeed and is it up somewhere or your github repo ?

  2. Thanks for he post, I also would like to use handlebars badly but I got into a lot of issues trying by myself and couldn’t use layouts at all, which is such basic feature that I cannot work without it.

    I didn’t try your solution for two reasons:
    – Since March, the v0.10 hs been released and I would like to jump into it, so I cannot use this solution. Did you find any workaround for the new sails version?
    – Can you use the partials from the server and the client side? Something I LOVED in ejs+sails is that the partials where available from the client, which makes things potentially much better. It is obvious that’s usable from the server here, but what about the client? Does the same partial are somehow available from the browser?

    I also hate EJS, I don’t like the syntax and the project died a few months ago (github), someone else is now maintaining it, but anyway I wasn’t able to use partials from the server side with sails…

    1. I gotta update this for v0.10. Once I get back to SailsJS land, I’ll be sure to do this. Re. using partials on the client and server, yes this is possible. I’ll update my Node Boilerplate on GitHub with that code. Contact me via email to learn more about this!

Leave a Reply

Your email address will not be published. Required fields are marked *