Developer Blog

← Home

Asset Compression with Brotli for Improved Website Performance

by Louise Swift

Part of our ongoing website performance improvement work has been to implement Brotli compression for Beano.com's static assets.

It was a rewarding change to implement since it provides a specific benefit from a couple of reasonably straightforward config updates.

Note: Brotli compression can be applied on-the-fly, where the server compresses the assets upon request, but we are currently using Webpack to create Brotli-compressed versions of our assets when compiling assets during production builds. These Brotli-compressed assets are then available for Nginx to send to compatible clients on request.

What is Brotli compression?

Brotli is a compression algorithm, like gzip or deflate.

It results in smaller files than gzip or deflate, however, because of several algorithmic and format level improvements, including "a pre-defined dictionary of frequently used words and phrases".

Modern browsers can accept Brotli-compressed assets because they know how to extract them. They signify this by including br in the Accept-Encoding header of their requests, e.g.:

accept-encoding: gzip, deflate, br

Browser support for Brotli is great, although of course a non-Brotli fallback version of every asset file should always be available.

Importantly, Brotli compression is named after the Swiss word for bread rolls.

How did we implement Brotli compression?

We implemented Brotli compression for our static assets via one Webpack plugin, one Nginx module and one configuration update to the container our frontend application runs in.

This implementation does not provide on-the-fly compression. It allows us instead to provide Brotli-compressed versions of our assets ready for Nginx to send in response to requests from supporting browsers.

We are monitoring the impact of every performance-affecting change we make to Beano.com, so we will be testing on-the-fly compression separately.

The Webpack Plugin

We used brotli-webpack-plugin, which can compress JS, CSS, SVG and HTML assets.

Its options include a threshold (choose a minimum file size to qualify for compression) and minRatio (a compression result minimum requirement).

We used the defaults so our implementation is fairly straightforward:

// webpack.config.js
const BrotliPlugin = require("brotli-webpack-plugin");

module.exports = {
// ... remainder of webpack config here

plugins: [
new BrotliPlugin({
asset: "[file].br",
test: /\.(js|css|svg)$/
})
]
}

The Nginx Module

We used Google's nginx-brotli module. It offers both on-the-fly compression and/or the serving of precompressed files.

The steps in this guide are equivalent to what we used in our frontend application's Dockerfile to install Nginx 1.10 with the nginx-module enabled.

Our application's Nginx config could then be updated with:

# nginx/app.conf

brotli off; # enable/disable on-the-fly compression of assets
brotli_comp_level 6; # set quality/compression level (0-11)
brotli_static on; # enable/disable serving of existing .br assets
brotli_types text/xml image/svg+xml application/x-font-ttf image/vnd.microsoft.icon application/x-font-opentype application/json font/eot application/vnd.ms-fontobject application/javascript font/otf application/xml application/xhtml+xml text/javascript application/x-javascript text/plain application/x-font-truetype application/xml+rss image/x-icon font/opentype text/css image/x-win-bitmap;

Confirmining Correct Implementation

Using your browser's Developer Tools, you can inspect the headers of any request and response by opening up the Network tab and initiating the request, i.e. visiting a page of your site.

For example, you might provide a main.js.br version of your main JavaScript bundle.

If so, the Network tab should show this response header for that file:

  Content-Encoding: br

Brotli compression implementation complete!

How much did Brotli compression improve our site's performance?

Testing otherwise-identical builds of our app with and without Brotli compression enabled showed small improvements across metrics like Time To First Byte and First Contentful Paint.

However, these small improvements combined into an overall 0.5s improvement to the Time To Fully Loaded metric, for a throttled "3G Fast" lower-end mobile device test profile.

Brotli compression is clearly a key step in the journey towards a performant website. And with the multiple implementation options available, there's a configuration to suit almost any application.