Case study: Improve Page Speed with Minification & Compression

28 Feb 2019 8 minutes

In this article, we will discuss how and why it is important to minify assets upon deployment before serving them across Gzip and Brotli.

It is important to note that we will only discuss the areas around “minifying” files and compression with Gzip and Brotli on the basis of sending them from a web server to a client browser.

What is Minification?

In recent years, the term “minification” has been used to describe the process of reducing the file size of JavaScript and Cascading Style Sheets (CSS) as much as possible without compromising functionality.

For example, the following JavaScript function could be reduced from:

function printName(name) {
 // Prints a String to the console.
 console.log(name);
}

To this much shorter version:

function a(b)

Expressive code is more easily read and understood by the developer. In the first example, there are 86 characters to transmit, and in the second, there is only 29. Understanding what function a has however, is less immediately obvious than printName.

Expressive code can be advantageous during the stages of development and testing. Minification therefore should be delayed until the code is deemed suitable for deployment on the production environment.

While the browser may use the minified code for the user, beautified code can be viewed in the developer toolbar to help with debugging in production by using source map files. These files are only downloaded if the source maps are enabled and the dev toolbar is open.

What is the Best Way to Minify Assets?

Web application frameworks can include minification modules to statically generate files.

This however, will depend on the programming language used:

  • JavaScript frameworks may use Gulp
  • Ruby on Rails may use Uglify (a wrapper for UglifyJS) (default)
  • PHP frameworks may use Composer

Content delivery networks can also offer this service, and Cloudflare has become a one-stop solution for minification and compression with Gzip and Brotli compatibility.

What is Compression?

Compression is a process that reduces duplication in a dataset, usually having the desirable effect of reducing the size of the dataset. This is done by detecting repeated patterns and replacing them with more efficient encodings, as with run-length encoding, or with references to table of these patterns, as with LZ77-based DEFLATE algorithm used by GZip.

The reverse of this process is called decompression. Decompression is used to reproduce or approximate the original dataset.

After compression, less bytes are required to store and transmit the dataset.

Compressors often have a level which can be adjusted to trade compression or decompression time for greater reductions in size.

Changes to a dataset may be reflected in the internal data structures used during compression and maintained in the output. When these changes result in smaller internal data structures or more detectable patterns this leads to greater compression.

What Assets Should be Compressed?

Cloudflare can return both Gzip or Brotli encoded responses for many different types of files including:

  • HTML
  • CSS
  • JavaScript
  • JSON
  • XML
  • Plain Text
  • Font Files

A full list of compression files can be found here.

Cloudflare will only auto minify resources which don't use a .min.xx file format, to avoid accidental double compression. (Double compression is bad).

Gzip Compression

The Gzip compression level ranges between 1-10, with one being the fastest and largest, and 10 being the slowest and smallest file size.

A research piece by Jarrod on Root Users shows Gzip as a benchmark against other compression types. His research suggests that Gzip level 6 is a good trade-off between compression/decompression size and time.

Brotli Compression

Like Gzip, Brotli compression level starts at level 1, although it can go as far as 11.

In this research piece, written by Sam Saffron, we see the comparison between different Brotli compression levels.

His research concludes that Brotli at level 5 is competitive with Gzip, and that it starts using context modelling at this level, which is an advanced feature of the format.

Starting the Benchmarks

Before we begin, there are specific prerequisites for benchmarking a bash script called multitime. It's available on Github to download (or build a binary yourself).

We took the beautified.js file and ran it through UglifyJS, which would be a one-off cost for each server deployment.

Now that we have these files, we can compress them both using Gzip level 6 (recommended) and Brotli level 11 (default).

NormalGzipBrotli
Beautified.js733k180k147k
Minified.js283k84k73k
  1. Gzip saves 75.4% and Brotli saves 79.9% from Beautified.js.
  2. Gzip saves 70.3% and Brotli saves 74.2% from Minified.js .
  3. Gzip saves 88.5% and Brotli saves 90.0% when starting from Beautified.js, minifying it and compressing respectively.

This overall file size saving reduces the file transfer size from the server to the browser.

From the above table, it is evident there are considerable savings, but we also need to understand the computational cost.

