A blog about all things Cloud
by Ninefold and friends.

Back to blog

Rails and the Warped Asset Pipeline

To most Rails developers, just starting or otherwise, the Asset Pipeline is like the magical warp pipe in a certain 8-bit – and its many incarnations – video game most of us grew up with.

No not that one with the bird!

And maybe it IS that magical warp pipe that takes us to a whole new world. That’s pretty much what the asset pipeline does. It takes us to a different, and more efficient, world.

If you’re anything like me, you’ll want the TL,DR first. Think of it as finding that one awesome pipe and warping to the last level.

Make your own warping noise!

So here is how it works in 3 sentences.

TL,DR: Your Javascript files and CSS files all get compressed into 2 files: application.js and application.css. Those compressed files get sent down to the public/assets directory and are served up for your viewing pleasure. Your images and other files in app/assets get sent down the pipe to public/assets as well and are served from there.

Now that we’ve gotten that out of the way, let’s restart our journey and jump down all the individual pipes to learn more.

THE THREE FEATURES OF THE PIPELINE

That heading might be a bit misleading, as there are other features as part of the pipeline, but there are three main ones: concatenation, compression, and precompilation (of high-level languages). There’s some preprocessing going on!

Concatenation

Rails uses Sprockets, a fancy term for puppetmaster, to take all your Javascript files and merge it into one single .js file. It does the same thing for CSS. This is brilliant because serving up less files means load times are that much faster. If you don’t believe me, the math is simple: 15 Javascript or CSS files take longer than 1 Javascript or CSS file to load.

Fusion HA!

Compression

Once those files have been merged together, they undergo a metamorphosis and are shrunk down to a more manageable size. Extra whitespace and comments are removed. When we code, our CSS files are formatted in a way to make things look pretty and visually appealing. But when you’re a machine, you don’t need comments or pretty indents and spaces. You’re a machine! And all this equates to faster loading times, since it’s less bits being transferred.

Honey...

Precompilation (of high-level languages)

Some of the best things about being a web developer right now is being able to use handy new next-gen higher-level languages. No longer do we have to survive by actually writing out every. single. HTML tag by hand. No longer do we have to write out lines and lines of code and make sure you get every bracket, comma, and semi-colon right. Now we have meta-languages like Coffeescript, Sass, ERB, HAML, and the list goes on! At this stage, our Rails Coffeescript and Sass files get converted – precompiled – to vanilla Javascript and CSS.

Internets!

MANIFEST DESTINY

With our Javascript and CSS files, as .js.coffee and .css.scss, they each have an application.js/css file that is the manifest used to control what will get included and served. You can include files that need to be precompiled individually or by directories. By default, the directives go from top to bottom, except for require_tree, which is just a party with no discernable order to how they are served. This means that if you’ve a file that needs special attention and needs to be loaded first, that should be listed before the require_tree directive.

Directive!

WHAT ABOUT THE OTHER FILES?

For all the other files – the other assets – that aren’t Javascript and CSS, they are passed down to public/assets.

FINGERPRINTING

All the files that go down the pipeline are given a hash (fingerprint), that allows them to be cache friendly. If that file or it’s fingerprint has been changed, the cached copies along the network will know. Typically this means that all the assets get this crazy gobbledigook at the end of their filename, like so: public/assets/image-1h234j348n45h4u88vjgdfg.png

Don’t worry, you won’t have to actually KNOW the hash at the end. You can still call your files what they are: image.png.

Fingerprint

Production environment vs. development environment

With the asset pipeline, the production (prod) environment behaves differently than the development (dev) environment. In prod, Rails has a specific rake task to run asset precompilation, which makes the assets go down the pipeline: rake assets:precompile.

Note: On Ninefold, this task is automatically run during every deployment and redeployment unless you have files in your public/assets folder already – if you do, rake assets:precompile is aborted.

Ninefold!

However in dev, assets aren’t precompiled and are served as separate and individual files, based on the manifest order. They are compiled on the fly. Of course nothing’s stopping you from precompiling your assets. In dev, Rails looks at public/assets to see what’s in there. If it’s empty, it goes and checks the app/assets directory for them. This is controlled by config.assets.compile. In development, it’s true by default. In production, it’s false to keep page rendering speedy.

Development: in config/environment/development.rb

config.assets.compile = true

Production: in config/environment/production.rb

config.assets.compile = false

This means that what works locally in dev probably won’t work in prod. It’s always good to double check how things look in prod on your local machine by doing

$ rails s -e production

I don't always...

Simple tip for testing in prod locally

Standard Rails apps come with WEBrick to test things out locally. Naturally, after saying what command to run to test the production environment on your local machine, it would make sense to follow up with some tips on getting things to work correctly. So let’s digress a bit from the asset pipeline to talk about how to really check this out locally.

If you haven’t done so, checkout a new branch, calling it test-prod or whatever you’d like. This isn’t the branch you want to be pushing to production, but it’ll be pretty darn close. $ git checkout -b test-prod

Now, precompile your assets.

$ RAILS_ENV=production bundle exec rake assets:precompile

At this point you can run $ rails s -e production, but you’ll notice that none of your assets have been found. All your GET requests for assets will be FATAL.

Here, I did it for you

What happened here? Unlike Apache or Nginx, which can handle serving these assets statically, WEBrick is a pretty dumb web server. You’ve got to tell it what to do. In your config/environment/production.rb file, have this: config.serve_static_assets = true

Save that and now run $ rails s -e production. Voila! Your page should be rendering your images and JS/CSS files properly.

CSS and occasional wonkiness

The asset pipeline can be really confusing…mostly when you’re trying to call out images in your CSS. A prime example is when you want a background picture to display, and you call it like this: background-image: url(“/assets/background.jpg”);

It’ll work in dev, but not in prod. If you’ve been paying attention, you can probably figure out why. (Hint, it’s not the ‘assets’ path, though that too is incorrect.)

Luckily for us, we have helpers and tags that make things easier, and those end with -path or -uri, heck even _path and _tag. Of course, there’s reasons behind this, as with anything, but that’s a topic for a different discussion.

Arming ourselves with this knowledge, the background image will work if it’s this: background-image: url(image_path("background.jpg"));

Alternatively, this also works:

background: image-url("background.jpg");

PROTIP for Rails 3.2.x users

If you’re using Rails 3.2, you may want to use turbo-sprockets-rails3. That’ll greatly speed up the sluggish asset precompilation by checking to see which assets were already precompiled and unchanged and only compiling the new / changed assets. This was included in Rails 4 so if you’re running that, no need to worry.

Hopefully you now understand the asset pipeline a bit more. It’s not as warped as it may seem, but it’s definitely a bit confusing. But with this newfound knowledge, you should be fully prepared to dive in and become best friends with the Rails guides on it. Go on and read it! It’s found here

If you’re a Ninefold customer and are confused about how we handle your assets, check out this KB article!

Disclaimer: All images were found via Google image search and probably was modified to fit the blog post. Bonus internet points if you know the references.

Tell us what's what.