Just recently my mobile data connection was throttled and I was faced with uber-slow download rates. As a consequence it is almost impossible to check links shared by my friends. But I am a friend of performance and a small footprint. So I took this opportunity to check my site. Here is how I improved the performance of my site.

Where we start from…

For creating and managing my website I’m using Jekyll. I really like the simplicity: flat-file based, simple workflow, supports all the tools you really need (Markdown, Liquid template engine, SASS).

To get started I build a layout on top of Bootstrap. Naturally I optimized my JavaScript files(by grabbing them from a CDN) and CSS(minification). That leaves us with the following stats:

  • Page size: 236KB (31.8% JS, 44.9% CSS)
  • Requests: 9

Compare the Google homepage to that (without ad-blocker, not logged in):

  • Page size: 62.8KB
  • Requests: 16

That is obviously a no go and we can already see where it comes from: a lot CSS and bit too much JS. Let’s see what we can do.

Bootstrap: Makes your life easier, but also bloated

I already pointed out that I’m using bootstrap. And even though I minify the CSS and JS files the still make up more than 80% of my website’s size. Checking my site I come to the conclusion that I only need one JavaScript plugin from Bootstrap. That is the accordion on my Projects page. I customize the JavaScript file on the Bootstrap website and my new bootstrap.min.js is now 4.1KB instead of 36.9KB! Way to go.

Now let’s tackle the CSS! I’m using Bootstrap because of all the nice features: mixins, configurable, a lot of components. That is really great, but do I need all the components? Certainly not! So I head over to my main.scss which is used by Jekyll to compile my CSS. Instead of importing the standard Bootstrap file it’s time to create my customized one! To do this I just grab the default file and remove all the components I don’t need. This leaves me with 14 out of 39 imports. All in all, this way I reduce the size of my Bootstrap import to 52.5KB(minified)!

Check the Configuration section of the bootstrap-sass repository to see how you can minimize the imports.

Another look at our statistics:

  • Page size: 150KB (28% JS, 36% CSS)
  • Requests: 9

Way better! Especially if we consider, that the JS and CSS files can be cached!

Now after stating the obvious…

For sure, these optimizations are common sense and performed regularly. Now how to improve on that? The answer lies in a nice little Grunt plugin. grunt-uncss helps us remove unused CSS rules. Let’s try it and see what happens!

Right now my Jekyll setup is a bit messy so I had to adopt the htmlroot parameter:

module.exports = function(grunt) {
    grunt.initConfig({
        // ...
        uncss: {
            dist: {
                options: {
                    htmlroot: 'jekyll-src/_site', // helps uncss load referenced css files
                },
                files: {
                    './jekyll-src/_site/css/bootstrap.min.css': ['jekyll-src/_site/**/*.html']
                }
            }
        }
        //...
    });
};

After running my task I get the following info:

Running "uncss:dist" (uncss) task
File ./jekyll-src/_site/css/bootstrap.min.css created: 53.58 kB → 7.95 kB

If that is not some optimization I don’t know what is! Now unfortunately my accordion does not work anymore. So I adjust the configuration and exclude some of the CSS selectors.

// uncss configuration ...
ignore: ['.collapse.in']
// ...

Conclusion: Optimized!

Before the optimizations my website was around 236KB big(measured for the Projects page). The first step reduced that to 150KB. After the final optimization using UnCSS it is only 101KB in size. That is a reduction by ~42% without touching the build process too much. A last look at the statistics:

  • Page size: 101KB (36.4% JS, 9.4% CSS)
  • Requests: 9

I think that shows how easy it is to optimize a small site, especially when using frameworks like Bootstrap or jQuery. The biggest objects to load are now the minified jQuery and the fonts. Further optimization might be done in the area of request amount. Maybe one could merge bootstrap.min.js and jquery.min.js. Also the loading of fonts might be further optimized.

Is that really necessary? Probably not. Fetching jQuery from a CDN almost certainly ensures that the user has it already cached. The caching also accelerates further requests to the site. For example requesting the Projects page a second time only 2.2KB are transferred. That is easy to fetch even for a throttled mobile connection. The same goes for navigating to other pages, even though the loading of fonts is mostly on top of the requests.