This computational saving is important for server stacks that could have to handle hundreds of thousands of people on a website at any given time.

Dynamic Compression

Both Gzip and Brotli offer dynamic compression, and the following modules are used to compress Gzip:

To understand how much time is required to compress the files, we ran a benchmark test for compressing our JavaScript file. For this, we used multitime to wrap the Postfix time before reporting back.

The following command runs the script 100 times with a confidence level of 95%. Here, we are mainly interested in the average (median) time, as environmental fluctuations can occur (shown with the standard deviation).

GZIP

multitime -n 100 -c 95 gzip -kf -6 beautified.js

MeanStd.Dev.MinMedianMax
real0.037+/-0.00070.0040.0310.0360.047
user0.031+/-0.00040.0020.0280.0310.039
sys0.004+/-0.00030.0010.0020.0040.009

multitime -n 100 -c 95 gzip -kf -6 minified.js

MeanStd.Dev.MinMedianMax
real0.016+/-0.00040.0020.0130.0170.021
user0.013+/-0.00020.0010.0110.0130.015
sys0.003+/-0.00010.0000.0020.0030.005

The beautified file took 36 milliseconds, while the minified file took 17 milliseconds.

Brotli

multitime -n 100 -c 95 brotli -kf beautified.js

MeanStd.Dev.MinMedianMax
real1.761+/-0.03830.1951.5671.6992.626
user1.710+/-0.02750.1401.5491.6652.183
sys0.029+/-0.00300.0150.0130.0240.084

multitime -n 100 -c 95 brotli -kf minified.js

MeanStd.Dev.MinMedianMax
real0.681+/-0.01180.0600.6180.6530.882
user0.658+/-0.00980.0500.6040.6350.822
sys0.017+/-0.00140.0070.0090.0140.036

Compressing with Brotli takes a considerable amount of time to compress in comparison to Gzip. The beautified file takes 1,699 milliseconds while the minified file takes 653 milliseconds.

Introducing Static Compression

Web servers can use a statically generated version of an asset. The initial cost is that the server will need to compress all files beforehand. This means a one-off cost can be used to create the compressed version of the asset, which is then served.

The server simply adds the standard file extension to file the compressed version. Gzip is ".gz" and Brotli is ".br"

Here are some installation guides for both Gzip and Brotli:

These web servers check the VARY HTTP header and route the request to either the static .gz version or .br version according to the request made.

How Much Does it Cost to Decompress?

Once the files have been compressed and sent across the Internet to the web browser, the next step is for the browser to decompress the file.

GZip Results

Decompressing the beautified.js.gz file:

multitime -n 100 -c 95 gzip -dkf beautified.js.gz

MeanStd.Dev.MinMedianMax
real0.009+/-0.00030.0020.0070.0090.013
user0.004+/-0.00010.0010.0040.0050.005
sys0.003+/-0.00010.0010.0020.0030.005

Decompressing the minified.js.gz:

multitime -n 100 -c 95 gzip -dkf minified.js.gz

MeanStd.Dev.MinMedianMax
real0.008+/-0.00050.0020.0050.0070.019
user0.003+/-0.00010.0010.0020.0030.006
sys0.003+/-0.00030.0010.0020.0030.009

Brotli Results

Decompressing the beautified Brotli file:

multitime -n 100 -c 95 brotli -kdf beautified.js.br

MeanStd.Dev.MinMedianMax
real0.013+/-0.00060.0030.0080.0130.019
user0.005+/-0.00020.0010.0040.0050.008
sys0.004+/-0.00030.0020.0030.0040.009

Decompressing the minified Brotli file:

multitime -n 100 -c 95 brotli -kdf minified.js.br

MeanStd.Dev.MinMedianMax
real0.009+/-0.00040.0020.0060.0090.015
user0.003+/-0.00010.0010.0020.0030.006
sys0.003+/-0.00020.0010.0020.0030.006

Summary

NormalGzipBrotli
Beautified.js733K180k147K
Minified.js283K84K73K

Our tests have consistently shown that minification leads to more efficient compression. Static compression is preferable over dynamic compression. We can also conclude that Brotli results in the smallest file at the end of the process, but both should be enabled in case the browser not being able to support one or the other.

Share