Skip to content
This plug-in is for precompiling emberjs's handlebars templates on the server side. It integrates with grails resources plugin to allow subsequent minification gzip and more. It's a simple fork from Matt Sheehan grails-handlebars-resources plugin but unlike the latter it does not declare any resource module.
JavaScript Groovy Shell
Find file
Pull request Compare This branch is 45 commits ahead, 39 commits behind sheehan:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.

warning : I'm not using this plugin anymore. If you need an upgrade for newer versions of Ember.js and/or Handlebars, please raise an issue with the targeted versions. I promise I'll release a new version very quickly.

Ember.js templates precompiler plug-in for Grails

This plug-in precompiles EmberJS powered Handlebars templates on the server side.

It integrates with grails resources plugin to allow subsequent minification, gzip and more.

It's a fork from Matt Sheehan's grails-handlebars-resources plugin with two differences :

  • it specifically targets Handlebars templates with added EmberJS capabilities
  • it does not declare any resource module.

The goals are:

  • Cleanliness and readability: templates are compiled from plain text files (not embedded somewhere in a gsp, not in javascript strings) and can be in the same directory as your Ember Application is.
  • Performance: template precompilation meets the ember team preconization


Add this line to BuildConfig.groovy plugins section :

    runtime ":ember-templates-precompiler:0.4.3"

warning : this plugin requires rhino 1.7R4 (and above). Previous versions should be excluded from other plugins. Typically, if you use lesscss resources and handlebars resources plugin:

    compile (":lesscss-resources:") {
        excludes([ group: 'rhino', name: 'js'],[name: 'rhino'])
    runtime (":handlebars-resources:0.3.1")  {
        excludes([ group: 'rhino', name: 'js'],[name: 'rhino'])


You can see a possible usage of this plugin here : grails-ember-trek

Directory Structure Example

├── js
│   ├── emberapp
│   │   ├── app.js
│   │   ├── controllers
│   │   │   ├── user.js
│   │   │   └── tabs.js
│   │   ├── templates
│   │   │   ├── user.embbars
│   │   │   └── tab.embbars
│   │   └── views
│   │       ├── user.js
│   │       ├── tab.js

Note: I chose '.embbars' to be the arbitrary extension managed by this plugin; My first clean thought was .emberhandlebars but it was just too long for me...

Declaring Resources (following the previous example)

emberapp {
    dependsOn 'handlebars,emberjs' // previously declared modules
    resource url: 'js/ember-app/app.js'
    resource url: 'js/ember-app/controllers/user.js'
    resource url: 'js/ember-app/controllers/tabs.js'
    resource url: 'js/ember-app/templates/user.embbars', attrs: [type: 'js'], bundle:'bundle_emberapp'
    resource url: 'js/ember-app/templates/tab.embbars', attrs: [type: 'js'], bundle:'bundle_emberapp'
    resource url: 'js/ember-app/views/user.js'
    resource url: 'js/ember-app/views/tab.js'
  • attrs[type]: must be js.
  • bundle: must be set as will not default correctly. To add to default bundle use bundle_<module name>.

Using with Ember.js views

Simply give the template name (see next section) to the view:

userView = Ember.View.extend({
    templateName: 'user'

See the Ember.js Handlebars section for more information.

Template Names

Template names are based on web-app relative paths. If the relative path is js/ember-app/templates/user.embbars, then the template name will be "js/ember-app/templates/user". The .embbars extension is of course removed. The templatesRoot config value should be used to customize this name to your needs. For example, setting

grails.resources.mappers.emberhandlebars.templatesRoot = 'js/ember-app/templates'

will change the template name to just user.

The plugin also supports multiple roots, but be aware of possible name conflicts. Example:

grails.resources.mappers.emberhandlebars.templatesRoots = ['js/ember-app/templates','js/other-ember-app/templates']

The default path separator is /. If you want to change it, you can specify a value for templatesPathSeparator in the configuration. For example, adding

grails.resources.mappers.emberhandlebars.templatesPathSeparator = '.'

will change the template name to js.ember-app.templates.user (in the case you haven't set the templatesRoot config value).


All configuration variables should be relative to:

  • templatesRoot: The root folder of the templates relative to web-app. This value will be stripped from template paths when calculating the template name. Default is none.
  • templatesRoots: The same as above but accepts a list.
  • templatesPathSeparator: The delimiter to use for template names. Default is /


  • The plugin makes internal use of handlebars-xx.js and ember-template-compiler.js which I found to be part of the distribution of ember after building ember.js myself. Those resources are not exposed.
  • IntelliJ has a plugin for Handlebars, you can use it to highlight syntax of *.embbars files.



  • versioning policy from now on : version numbers mirrors Ember's version numbers for the sake of clarity.
  • compatible with ember-1.0.0.js (and ember-1.0.0-rc.7.js)


  • compatible with ember-1.0.0-rc.7.js


  • compatible with ember-1.0.0-rc.5.js and ember-1.0.0-rc.6.js


  • compatible with ember-1.0.0-rc.1 & ember-1.0.0-rc.2 & current head
  • got rid of ember itself and envjs -> results in performance enhancement
  • log each compiled template name: debug "org.grails.plugin.ember.handlebars" in config/log4j closure


  • updates : ember-1.0.0-rc.1 and handlebars-1.0.rc.3
  • in the previous version ember code was a little hacked, this is no longer the case due to the usage of EnvJs.


  • ember update: ember-1.0.0-pre.4 and handlebars-1.0.rc.2.js


  • non-blocking bug fix (learn more in commits comments)


  • support for multiple templates roots


  • first release : ember-1.0.pre.js and handlebars-1.0.rc.1.js
Something went wrong with that request. Please try again.