How to render jade templates on the server

January 11, 2013 Georg Apitz

The best way for Google and friends to crawl and index a page is by finding static content. With applications that make heavy use of libraries like Backbone, Sproutcore or ember.js a lot of the content can be rendered in the browser. This can constitute a serious problem since the support methods from Google et. al. for alternative crawling coem with no guarantees.

We recently ran into this problem and came up with a neet solution where the client side templates can also be rendered server side.

There are two parts to the implementation. First, a method that can take a jade partial and its local variables, compile and evaluate it. Second, a view that calls out to that method and provides the template and the necessary local variables.

Part 1, the application_helper.rb


require 'tilt-jade/jade_js'

module ApplicationHelper
  def html_from_jade_template(partial, options={})
    data = File.open(
            Rails.root.join("app", "assets", "templates", "#{partial}.js.jst.jade"
            ))
    compiled = JadeJs.compile(data, locals: {}, client: true, compileDebug: false)

    raw(JadeJs::Source.context.eval("(#{compiled})(#{options[:locals].to_json},
        jade.runtime.attrs, jade.runtime.escape, jade.runtime.rethrow,
        jade.runtime.merge)"
        ))
  end
end

The method is pretty straight forward, it loads the template from the assets/template directory, compiles it and then evals it with the provided locals. The output is raw html that can be included in your view.

Part 2, a view that requests the compiled and eval’d templates from the server


- body = "This content comes from the server. Remove the param from the url or toggle
          with the link in the upper right."
#menu
  = html_from_jade_template("home/menu", locals: {items: [{title: "Server"},
    {title: "Side"}, {title: "Rendered"}]})
#content
  = html_from_jade_template("home/content", locals: {body: body })

Here the main thing is the call to the method in application helper that will produce the raw html given a template name and the necessary local variables.

That is pretty much it. It may take a little bit to figure out the requirements for the local variables in your template, especially since jade is very strict about them. If it can’t find one it will not compile.

I’ve put an example app on github with the complete source code for this post.

About the Author

Biography

Previous
How to split up rails 3.x logger by unicorn workers
How to split up rails 3.x logger by unicorn workers

TLDR: Put this in your unicorn config. Make sure not to have duplicate after_fork calls after_fork do |serv...

Next
Cloud Foundry Now Supports Rails Assets Pipeline
Cloud Foundry Now Supports Rails Assets Pipeline

Rails version 3.1 introduced the assets pipeline as a way to properly organize and serve static assets. We ...