Serving precompressed content with Nginx and Zopfli

2013-03-11 21:50

Zopfli is a new compression algorithm which has recently been opensourced by Google. Being deflate compatible, it can create compressed files which can then be unpacked using zlib, and thus served to web browsers without any modifications on client side.

Zopfli is focused on output efficiency, not on runtime performance, making it impractical to use for doing on-the-fly compression. It shines at compressing static content, and I will show you how in this article using Ascii Codes website as an example.

We start by fetching and compiling Zopfli:

git clone https://code.google.com/p/zopfli/ cd zopfli make

The available options are as follow:

Usage: zopfli [ OPTION]... FILE -h gives this help -c write the result on standard output, instead of disk filename + '.gz' -v verbose mode --gzip output to gzip format ( default ) --deflate output to deflate format instead of gzip --zlib output to zlib format instead of gzip --i5 less compression, but faster --i10 less compression, but faster --i15 default compression, 15 iterations --i25 more compression, but slower --i50 more compression, but slower --i100 more compression, but slower --i250 more compression, but slower --i500 more compression, but slower --i1000 more compression, but slower

We now compress the content (in our example, we want to pack HTML and CSS files):

zopfli * html * css

Alternatively, for maximum compression (1000 iterations):

zopfli --i1000 * html * css

Now, let's test the actual server configuration (Nginx + standard Gzip module):

curl https://www.ascii-codes.com --silent --header "Accept-Encoding: gzip,deflate" | wc -c 6124

The file size is 6,124 bytes: we are getting gzip content compressed on-the-fly.

We now modify our Nginx virtual host configuration to add the following directive:

gzip_static on ;

Let's reload Nginx configuration:

nginx -s reload

And finally, we test again (Nginx + Gzip Precompression module):

curl https://www.ascii-codes.com --silent --header "Accept-Encoding: gzip,deflate" | wc -c 5621

As we can see, the file size is 5,621 bytes: it now serves the Zopfli precompressed content.

For reference, here is a comparison matrix of file sizes:

file name | original size | gzip -9 | zopfli | zopfli --i1000 ------------ |----------------|----------------|----------------|---------------- cp737.html | 36,567 bytes | 6,001 bytes | 5,499 bytes | 5,494 bytes cp775.html | 36,040 bytes | 6,063 bytes | 5,540 bytes | 5,538 bytes cp850.html | 36,047 bytes | 6,149 bytes | 5,651 bytes | 5,646 bytes cp852.html | 36,120 bytes | 6,027 bytes | 5,493 bytes | 5,489 bytes cp855.html | 36,388 bytes | 6,079 bytes | 5,581 bytes | 5,578 bytes cp857.html | 35,861 bytes | 6,052 bytes | 5,575 bytes | 5,570 bytes cp860.html | 36,506 bytes | 6,132 bytes | 5,657 bytes | 5,652 bytes cp861.html | 37,185 bytes | 6,619 bytes | 6,268 bytes | 6,254 bytes cp862.html | 36,078 bytes | 6,102 bytes | 5,580 bytes | 5,577 bytes cp863.html | 36,421 bytes | 6,144 bytes | 5,677 bytes | 5,672 bytes cp865.html | 36,347 bytes | 6,154 bytes | 5,661 bytes | 5,659 bytes cp866.html | 36,595 bytes | 6,042 bytes | 5,541 bytes | 5,533 bytes cp869.html | 36,014 bytes | 6,007 bytes | 5,479 bytes | 5,474 bytes index.html | 36,035 bytes | 6,124 bytes | 5,631 bytes | 5,621 bytes

The results look pretty good indeed, and we can definitely achieve a non-negligible gain in file size using Zopfli instead of Gzip.

Every byte counts!