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 with the
-V flag. You should
--with-http_gzip_static_module in the output. If you don’t, you’ll need a copy of Nginx compiled
--with-http_gzip_static_module flag added to the configure script arguments – either
compile it yourself or
beg politely ask your
package supplier to add the module.
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 available.
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
Nginx will check if
/var/www/static/screen.css.gz exists. If it does, it’ll send it as is, otherwise
/var/www/static/screen.css as it normally would.
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 that.
Also, using zopfli doesn’t negate the benefits of specialised compressors (or “minifiers”) for CSS,
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). Not bad.