Organize Your Assets with Rails Engines

|   Sep 19, 2013

This post is a follow-up to my previous post where we broke down our application into components using Rails Engines.

When breaking down our application we found that there were two types of components that worked well as Engines. The first were mini apps, targeted views that are separate from the main web application. An example is our bookmarklet:

Screenshot_7_25_13_2_21_PM-2

The other type of component was an extension to the core, something that contributed new pages to the core web application. Examples of this are Private Messages, Projects, and Town Halls.

One of the benefits of using Engines is separating out your assets (javascript, stylesheets, images, etc) to make it clearer which components own which assets. For the mini apps this was an easy win – each got its own javascript and CSS bundle and an image directory. Make those available by adding them to the Rails precompile config:

module Bookmarklet
class Engine < Rails::Engine
initializer :assets do |config|
Rails.application.config.assets.precompile += %w{ bookmarklet.css }
Rails.application.config.assets.precompile += %w{ bookmarklet.js }
Rails.application.config.assets.paths << root.join("app", "assets", "images")
end
end
end

And then reference them in your layout / view such as engines/bookmarklet/app/assets/views/layouts/bookmarklet.css.erb:

<head>
<%= javascript_include_tag :bookmarklet %>
<%= stylesheet_link_tag :bookmarklet %>
</head>

Now you no longer have to wonder where header.jpg is used in your application because it’s located in the bookmarklet Engine in engines/bookmarklet/app/assets/images.

The extensions to our core functionality are a little bit more interesting. We typically add a separate CSS and javascript bundle for each Engine. This gives a nice level of granularity where each page has 2-3 javascript and 2-3 CSS files, giving you what you need for the current page in a couple of requests. For javascript it’s important to make sure that you don’t double include dependencies if you are using Sprockets. You can avoid double includes using stub like this:

//= stub core
//= require_tree .

In some cases, such as modals accessible from the navigation, we also wanted to add some CSS to the core from the Engines. We weren’t able to find an easy way to automatically add to the core so we came up with a convention of putting the assets in app/assets/stylesheets/core_ext/projects and then including them in the core CSS like this:

//= require core_ext/projects

Note that this violates the encapsulation of the Engines a bit but we felt that it was still an improvement.

Using these techniques we were able to cut down quite a bit on the amount of unused CSS and javascript that are loaded on the home page. It is much easier to find unused CSS and images when it’s clear which pages are using them.

Comments are closed.

Sign up to receive email communications regarding events, webinars, and product news.

What is Socialcast?

Socialcast by VMware (NYSE: VMW) is a social network for business uniting people, information, and applications with its real-time enterprise activity stream engine. Behind the firewall or in the cloud, Socialcast enables instant collaboration in a secure environment. Socialcast is headquartered in San Francisco, California. www.socialcast.com