I have just pushed a small, long overdue update to my css_dryer plugin which lets you convert your nested stylesheets to CSS as part of your deployment process. This means:
stylesheet_link_tag helper will bundle your nested stylesheets with your normal ones.stylesheet_link_tag helper will append the cache-busting asset timestamp on your nested stylesheets.None of this was possible before.
Use the new Rake task css_dryer:to_css. This loops over every .css.ncss file in app/views/stylesheets/ and generates a corresponding CSS file in public/stylesheets/.
When deploying you should use this between updating the code and symlinking the new current directory (assuming a conventional Capistrano deployment).
namespace :deploy do
task :after_update_code do
generate_css
end
task :generate_css, :roles => [:web] do
run "cd #{release_path}; RAILS_ROOT=#{release_path} rake css_dryer:to_css"
end
end
This generates the CSS on the server(s) which is where it’s needed.
This is compatible with any asset packaging system you might use, such as Jammit. Just run the Rake task before you package your assets.
Taking a leaf out of GitHub’s asset bundling book, we want to be able to deploy code updates without invalidating our users' CSS and JavaScript caches. GitHub uses Grit but I prefer calling out to Git directly:
# production.rb
# Set the asset timestamp to the timestamp of the most recent commit
# to touch any assets. Do this so we only bust client caches when we
# have actually changed assets.
ENV['RAILS_ASSET_ID'] = %w( public/javascripts public/stylesheets app/views/stylesheets ).map do |path|
`git log -1 --pretty=format:%ct #{path}`
end.max
As well as JS and CSS, Rails also regards images as assets. If you set RAILS_ASSET_ID as above, your images will use that timestamp too. This doesn’t seem sensible to me: if you change some Javascript or CSS, you don’t want to force your users to download all the images again.
I haven’t pursued this yet but I think there are a couple of options:
RAILS_ASSET_ID into three: one for JS, one for CSS, and one for images.RAILS_ASSET_ID for JS and CSS but file modification time for images.The latter depends on whether Git (via Capistrano) sets the last modification time of files correctly. I would be surprised if it didn’t but I haven’t checked. If it does, you would also have to stop Capistrano from touching all the images with set :normalize_asset_timestamps, false.
While looking into asset timestamps I ran across smusher, a gem which provides an easy command line interface to Yahoo’s Smush.it service (for lossless image size reduction of jpg, png and gif). You can process a whole directory of images at once, which is useful.
css_dryer now works properly with Rails' asset bundling, as well as any asset packaging you might wish to do.