279: Understanding The Asset Pipeline
The asset pipeline is one of the biggest new features in Rails 3.1 but it can also be the most confusing. In this episode we’ll attempt to demystify it a little by showing how it manages your Rails applications’ assets. If you’re completely unfamiliar with it a good place to start is the a Rails Guide on the asset pipeline as this covers a lot of its features.
If you’ve written any Rails 3.1 applications you’ll probably know that if you visit
There’s nothing special about the
application.js file; any file that is put under the
http://localhost:3000/assets/greeting.txt. Even though the file is under
/assets/greeting.txt. This applies no matter what subdirectory under
/app/assets we put the file in. We can even create a new directory and put the file in there and it’ll still be available at the same URL. If we do create a new directory however, we’ll need to restart the server before any files we put in there are accessible.
/app/assets directory isn’t the only place that we can add assets. If we create an assets directory under
/lib any files we add there will be accessible from there as if they were in the main
/app/assets directory. This also applies to any files under a
If you have assets that are not really specific to the current application then assets directories under either
/vendor are ideal places for them. If our app uses a jQuery plugin then the
/lib directory is a good place.
At its most basic the asset pipeline is a list of loadpaths. We can see this list by running the console and viewing
Rails.application.config.assets.paths. We’ll view the output as YAML to make it easier to read.
The output shows every directory under the
app/assets directory and also those under
/vendor/assets. There’s an interesting directory at the end of the list which comes from the
jquery-rails gem that we’ve included in our application. We can look at its contents with the
bundle open command.
$ bundle open jquery-rails
This opens the gem with the text editor defined by our shell’s
EDITOR environment variables. If we look at the gem’s files we’ll see an
As you might expect we can access any of these files in a browser under the
assets path as the directory they’re in is in the asset pipeline’s loadpath.
Managing Assets With Sprockets
Let’s go back to our application’s
application.js file now and take a look at it.
The file only contains comments but some of these are significant. This type of file is known as a manifest and it’s managed internally by Sprockets. When a request comes in for this file Sprockets looks at the manifest and compiles together every file that is mentioned in it and includes their contents before any code in this file.
The loadpath works here as well. We have
require jquery in this file (the extension
.js is optional and can be left off). Sprockets will search the loadpath for this file and, in this case, load it from the
require jquery-ui to the file the gem’s
jquery-ui.js file will be included. This applies to CoffeeScript files too; if we include
require home the /
home file isn’t necessary, however, as at the bottom of the file we have
If we want to see the files that are included we can add a
There are a couple of ways that we can get around this problem. We could use
require_directory instead of
require_tree as this will only load the files in the current directory and not in subdirectories. If we want more control over the included files we can
public subdirectory. We can then use
require_tree ./public to include just those files.
You might be wondering what commands can be passed into the Sprockets manifest. There isn’t a good source of documentation yet but within the
directive_processor.rb file in the source code are comments that explain how it works and the various commands that can be passed in.
The asset pipeline also handles preprocessing. To show how this works we’ll create a file called
greeting.txt in a new
/app/assets/anything directory. As it stands this is just a static text file but we can add another extension to the file name and specify a processor, for example
.erb. We can now add ERB code to this file and it will be processed.
hello world <%= 1 + 1 %>
If we look at this file in a browser we’ll see that the ERB code has been processed. Note that we don’t include the preprocessor extension in the URL.
This is basically how SASS and CoffeeScript work. When a file has an
.scss extension this is treated as a preprocessor extension and the file will be passed through the SASS processor. We can even chain the extensions and create a file with, for example, an
.scss.erb extension. This file would first be passed through the ERB processor and then the SASS processor.
The preprocessor is very configurable. We can add our own processors or swap out the existing ones. This is all handled by the Tilt gem and there’s more information on how it works and the extensions you can use there.
Differences in Production Mode
That’s it for our quick walkthrough of the asset pipeline’s features. There are some differences in how the pipeline works in production mode and we’ll spend the rest of the episode covering these. First, we’ll start up the server in production mode.
$ rails s -e production
If we visit our application’s homepage now and view the source we’ll see that our assets are delivered differently.
These assets are automatically cached and served by the Rack Cache middleware so they’re pretty fast. If we want to have the webserver itself handle serving and hosting the assets instead we can precompile them by running
$ rake assets:precompile
This will precompile the assets into the
/public directory so that they’re easy accessible by the web server.
That’s it for this episode on the asset pipeline. Don’t forget to checkout the Rails Guide for more information on it.