Artem Kholodenko
Engineering @ BuildZoom
2 min readNov 20, 2015

--

How to populate AngularJS $templateCache server-side with Rails

AngularJS custom directives are a great way to modularize front-end functionality. I think of each one as a Lego piece to be mix-and-matched for different solutions. One downside of the basic set up of directives is that directive templates are asynchronously loaded after the directive is initialized. Having a dozen components on a page leads to a dozen HTTP requests as the page loads.

The basic solution is inline templates via the script tag. The downside is code maintainability. If you have all the templates in a single file, you have a really long and fragile template code base. Even if you have separate files, the HTML mark-up is not properly recognized by most code editors within the script tags.

The more advanced approach is explicitly populating $templateCache key/value store. Here’s what we did to populate $templateCache server-side to improve page-load performance.

Created Rails Helper

The helper methods read in the content of files, serialize the content, and use the resulting content as the value in generating JavaScript code to populate the $templatecache key/value store.

module AngularHelper
def angular_template_file_path (file_path)
"app/assets/templates/" + file_path
end

def set_angular_template_cache (templates = [])
template_js = ''

if !Rails.env.local?
templates.each do |template_file_path|
template_html = File.read(angular_template_file_path(template_file_path)).to_json
template_js += "$templateCache.put('/assets/#{template_file_path}.html', #{raw(template_html)});\n"
end
end

template_js
end
end

angular_template_file_path

This method puts together the path to the template file within the code base.

set_angular_template_cache

This method loops through an array of file paths, to read in the content and generate the JS code.

To note, the local environment is excluded from the caching for development purposes, as changes to template files do not automatically force a regeneration of the js.rb file where the module is defined. In production, where assets are compressed and minified, the top-level asset file is generated with every pre-compilation when it’s supporting files change.

Add AngularJS Run task within an *.js.erb file

The Rails helper methods now need to be used within the JS code.

<% environment.context_class.instance_eval { include AngularHelper } %>

angular.module("myApp", []);

angular.module("myApp").run(['$templateCache',
function($templateCache){
<%
templates = []
templates << 'demo01.html'
templates << 'demo02.html'
templates << 'demo03.html' %>
<%=set_angular_template_cache(templates)%>
}
]);

First, include the AngularHelper. Then define a run task on the module, which is injected with Ruby code. The server-side code builds an array of templates, which is passed into the helper method for JS generation.

The result is a JS file created using the regular Asset Pipeline process, which has compressed inline templates, without sacrificing code maintainability, while reducing HTTP request calls made on page load.

Originally published at www.buildzoom.com on November 20, 2015.

--

--