This article is useful to anyone who is not indifferent to the speed of delivery of your web application to the user and wants to squeeze out an extra millisecond and kilobytes of savings.
What is brotli?
This is a new data compression standard developed by Google.
Clouflare has a good description and comparison with other algorithms.
In a nutshell: this is a new kind of compression that is optimized for web applications (HTML, CSS, JS, etc.) through the use of a static dictionary and other optimizations. It shows comparable speed with better compression compared to gzip and much better compression with maximum settings (and very low speed). A detailed study of the speed and compression ratios, see the specified article from Cloudflare.
')
I will provide a small table with real files (JS, CSS) of a live website. Before compression, all files were minified. Let's
compare zopfli (i500) - compatible with gzip compressor and brotli with compression setting 11 (maximum).
File type and compression | Size (bytes) | Size (% of original) |
---|
CSS source files | 334 937 | 100% |
CSS zopfli | 60 771 | 18.1% |
CSS brotli | 56 168 | 16.7% |
Js source files | 477 393 | 100% |
Js zopfli | 149 905 | 31.4% |
Js brotli | 135 766 | 28.4% |
From this table, you can estimate the savings for the use case in static mode (when the files are compressed in advance and given to Nginx as is). Compression of dynamic content is a bit more complicated - you need to maintain a balance between the degree of compression and compression time.
For myself, I derived the following rule: at the expense of
zopfli, you can save about 10% compared to
gzip 9 , and
brotli gives you another 10% savings.
Browser Support
Good enough to use now. According to
caniuse.com, that's about 50% of the audience. In fact, I think more, because brotli is supported in Chrome 51+, Firefox 47+ and mobile Chrome. Important addition: since brotli is incompatible with gzip, it is supported
only for HTTPS resources . This is so all sorts of stupid proxies do not beat the content.
It’s simple to look at customer support: it should specify accept-encoding
br in the request header, which means “brotli”. For example:
accept-encoding: gzip, deflate, sdch, br
We include support in Nginx
Unfortunately, there is no standard module to support
brotli in
Nginx . But we can't stop us with this: there are third-party modules from Google itself and from Cloudflare. We will use the option from Google, as it is normally documented and has all the necessary features.
Here you need to decide how you will use
brotli : only in a static version (
brotli_static ) or in a dynamic version (compression on the fly - brotli). Building the module in brotli_static mode is simpler, since a library is not required for brotli compression:
libbrotli .
We use a ready-made package from PPA
We will use
Ubuntu 16.04 as a server. This is where PPA comes to the rescue:
https://launchpad.net/~hda-me/+archive/ubuntu/nginx-stable . From the PPA, we get
Nginx Stable branches with many additional modules. Most of them are dynamic, that is, they can be connected at will. If you are satisfied with this option, you can set and go to the configuration.
We collect Nginx independently
In this case, the process is similar to building Nginx with any other modules. First, download and unpack the Nginx sources (the current version is listed at the time of publication).
wget https://nginx.org/download/nginx-1.11.4.tar.gz
Get the code for the ngx_brotli module:
git clone https://github.com/google/ngx_brotli.git
If we want to use brotli in dynamic mode, download libbrotli:
git clone https://github.com/bagder/libbrotli.git
And collect (in the folder libbrotli):
./autogen.sh ./configure make
Or we can install libbrotli from the
PPA specified earlier.
sudo add-apt-repository ppa:hda-me/nginx-stable sudo apt-get update sudo apt-get install libbrotli
If we only need brotli_static, before building Nginx we talk about this:
export NGX_BROTLI_STATIC_MODULE_ONLY=1
Now go to the folder with the Nginx source code and build it (with the option
--add-module = [path to ngx_brotli] ):
./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_geoip_module=dynamic --with-http_perl_module=dynamic --with-threads --with-stream --with-stream_ssl_module --with-stream_geoip_module=dynamic --with-http_slice_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --with-http_v2_module --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,--as-needed' --add-module=/home/db/ngx_brotli make
Next, you can install Nginx (
make install ) or build a deb package:
sudo checkinstall --pkgname=nginx --pkgversion=1.11.4 --nodoc
Nginx configuration
So, we finally have
Nginx with
brotli support. To use static
brotli files (compressed in advance), it is enough to include one directive in the
nginx.conf configuration (section
http ):
brotli_static on;
Now nginx will look for a version of the file with the
.br suffix if the client declares support for
brotli . If it does not, then the gzip_static module will work (if enabled).
To activate the dynamic mode, specify the following parameters:
brotli on; brotli_comp_level 6; brotli_types text/plain text/css text/xml application/x-javascript;
Here we use compression level
6 , because it has a good quality / performance ratio. The compression level will be better than with
gzip 9 . The following are
MIME content types for compression. Refine the configuration of your
MIME types on the server so that compression is applied to the desired content types.
Brotli has priority over
gzip , so it will be used in case of support (also for static mode).
Checking brotli is easy: look at the response headers, it should be there:
content-encoding:br
That's all: success in optimizing and use new technologies!
PS If you are using Ubuntu 16.04, then installing the brotli console compression utility is very simple:
sudo apt-get install brotli