68 lines
3.4 KiB
Markdown
68 lines
3.4 KiB
Markdown
|
---
|
||
|
title: "Precompile SASS to CSS for deployment to Heroku"
|
||
|
kind: article
|
||
|
slug: precompile-sass-to-css-for-deployment-to-heroku
|
||
|
created_at: 2010-09-28
|
||
|
tags:
|
||
|
- git
|
||
|
- haml
|
||
|
- sass
|
||
|
- heroku
|
||
|
---
|
||
|
If you have deployed apps to Heroku you know that you cannot write to the read-only file system that Heroku offers. For file uploads you have to use some storage provider like Amazon S3 or RackSpace CloudFiles.
|
||
|
|
||
|
Now, if your application (I'm assuming you're already on Rails 3), is using Haml + Sass, you're in some trouble. Sass is set to generate CSS files on the fly and save them to `public/stylesheets` so the can be served like static content. On Heroku, that is not possible.
|
||
|
|
||
|
Luckily, there are a few solutions to this problem. I'll describe one of them.
|
||
|
~
|
||
|
|
||
|
**Use the Force (of git)**
|
||
|
|
||
|
In my solution I'm using the power of git to generate the necessary CSS files and commit them automatically. Here's how it works.
|
||
|
|
||
|
In a normal situation the Sass plugin will compile the SASS or SCSS files in `public/stylesheets/sass/*.scss` and store the generated CSC files in `public/stylesheets`. What we need to do is generate those CSS files by hand and commit them just like other versioned files in our repository. To do this, you need to write a `pre-commit` hook for git. This sounds more difficult than it really is.
|
||
|
|
||
|
Here's the `pre-commit` hook I'm currently using to take all `public/stylesheets/sass/*.scss` files and store the resulting CSS files in `public/stylesheets`.
|
||
|
|
||
|
:::ruby
|
||
|
#!/usr/bin/env ruby
|
||
|
|
||
|
Dir['public/stylesheets/**/*.scss'].each do |sass|
|
||
|
basename = sass.gsub(/public\/stylesheets\/sass\//, '').gsub(/\.scss$/, '')
|
||
|
next if basename.match(/^_/) # skip includes
|
||
|
css = "public/stylesheets/#{basename}.css"
|
||
|
puts "Compiling #{sass} -> #{css}"
|
||
|
system "sass #{sass} #{css}"
|
||
|
system "git add #{css}"
|
||
|
end
|
||
|
|
||
|
Store the above Ruby script in `.git/hooks/pre-commit`, then give is execute permissions with `chmod 755 .git/hooks/pre-commit`.
|
||
|
|
||
|
This script will find all `*.scss` files and save their `*.css` equivalents. Then it also stages those files for the commit. Since this is a `pre-commit` script, the scenario is like this:
|
||
|
|
||
|
1. You stage your files to commit, like usual and run the `git commit` command.
|
||
|
2. Before git makes the actual commit, it runs the `pre-commit` script, which generates the necessare CSS files. You'll a message like `Compiling public/stylesheets/sass/app.scss -> public/stylesheets/app.css`.
|
||
|
3. With any changes to the CSS stages, your commit is made.
|
||
|
|
||
|
**Won't this spam a lot of CSS commits?**
|
||
|
|
||
|
No, it won't. Git is smart enough to see there are not changes to the content of the CSS file.
|
||
|
|
||
|
**Does it work?**
|
||
|
|
||
|
Yes, it works. The generated CSS files are deployed to Heroku like normal, static CSS files and will be served as such.
|
||
|
|
||
|
**One more thing...**
|
||
|
|
||
|
By default, Sass is set to generate CSS files when needed. Since the CSS file is already there Sass *probably* won't try to generate it again in production. But, it might try so anyway and cause an exception.
|
||
|
|
||
|
To prevent Sass for generating CSS in production completely, add the following line to your `config/environments/production.rb`.
|
||
|
|
||
|
:::ruby
|
||
|
Sass::Plugin.options[:never_update] = true
|
||
|
|
||
|
**Notes**
|
||
|
|
||
|
There is one problem with this approach. If you have multiple developers or machines you work on, each and every one must have this `pre-commit` script installed to make it work. My advise would be to include the script in your project's doc directory.
|
||
|
|