The Rails asset pipeline is very powerful, but often misunderstood. At the Utah Ruby User Group, most of the attendees aren’t sure how to use it fully in their Rails app. It’s considered as one of the magic features that Rails offers. I admit that I was confused as well and took it’s magic for granted. Not any longer.
In this article, I want to simplify the asset pipeline so it is better understood.
Sprockets performs the asset packaging which takes the assets from all the specified paths, compiles them together and places them in the target path (public/assets).
Tilt is the template engine that Sprockets uses. This allows file types like scss and erb to be used in the asset pipeline. See the Tilt Readme for a list of supported template engines.
Rails applications default to having three possible asset paths.
lib/assets is for your own libraries’ code that doesn’t really fit into the scope of the application or those libraries which are shared across applications.
The keystone of the asset pipeline is the manifest file. By default, Rails creates one for stylesheets (
For directives that take a path argument, you may specify either a logical path or a relative path. Relative paths begin with ./ and reference files relative to the location of the current file.
Here are some directives that can be used:
require[path] inserts the contents of the asset source file specified by path. If the file is required multiple times, it will appear in the bundle only once.
include[path] works like require, but inserts the contents of the specified source file even if it has already been included or required.
require_directory[path] requires all source files of the same format in the directory specified by path. Files are required in alphabetical order.
require_tree[path] works like require_directory, but operates recursively to require all files in all subdirectories of the directory specified by path.
require_selftells Sprockets to insert the body of the current source file before any subsequent require or include directives.
depend_on[path] declares a dependency on the given path without including it in the bundle. This is useful when you need to expire an asset’s cache in response to a change in another file.
stub[path] allows dependency to be excluded from the asset bundle. The path must be a valid asset and may or may not already be part of the bundle. Once stubbed, it is blacklisted and can’t be brought back by any other require.
Documentation for this section was largely extracted from the Sprockets README.
Using the asset pipeline is very simple. All it involves is placing assets (js/css/images/other) into the asset path. You can access the files using multiple helper methods within your views:
1 2 3 4 5 6 7
See ActionView::Helpers::AssetTagHelper documentation for more information.
Sass files need to use erb extension to allow for asset path inclusions within the files.
The truth is that
1 2 3 4
See the Rails Asset Pipeline guide (2.2.2) for more information.
Adding to Gems
A good way to include assets easily in a Rails application is by using gems. To include assets within a gem to be precompiled with the Rails application that is using it, all you need is to place the assets in one of the three standard asset paths:
vendor/assets. These will be automatically included in by Sprockets when the assets are compiled. See the Rails documentation for more information.
Q: Why doesn’t the auto-generated scss and coffeescript only get included in their respective controller views?
Because the assets all concatenate into one file, there are no seperate files to be included on a view-by-view basis. There is a way to get around this by using css classes.
Let’s say we have a controller named
Users with an accompanying sass file called
users.css.scss. Make sure your css is wrapped in a class which includes the name of the controller:
1 2 3
Next, add a class to the body tag of your layout:
Now the css in
users.css.scss will only be applied to views under the
- This may not be best practice. Refer to the comments below.*
Q: Do I have to use the asset pipeline?
No. In Rails 3.1, the asset pipeline is enabled by default. It can be disabled in
config/application.rb by putting this line inside the application class definition:
Q: What happens if there are duplicate file names in different asset folders?
Let’s say you have two asset files with the same name in different paths. For example, let’s say we have two files:
When the assets are compiled, it disregards all the duplicate files after the first one found in the asset path. Let’s look at the asset path using the rails console:
1 2 3 4 5 6 7 8 9
Note that the path
/Users/eberry/example/app/assets/stylesheets appears before the path
Q: How can I precompile assets that aren’t to be used in the pipeline?
Let’s say you want to include the folder
other/assets into the asset pipeline to be precompiled. This is a simple addition in the
application.rb file (or environment specific config file).
1 2 3 4 5 6 7
Now when you run the command
Rails.application.config.assets.paths in the Rails console, you will see the new asset path.
Multiple manifests can be created in the assets folder. For example, I can have a separate manifest called
footer.js which includes the files
I can add this into the HTML by using the same
1 2 3
Q: How can I precompile additional assets without having to include them in the manifest?
Let’s say we have a file called
search.js in our
public/assets when the assets are compiled.
This is very simple. Just add the following to your
application.rb file (or environment specific config file):
1 2 3
This configuration option appears by default in
As I said before, the asset pipeline has three goals: precompile, concatenate and minify* assets.
Precompilation let’s you use higher-level languages to create actual assets (for example, Sass to CSS).
Concatenation is very important in the production environment. It can reduce the number of requests that a browser makes to render a web page, which leads to faster load time.
Minification takes out the extra whitespace and comments from your assets. This allows for smaller asset file size, which leads to faster load times.
I strongly suggest learning more about the asset pipeline by going to the Rails documentation. Ryan Bates also two excellent Railscasts on Understanding the Asset Pipeline and Asset Pipeline in Production.