80% Smaller Rails Page Size With Rack Deflate
08 Nov 2017Do you have 5 minutes? Do you want to decrease the “over the wire” size of your Rails app by 80%? Sure you do! I added Rack::Deflate to CodeTriage.com, the best way to get started in Open Source, and went from a page size of 85,523 bytes to 15,568 bytes (over the wire). You can verify with this retro looking web based compression tool.
First up, what does Rack Deflate do and why do we want to use it? Rack Deflate uses Zlib::GzipWriter
to compress the body of your web page before responding to a request. Later, when the client gets the response from the server, it will see that it is compressed based on the Content-Encoding=gzip
header and unzips the web page before attempting to render it. It might sound like a bunch of hoops to jump through, and couldn’t possibly be faster than just sending the raw page, but that’s not the case. In general, CPUs are fast, and networks are slow. It’s much faster to send less data “over the wire” even if we have spend time to compress and expand that data.
How much could this compression trick possibly help? Well, before I added this to CodeTriage, a page render of the homepage with me logged on took roughly 578ms
.
After adding Rack Deflate it dropped to about 422ms
.
While those numbers vary a bit, it seems to be consistently about 100ms faster. It makes even more of a difference if you’re on a slower connection, such as a mobile phone in a spotty area, or if you’re on 3G. Not bad for a few minutes of work.
Rack Deflate ships with Rack so you don’t need to add any extra dependencies. To add it to your Rails app all you need to do is add this line of code to your config/application.rb
config.middleware.insert_after ActionDispatch::Static, Rack::Deflater
That’s it. Commit to git. Push to Heroku (or wherever else deploying Rails apps is delightful for you). Watch your over-the-wire footprint drop like a rock. Here’s the commit where I added Rack::Deflater to CodeTriage.
What does this line do? If you’re serving static assets from your Rails app, it’s being done from the ActionDispatch::Static
middleware. This line makes sure that the Rack::Deflater
comes after the static asset middleware. I did this because otherwise if you’re using a recent version of Rails that supports serving GZIP files from disk, and a recent version of Sprockets, then some files will already be gzipped. By default Rack Deflate will attempt to re-gzip any body that you throw at it. Gzipping a binary file or one already gzipped won’t help so this helps avoid double work.