Untangling the Rails Asset Pipeline, Part 4
Troubleshooting
In part due to the flexibility of the Rails asset pipeline, deployments to production can break in interesting and unexpected ways. In this final post of our asset pipeline series, we look at common error messages and problems we have encountered, and offer some quick solutions.
You’re reading the last installment of a four-part series on the Rails asset pipeline. The previous entries are Caches and Compass, Production, and Configuration.
Table of Contents
- Help! My production site is completely unstyled
- I’ve precompiled, but styles still don’t load
- My main stylesheet works, but others do not
- When precompiling, I get errors
- I’m trying to compile on-the-fly instead
- Pages load slowly
- When in doubt…
Help! My production site is completely unstyled
In this scenario you deploy to production, load your site and find that the HTML source code is fine, but no CSS is loading at all. Pull up the Webkit console (⌥⌘C in Safari, ⌥⌘J in Chrome) and you see red 404 error messages for each CSS and JavaScript file. Yikes!
I made this mistake myself when first experimenting with Rails 3.1. The solution is easy: run this very important command on the production server:
bundle exec rake assets:precompile
This is needed because Rails by default does not generate or serve its CSS assets in production, so you need to compile them beforehand. For further explanation on this topic, read Part 2: Production of this series.
I’ve precompiled, but styles still don’t load
If you’ve precompiled, double-check that compilation actually worked by listing the contents of the public/assets
directory of your application on the production server:
ls -l public/assets
You should see compiled and cache-busted versions of all your CSS, JS and image assets. If not, review the output of rake assets:precompile
for errors.
Assuming precompilation worked, make sure that you are accessing your application by way of the web server (i.e. Nginx or Apache, usually on port 80). If you haven’t configured the web server yet and are hitting your application directly (i.e. via thin
or webrick
on port 3000), assets will not work.
If you don’t wish to set up a web server1, or you want to test your Rails application in production before doing so, set the following in production.rb
:
config.serve_static_files=true
Check out Part 3: Configuration of this series to go more in-depth on this topic.
My main stylesheet works, but others do not
By default, Rails only precompiles application.css
. If you have additional stylesheets, like perhaps ie.css
or print.css
, these won’t be precompiled unless you explicitly tell Rails to do so.
config.assets.precompile += ['ie.css', 'print.css']
Refer to part 3 of this series for more information on the config.assets.precompile
setting.
When precompiling, I get errors
To precompile all of your CSS and JavaScript, Rails needs to have loaded all the required gems. That means that if your stylesheets use Compass, the compass-rails
and sass-rails
gems have to be present. Likewise CoffeeScript files need coffee-rails
.
Make sure all asset pipeline gems are declared at the root level of your the Gemfile
. For example:
gem "coffee-rails", "~> 4.1.0"
gem "sass-rails", "~> 5.0"
gem "uglifier", ">= 1.3.0"
I’m trying to compile on-the-fly instead
When testing your deployment process, you may find yourself wanting to skip rake assets:precompile
and compile assets on-the-fly instead, the way Rails normally works in development mode. After all, the precompilation step can take quite a long time for a large app.
In Rails 3.1 or 3.2, if you simply set config.assets.compile=true
, the pages of your app might fail to load with obscure errors relating to Sass, Compass or CoffeeScript. That’s because in production, these versions of Rails did not normally load the gems required for compiling assets. Tell Rails you want to load them by uncommenting this line in application.rb
:
Bundler.require(:default, :assets, Rails.env)
For a more detailed walkthrough of this setup, refer to the config.assets.compile
section of Part 3: Configuration.
Pages load slowly
Large stylesheets and JavaScript files take time to download and parse, especially on slower devices like the original iPad. If your application is not delivering the proper cache headers, the browser may re-fetch your stylesheets for each and every page, resulting in noticeable sluggishness.
Also remember that in production, Rails is not serving your assets: that’s the web server’s job. Solving this problem therefore involves configuring the web server to serve assets with far-future expires headers. For example, in Nginx:
location ~ "/assets/.*-[0-9a-f]{32}.*" {
gzip_static on;
expires max;
add_header Cache-Control public;
break;
}
See the Rails asset pipeline guide for more details.
When in doubt…
If during your troubleshooting and experimentation you have tried turning on asset compilation (or perhaps tried running Rails in development mode), you may have built up cache files that interfere with the asset pipeline.
If all else fails, manually clear out the tmp
and public/assets
directories:
rm -rf tmp/*
rm -rf public/assets/*
Then retry your deployment steps.
Good luck!
-
By default, Rails very much encourages developers to deploy to production using a web server like Nginx or Apache. Unless you are deploying on Heroku, which has its own deployment advice, it is usually a good idea to follow this suggestion. ↩