There’s a clear tradeoff with compressing HTTP responses on the fly: compress “harder” and you’ll (hopefully) get a
smaller file that takes less time to send over the network – but the net benefit might be negative if the extra work
takes too much time, or (when under heavy load) too much CPU. A lot of work has been done analysing this tradeoff, but for static
content there’s a neat and simple way to avoid the tradeoff completely: compress offline before serving. Nginx supports
this using the
The primary benefit is that you can eliminate serve-time CPU cost, while getting even better compression levels. Of course, it doesn’t work for dynamically generated content, but modern sites tend to have a lot of heavy static assets. A side benefit is that browser caches normally store the compressed response from the server, so better compression means that more of your site will fit in the browser cache. Lower network usage and better cacheability is a double win for mobile browsers.
More good news is that (at least with the DEFLATE algorithm used in gzip) higher compression levels don’t make any noticeable difference to decompression time. The compressor just works harder to find an optimal encoding.
To get a concrete feel for the size difference, here are some numbers for jquery-2.2.4.min.js:
Nginx uses gzip at level 1 (fastest) by default. As you can see, it reduces the size of this text file by better than half, which explains why it’s so popular. The last compression type, zopfli, is a relatively new algorithm designed for applications like offline compression – it prioritises compression quality over encoding speed. Here it’s cut a further 15% from the file. That’s not bad when you consider that compression is now effectively zero cost for serving.
To check if you have the
gzip_static module, run Nginx
-V flag. You should see
--with-http_gzip_static_module in the output. If you don’t, you’ll need a
copy of Nginx compiled with the
--with-http_gzip_static_module flag added to the configure script
arguments – either compile it yourself or
ask your package supplier to add the module. If you try to enable static compression without the module being
installed, you’ll get an error like
"gzip_static" on startup.
If you do have the module, things are very straightforward. There are two steps:
- Add a “
gzip_static on;” to a relevant
locationblock in your config.
- Put pre-compressed files next to the uncompressed files on disk.
On a *nix system, your Nginx configs are probably in
/etc/nginx/nginx.conf and other files in the same directory. You should
put the “
gzip_static on;” inside the blocks that configure
static files, but if you’re only running one site, it’s safe to just put it in the
http block. You can also just look for other existing gzip configuration
in your configs.
If you have “
gzip_static on;”, then “
gzip off;” disables dynamic compression, but not static
compression. This is a sensible configuration for serving static files, but it’s potentially confusing, so I suggest
adding a comment for your own sanity.
Also, if you’re serving HTTP (as opposed to HTTPS), make sure you have “
sendfile on;” in your config. On Linux, this tells Nginx to use the
sendfile system call when possible, which (among other
things) can dump a file directly onto a network link without userspace interaction. This is a good performance trick,
but doesn’t work if you’re doing processing like encryption or dynamic compression. If you’re using static compression
over HTTP, take advantage of it. On non-Linux systems, the sendfile config enables similar optimisations where
Here’s an example config. This doesn’t have most of the stuff you’d want in a production server, so adapt your existing config.
gzip_static module finds the pre-compressed files by
simply looking for them in the same directory. For example, if someone requests a file that’s located in
/var/www/static/screen.css, Nginx will check if
/var/www/static/screen.css.gz exists. If it does, it’ll send it as is,
otherwise it’ll serve
/var/www/static/screen.css as it
This means your static files directory will be full of files like
foo.js.gz. This is a bit odd, but isn’t actually a problem in most
applications (I’d be wary about using it in a user upload directory, though). Web sites these days use all kinds of
build scripts for generating static files, but as an example, here’s a *nix command that uses zopfli to pre-compress
css, csv, html, js, svg, txt and xml files in
You probably need to install zopfli – try your distro’s package manager.
Note that the above command specifically chooses file types that tend to compress well (text files). Your site possibly has other file types that are worth compressing, but experiment and don’t take it for granted that compression will make files smaller. Naïvely running zopfli on an image or movie file will tend to make it bigger, for example.
Having said that, the PNG image format uses the DEFLATE algorithm internally, and zopfli is pretty good at making
PNG files smaller, too. Use the
zopflipng command for
SVGs, etc. These can do semantic compression tricks like shortening variable names and replacing “
false” with “
!!0”. The unminified, uncompressed copy of the jQuery library used before
was 257551 bytes (252kiB). Minifying cut that down to a third (84k), and zopfli brought it down to a third again (29k).