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.
rack-zippy (since 2.0.0) has the same convenient directory request handling provided by ActionDispatch::Static
, which means you can take advantage of this in any rack app:
- Requests for
/
and/index
respond withpublic/index.html
if present - Requests for
/foo/
and/foo
respond with first file present out ofpublic/foo.html
,public/foo/index.html
(Same behaviour for subdirectories)
Watch the Web Dev Break podcast on rack-zippy to see how you can check if your app is currently serving uncompressed assets and how quick it is to setup rack-zippy:
Add this line to your application's Gemfile:
gem 'rack-zippy'
And then execute:
$ bundle
In config/environments/production.rb
, set config.serve_static_assets
to true
:
# Puts ActionDispatch::Static in middleware stack which we are going to replace with
# Rack::Zippy::AssetServer
config.serve_static_assets = true
Create the file config/initializers/rack_zippy.rb
and put this line in it:
Rails.application.config.middleware.swap(ActionDispatch::Static, Rack::Zippy::AssetServer)
Now run rake middleware
at the command line and make sure that Rack::Zippy::AssetServer
is near the top of the outputted list. ActionDispatch::Static should not be in the list. Nicely done, rack-zippy is now installed in your app.
Add this line to your application's Gemfile:
gem 'rack-zippy'
And then execute:
$ bundle
In config.ru
:
require 'rack-zippy'
# Set asset_root to an absolute or relative path to the directory holding your asset files
# e.g. '/path/to/my/apps/static-assets' or 'public'
asset_root = '/path/to/my/apps/public'
use Rack::Zippy::AssetServer, asset_root
Follow the installation instructions above and rack-zippy will serve any static assets, including gzipped assets, from your application's public/ directory and will respond with sensible caching headers.
max_age_fallback
, is an integer value in seconds that should be used as the max_age fallback for files served by rack-zippy that live outside the /assets
subdirectory and aren't /favicon.ico
.
A typical use for max_age_fallback
is to define how long the cache lifetime for static HTML files served by rack-zippy should be. For one of my sites I have this set to 10 minutes:
max_age_in_secs = 10*60 # 10 mins = 600 secs
use Rack::Zippy::AssetServer, asset_root, max_age_fallback: max_age_in_secs
Any files given the max_age_fallback
would have the following Cache-Control
header:
Cache-Control: public, max-age=600
rack-zippy handles only files with whitelisted extensions. Default extensions are stored in the static_extensions
array with an entry for each of these:
css js html htm txt ico png jpg jpeg gif pdf svg zip gz eps psd ai woff woff2 ttf eot otf swf
You can modify this list to support other extensions by appending the lowercased file extension to the static_extensions
array:
Rack::Zippy.configure do |config|
# Add support for the given extensions:
config.static_extensions.push('csv', 'xls', 'rtf', ...EXTENSIONS TO ADD...)
end
Check your environment (in config/environments/) does not have serve_static_assets
set to false:
config.serve_static_assets = false # Oops! Should be set to true for rack-zippy
- Check
Gemfile
doesn't limit rack-zippy to a subset of environment groups - Run
bundle install
- Check
Gemfile.lock
contains an entry for rack-zippy
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Run tests (
rake test
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
To try a local branch of rack-zippy out as the gem dependency in a local app, configure bundler with a local gem override as follows:
In your-app/Gemfile
: edit the rack-zippy dependency to the following:
# The branch your-local-branch-name **must** exist otherwise bundler will shout obscenities at you
gem 'rack-zippy', :github => 'eliotsykes/rack-zippy', :branch => 'your-local-branch-name'
At the command line, inside your-app
, configure bundler to set a local git repo to override the one we specified in the previous step for rack-zippy:
$> bundle config --local local.rack-zippy /path/to/your/local/rack-zippy
Now when you run your-app with bundle exec
, the rack-zippy gem dependency will resolve to /path/to/your/local/rack-zippy
.
Cleanup time! When you’re finished testing, delete the local override and set your Gemfile dependency back to the original:
# At the command line:
$> bundle config --delete local.rack-zippy
# In your-app/Gemfile change rack-zippy dependency to this (or similar):
gem 'rack-zippy', '~> 9.8.7' # Replace 9.8.7 with the rack-zippy release version you want to use.
- Eliot Sykes https://eliotsykes.com
- Kieran Topping https://github.com/ktopping
- Luke Wendling https://github.com/lukewendling
- Anton Petrunich https://github.com/solenko
- ssemakov https://github.com/ssemakov
- Update pre-release version to the release version in
lib/rack-zippy/version.rb
, e.g.1.0.1.pre
becomes1.0.1
- Update
CHANGELOG.md
version and date. Update Contributors inREADME.md
. - Tests pass? (
rake test
) - Commit and push changes to origin.
- Build the gem (
rake build
) - Release on rubygems.org (
rake release
) - Update version to the next pre-release version in
lib/rack-zippy/version.rb
, e.g.1.0.1
becomes1.0.2.pre
. - Add new heading to
CHANGELOG
for the next pre-release - Commit and push the updated
lib/rack-zippy/version.rb
andCHANGELOG
files.