Rails asset pipeline: Why things break in production and what precompilation does to your assets
When you work with a Rails 3.1+ application, you will be working with the asset pipeline. The asset pipeline is awesome until you deploy. Then it will be less so if you haven't done everything as the pipeline expected it from you.
When you deploy, Rails runs
assets:precompile which precompiles all assets into static files that live in
public/assets. This way you have all the performance of static files with all the expressiveness of Ruby.
Unfortunately, the path of every single file changes during precompilation. This means that you have to be a bit careful how you reference assets.
.tile background-image: url('../images/foo.png')
won't work any longer, because there is no
foo.png now lives directly in
This precompiles into this (fingerprinted and compressed files removed for clarity):
What has happened?
All asset folders (
app/assets/fonts, etc.) are merged into one folder:
Subfolders are also merged into
public/assets. That means both
app/assets/stylesheets/subfolder/*now live in
All CSS files are concatenated into one file (
public/assets/application.css). With the default manifest in
app/assets/stylesheets/application.css, stylesheets in
app/assets/stylesheets/**/*.cssare concatenated. So
public/application.csshas the following content:Copy
/* content from app/assets/stylesheets/stylesheet_root.css */ /* content from app/assets/stylesheets/subfolder/stylesheet_subfolder.css */
public/assets/application.js). With the default manifest in
public/application.jshas the following content:Copy
What will break after precompilation?
- Stylesheets, that used
- @font-face definitions that used
How can I fix my stylesheets?
Do not use
This is plainly wrong, since from your browser's point of view, your stylesheet lives at
/assets/application.cssand your image at
/assets/foo.png. I have no idea why it works in development in the first place. Simply use the SASS helper:Copy
.tile background-image: image-url('foo.png')
How can I fix my font definitions?
With the Asset-Pipeline fonts are stored in
Depending on your rails version, you may need to addCopy
config.assets.paths << Rails.root.join("app", "assets", "fonts")
to your config/application.rb (config/initializers/assets.rb in Rails 4+)
Do not use
src: url(...)in your @font-face definitions.
Again instead use a sass-helper:
src: font-url(...)(file need to be
Maybe the referenced paths need adjustment. If before it was
src: url(fonts/...)now the leading
fonts/directory needs to be removed, because the fonts are compiled to the assets folder by the asset-pipeline.
Managing 3rd party assets
You don't want to manually fix references in external libraries you put into your application. The card Managing asset libraries offers two solutions.