📜 ⬆️ ⬇️

We implement Brotli with the help of Nginx - we save bytes almost for free

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 compressionSize (bytes)Size (% of original)
CSS source files334 937100%
CSS zopfli60 77118.1%
CSS brotli56 16816.7%
Js source files477 393100%
Js zopfli149 90531.4%
Js brotli135 76628.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 

Source: https://habr.com/ru/post/310200/


All Articles