And the relevant bits of the app dir structure are:
app/assets/stylesheets/application.css.scss # Contains ‘require_self’ and ‘require_tree .’ as usual
vendor/assets/stylesheets/bootstrap.css
I’m using Capistrano’s asset pipeline support (load ‘deploy/assets’) in my Capfile. When I’m deploying the app using cap deploy it’s precompiling the assets correctly and copying them into the shared/assets directory for the app on the server.
The problem seems to be that the bootstrap.css file is plain old CSS so it doesn’t get compiled (obviously) but this means that it doesn’t end up in the shared/assets directory (which is symlinked to public/assets in the app directory). Maybe there’s something I’m missing as I’m still getting to grips with the asset pipeline. Anyway, there’s no problem with this locally - I’ve tested with asset compression enabled - but then it’s not the same setup that we end up with on Capistrano deploys.
Do plain CSS/JS files need to go through pre-compilation? And if so, do they really have to be manually specified in application config?
Shouldn’t Rails’ stylesheet_link_tag helper be looking in /vendor/assets/stylesheets as well as public/assets/stylesheets?
The error I get in production is: ActionView::Template::Error (bootstrap.css isn’t precompiled)
Surely bootstrap.css will never be precompiled and end up in public/assets if it’s just plain old CSS?
There is a good reason why this is disabled by default in Rails which is that Rails is not a general purpose web server. Servers such as Apache and Nginx are optimized for rapidly serving up static content. You should consider the advice of the Rails core team and let your webserver do what it does best (as described in the next section.) "
Agreed. I must say this is extremely confusing. There seem to be no decent explanations in the docs or anywhere else. Why would config.serve_static_assets need changing to be true when we are told “Apache or nginx will already do this”? Should I actually be setting up Nginx to serve the files in the vendor/assets directory? I don’t know how this would work when the helper appears to believe it’s going to find bootstrap.css in public/assets/.
If you have config.assets.compile set to true (typical for development) the stylesheet_link_tag will attempt to look in your app/assets directory and compile the css file if necessary. But the stylesheet_link_tag doesn’t look outside public/assets in when config.assets.compile is set to false (which is typical for production). Actually, it reads from the manifest.yml to determine which file path to return.
When an asset is precompiled, it gets put into the public/assets directory and an entry is put in manifest.yml like so:
When you use stylesheet_link_tag(“application”) in production, it checks to see if an entry exists in manifest.yml with that name. if so, it returns the hashed filename specified in the manifest. Otherwise it would just return the unhashed file name like “assets/application.css”
So one option is to add bootstrap.css to config.assets.precompile. This will in fact send it through the pipeline and dump it in public/assets with the name bootstrap-digest.css and put an entry in manifest.yml.
However, plain CSS files don’t really *need *to be pre-compiled since they don’t contain SASS/ERB. If it doesn’t need to be compiled, you can just put them directly in public/assets without adding it to config.assets.precompile and you’re done.
So to sum it up: in production, all assets need to be under public/assets. How they get there depends on whether they need to be pre-processed or not.
Hopefully that’s not too confusing. It sounds complicated but once you understand what’s going on it’s really kind of nifty.
Thanks Tim - that has definitely cleared it up in my mind. It’s a shame it’s not explained like this in the Rails guide. I never had this much trouble when I was just using Jammit before Rails 3.1