Node.js, CoffeeScript and Eco Templates

Lately, I’ve had a desire to use CoffeeScript to create a one page application, utilizing Backbone.js.  So I decided to take this opportunity to learn Node.js and use the Express framework for the application server.  While doing this I realized that I was going to have a lot of CoffeeScript code that would be used on the client side.  For this, I wanted a Ruby on Rails 3.1.x style asset pipeline.  I found a library called connect-assets, which was inspired by Rails 3.1.x asset pipeline and the sprockets gem.  Also, I needed to pick a client side template engine.  There are many options to choose from, and I decided to use Eco templates.

I chose Eco templates for two reasons.  First, they utilize CoffeeScript for their processing.  Secondly, they can be complied to JavaScript on the server.  To me, this is a benefit over many of the template engines that exist that require some sort of markup to be sent to the client and then compiled to be utilized by Backbone.js.  The other benefit of using the Eco templates is that I can also use them as the template engine to render the HTML views trough Express.

The connect-assets library really seemed to do what I was looking for.  It combines all of you JavaScript and CoffeeScript per the directives that you specify.  It defers to Stylus to handle all of the CSS processing.  Under the hood it uses a secondary library, snockets, to process all of the JavaScript and CoffeeScript.  However, it does not handle Eco templates natively.  Also, it will not allow you to provide multiple file extensions to handle processing a single file through multiple processors, for example  Here is the code that I came up with to handle processing Eco templates and provide them in a global JST object.  The JST object is created in a similar way that Jammit, by DocumentCloud, does it.

assets = require 'connect-assets'
eco = require 'eco' =
  match: /\.eco$/
  compileSync: (sourcePath, source) ->
    fileName = path.basename sourcePath, '.eco'
    directoryName = (path.dirname sourcePath).replace "#{__dirname}/assets/templates", ""
    jstPath = if directoryName then "#{directoryName}/#{fileName}" else fileName
    (function() {
      this.JST || (this.JST = {});
      this.JST['#{jstPath}'] = #{eco.precompile source}

This code does work for my needs and gets me the global JST object with all of the Eco templates compiled to JavaScript and stored in the JST object.  You will just need to put the following code into your view to have connect-assets render the correct JavaScript.

<%- js '/templates/index'  %>

Ultimately, this code and the processing of multiple file extensions should be handled in snockets.  This may be something that I will contribute to the project in the future.

« Ignoring Extra Elements in mongoDB C# Driver Python Meta-programming Gotcha with __getattr__ »