Blog Entry - Improving Page Performance

18th October 2019

As of writing this post, Pictochat is hosted using a free-tier Heroku server (https://hidden-brushlands-32548.herokuapp.com/), and was tested using PageSpeed Insights. The website received a score of 62 for desktop devices, but only a 13 for mobile devices. This was not a shocking result, as the primary concerns during the semester were mostly regarding the usability and performance of desktop devices.

Google PageSpeed Insights also provides users with a list of strategies to potentially improve loading times. For both the mobile and desktop tests, PageSpeed Insights recommended to serve text-based resources using compression with such standards such as gzip, deflate, or brotli. The main reason these compression techniques are recommended is due to the speed improvements they provide. Compressing a file ultimately decreases the amount of data that is required to be sent. If less data is required to be sent, then it will theoretically take less time to send. When viewing the response of the bundle.js within the network tab, the amount of data sent is around 800KB, which can definitely be improved.

Looking into the compression rates for these three standards, it can be noted that brotli has a 14% compression improvement over gzip (https://blogs.akamai.com/2016/02/understanding-brotlis-potential.html). However, not all browsers support brotli, which means we will also have to provide a fallback to gzip in case a user is using a browser such as Internet Explorer.

In order to set up compressions for our bundle files, we will need to modify the webpack bundling process, as well as the way we’re serving the bundle from the server. Firstly, we will need to add in two new webpack plugins, which will generate a compressed version of the bundle.js file using the two algorithms. (the code snippet for this can be viewed below).

const CompressionPlugin = require('compression-webpack-plugin');
const BrotliPlugin = require('brotli-webpack-plugin');

new CompressionPlugin({
  filename: `[path].gz[query]`,
  algorithm: 'gzip',
  test: /\.(js|css|html|svg)$/,
  threshold: 10240,
  minRatio: 0.8,
  deleteOriginalAssets: false
}),
  new BrotliPlugin({
    filename: `[path].br[query]`,
    test: /\.(js|css|html|svg)$/,
    threshold: 10240,
    minRatio: 0.8,
    deleteOriginalAssets: false
  });

Secondly, we need to tell the server to serve the correct file based on the incoming request’s “accept-encoding” header. This can be handled using the “express-static-gzip” package. (the code snippet for this can be viewed below).

import express from 'express';
import expressStaticGzip from 'express-static-gzip';

/**
 * @param webContentDir Directory containing the files that should be served
 */
export function makeFrontEndRouter(webContentDir: string) {
  const router = express.Router();
  router.use(
    '/',
    expressStaticGzip(webContentDir, {
      enableBrotli: true,
      orderPreference: ['br', 'gz'],
      serveStatic: {
        maxAge: 234, // will be kept
        cacheControl: false // will be kept as well
      }
    })
  );
  return router;
}

After applying these changes and running the website on local (ensuring the production webpack settings are used), the size of bundle.js has halved to 430KB. Additionally, testing the page on PageSpeed Insights shows us that the score has increased to 79!