Skip to main content

Extend Sprockets to bundle mustache templates

Rails • Asked by Alex Musayev

I'm trying to include some Mustache templates into the main JS bundle. The idea is to take /app/templates/*.mustache files, generate a JSON object, and set a window-level variable, like this:

window.Templates = {
  post: "<h2>{{ title }}</h2> <p>{{ body }}</p>",
  comment: "..."
}

This way the templates will be preloaded with application.js and remain available from every Rails view.

I've read this: https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md, and now I'm trying to create a transformer for new MIME type. Like so:

module Sample
  class Application < Rails::Application

    // ...

    config.assets.configure do |env|
      env.register_mime_type 'text/mustache', extensions: ['.mustache']
      env.register_transformer 'text/mustache', 'application/javascript', -> (input) {
        { data: '// THIS IS SAMPLE JS CODE GENERATED BY A TRANSFORMER' }
      }
    end
  end
end

Adding this directive to app/assets/javascripts/application.js file suppose to inject sample output from this transformer for each file from templates directory:

//= require_tree ../../templates
//               ^ This should point to /app/templates

But I'm getting empty result after Sprockets compiles JS. Any advice?

I just want to understand how to set up Sprockets transformer. Actual JS generation is not a problem, I've added details just for the context.

I know that there are couple of gems that can do this for Mustache and Handlebars templates (like https://github.com/leshill/handlebars_assets), but I don't want to introduce another dependency here. The extension seem to be pretty simple.


I solved it, LOL.

Transformer lambda was correct. Just needed to add a regexp to Rails.application.config.assets.precompile to enable *.mustache processing. Also had some troubles with overly smart Sprockets caching.

I've also replaced the labda with this class:

module Service
  class MustacheTransformer
    def self.call(input)
      Rails.logger.debug "---> Transforming Mustache: #{input[:filename]}"
      key = input[:name]
      body = Oj.dump(input[:data])
      obj = 'window.MustacheTemplates'
      { data: "#{obj} = #{obj} || {}; #{obj}['#{key}'] = #{body}" }
    end
  end
end

Seem to be working pretty neat.


This is awesome. I haven't extended sprockets myself before and that looks like it turned out rather nicely. I'm impressed! :D


Chris, you can create an episode about this. I'll share more detailed code example if you like :)


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 24,647+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.