Sorry this page looks weird. It was automatically migrated from my old blog, which had a different layout and different CSS.

Generate CSS with css_dryer in your deployment process

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:

None of this was possible before.

How to do it

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 :generate_css, :roles => [:web] do
    run "cd #{release_path}; RAILS_ROOT=#{release_path} rake css_dryer:to_css"
  end

  after 'deploy:update_code', 'deploy:generate_css'
end

This generates the CSS on the server(s) which is where it’s needed.

Asset packaging

This is compatible with any asset packaging system you might use, such as Jammit. Just run the Rake task before you package your assets.

Asset timestamps

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

Image timestamps

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:

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.

Smusher

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.

Conclusion

css_dryer now works properly with Rails' asset bundling, as well as any asset packaging you might wish to do.

Andrew Stewart • 2 February 2010 • RailsCSSDeployment
You can reach me by email or on Twitter.