#1 By: eliotsykes, October 29th, 2013 10:08
Please forgive me for posting about one of my own gems, but I hope this will help those of you looking to shrink your asset downloads. From the README for rack-zippy:
rack-zippy is a Rack middleware for serving static gzipped assets precompiled by the Rails asset pipeline into the public/assets directory. Use it on Heroku if you want to serve the precompiled gzipped assets to gzip-capable clients with sensible caching headers.
By default, Rails + Heroku will not serve *.gz assets even though they are generated at deploy time.
rack-zippy replaces the ActionDispatch::Static middleware used by Rails, which is not capable of serving the gzipped assets created by the rake assets: precompile task. rack-zippy will serve non-gzipped assets where they are not available or not supported by the requesting client.
You'll find it on GitHub here: https://github.com/eliotsykes/rack-zippy
#2 By: Ryan Daigle, October 29th, 2013 10:54
Thanks for this, @eliotsykes! For this interested in the background - here's a great article about rack-zippy.
Another option is to use Rack Deflater:
You can quickly reduce the amount of data transferred from your Rack or Rails application with Rack::Deflater. Anecdotal evidence shows a reduction â¦
It appears the difference is that Rack Deflater compresses files in real-time whereas rack-zippy just serves up the pre-generated static files. Both would benefit from an upstream rack-cache middleware which would then cache the compressed results. Accurate?
#3 By: eliotsykes, October 29th, 2013 12:26
You've reminded me of one of the reasons I needed rack-zippy when there were existing Rack middleware to do almost the same thing.
The BREACH attack  preys on HTTP responses served over SSL that are compressed.
BREACH can identify a repeated secret in a response such as an API token or CSRF token.
One way of avoiding this attack is to not compress secret-containing responses. At least some of the other asset compression middlewares compress all responses (not just .css and .js files) by default. I'm guessing these middlewares were written before the BREACH attack was discovered. I can't remember if Rack Deflater falls victim to this.
For both middlewares I'd expect to see the greatest benefit by using a CDN for serving your assets. Once the gzipped and non-gzipped assets are cached in the CDN, your app doesn't have to do any work on the assets again.
For anyone wondering how to setup a CDN for a Rails app, see the config.action_controller.asset_host setting. You'll probably want to set it in your production.rb. As far as picking a CDN goes, I've found Amazon Cloudfront  a good option.
#4 By: Richard Schneeman, October 29th, 2013 15:00
@eliotsykes have you explored getting this or something like it into Rails by default? Seems anyone not running behind nginx would benefit by serving .gz files by default.
#5 By: clint, October 29th, 2013 16:54
So this tool works with a CDN, or in place of one? Meaning, is it still useful when you're already using a CDN?
What I'm hearing is that Rails compiles the gzipped assets, but won't serve them itself. The CDN then also won't get those gzipped assets? But with this middleware, it will?
#6 By: eliotsykes, October 30th, 2013 07:41
@schneems If memory serves, there is a long standing issue on the Rails github repo to incorporate serving gzipped assets into the Rails core - hopefully its still open.
@clint Using a CDN and rack-zippy together ought to give an app a bigger performance boost than using only one of those.
Yes, Rails will create a gzipped version of the assets (when the rake assets: precompile task is run).
It seems odd, but by default, Rails (at time of writing) will never serve those gzipped assets, even though it created them. So if you're using a CDN, it also won't serve those assets gzipped.
To serve those gzipped assets, use a middleware like rack-zippy. If you're using a CDN, then the CDN will also serve those gzipped assets (assuming it handles the 'Vary' and 'Content-Encoding' HTTP headers correctly).
Curl can help verify if a CDN is handling these correctly. To mimic a client that is gzip-capable:
curl -I -H 'Accept-Encoding: gzip' https://my-cdn.tld/assets/application-abc8636a47d6fb93c71a3a707cdfe1a2.css
If operating correctly, this should give you response headers that include the following:
Status: 200 OK
Compare the output of that curl command with this one to mimic a client that can't handle gzip encoded responses, for the same URL:
curl -I https://my-cdn.tld/assets/application-abc8636a47d6fb93c71a3a707cdfe1a2.css
In this case, you should see response headers that include:
Status: 200 OK
Notice there is no 'Content-Encoding' response header and that the 'Content-Length' header is much larger than from the gzipped response (4840 vs 28988 in the example).
#7 By: clint, October 30th, 2013 09:36
Interesting. Thank you for the clarification.
#8 By: guilleiguaran, October 30th, 2013 18:31
It was suggested in Rails issue tracker but we suggested to do it in Rack to benefit to all users, not only to Rails users. There are a PR for it in Rack: https://github.com/rack/rack/pull/479
#10 By: jon408, October 31st, 2013 13:43
Here is the Rail's PR. It's currently closed but I'd love to see it reopened. Feel free to at a +1 if you agree:
changed 4 files
with 61 additions
and 32 deletions.
#11 By: jon408, October 31st, 2013 13:43
I've also extracted the functionality of the PR into a gem, which basically does the exact same thing at zippy.