One of the first movies I ever saw in a cinema was in my tiny home town Nova Gradiška in Croatia. The movie playing that day was Gone in 60 seconds. As you can imagine I was blown away. My first movie on the big screen. And at the time there were a lot of popular actors in it like Nicolas Cage, Angelina Jolie, Vinnie Jones and others. Really an experience I remember to this day as you can see. In particular a scene from that movie seems like a great intro to this article. So, before you continue, play the video and get yourself into the performance groove. Don't forget to do the finger thing that Cage does 😂
Before you think "Oh no, yet another guide I'll never actually be able to implement on my website" let me stop you there! More or less everything we will go through in this article is easily achievable. In some cases, some things might take 2 minutes and some might take longer but in general, the goal is to bring your website performance up as fast as possible.
Personally, I'm very passionate about website performance, loading times and optimizing everything in the stack to run as smoothly as possible. For the past 10 years I've spent a lot of my time chasing milliseconds in our software development company.
Performance is something we included in every of our projects and the same is with our startup - Treblle. To be honest my obsession with performance is probably the reason why we were able to build Treblle. Besides that, I’ve also spent a lot of time consulting for other companies on how to improve performance. Going after their developers and tidying things up.
Recently, I've even broken down my monolith into microservices for better performance on the backend as well. How I did that using Singlestore is another story you can read.
Based on my experience I came up with a list of things you can do almost day one on any project that would improve the speed drastically and show a noticeable improvement. Some will take time but most are hassle-free.
When someone visits your website they probably don't see the entire website but only, what in the marketing world they call, "above the fold" content. In most cases that includes a hero element with either text, images/video and a call to action. Below that is everything else explaining why your product or startup is the next big thing (same as ours 😎). More often than not a user might only view that hero element, scroll a few times but won’t reach the end of the website.
So why load all the images, videos, iframes and content that nobody will see?
That right there is the fundamental idea behind lazy loading. It’s probably the simplest and most effective thing you can do to improve your website load time. The reason why it has such a huge impact is because 90% of the time the content we are loading on the rest of the website are images and videos.
So if you have 20 - 30 images on your website and the users can only see 3-4, why load the rest? Sounds logical - it is - but you would be surprised at how many websites don't do this. Especially considering that it’s super easy to add it to your website.
<img> element as well as picture elements which is great for responsive design.
To use it simply replace your existing
<img> elements with the following:
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="path-to-my-image.jpg" class="lazyload" alt="Lazy loaded image">
Note that the path to the real image is in the "data-src" attribute and to enable lazy loading you have to add a class of "lazyload". You also might be wondering what the mambo jumbo in the "src" attribute is. Well it’s basically a really tiny image with a light gray background. This is used to fill up the space and not cause jumps in layouts shift while the image is "replaced". In any case you are done. Nothing more or less to do. The plugin has more options which you can check out on their website.
Another way you could start using lazy loading is by utilizing a new HTML standard attribute called
loading. Now it does have limited support but it is probably the future of lazy loading and it will be a default HTML attribute once everybody starts supporting it.
You use it by adding
loading="lazy" to any image element like so:
<img src="image.png" loading="lazy" alt="Lazyloaded image" width="200" height="200">
Again, maybe wait a bit with this one because it’s lacking support for older browsers but definitely keep an eye for it.
I'm adding this because it has a huge impact and it’s dead simple to do. Yet - most people don’t do it. When you are using images as design elements, backgrounds and such simply run them through something like ImageOptim or JPEGMini. I've been using the FREE Mac app of ImageOptim for years and it works like a charm. In some cases it reduces images by like 80% and I simply get shocked. You don't have to think about it, simply drag and drop the images and they are automatically saved as optimized images with as little as possible quality loss. They also have a webservice so you can connect your user generated images with their API and have them optimized as well.
As far as SVG goes I use another free and awesome service called SVG Nano. It's just like ImageOptim but for SVGs and the results are astonishing. You can have a Full HD illustration cut down to like 10KB which is great.
Minify and compress
A must do when working with CSS and JS is to minimize them! Don't use a non minimized version of your code or other plugins/packages/dependencies in production. Simply don't. You can manually minimize the CSS/JS via tools like this: https://minifycode.com/ or https://www.minifier.org/. Ideally you should include minification in your build process either via Webpack or some other tool. If you don't know how to do any of those then you can maybe download already minified versions of various frameworks and JS plugins.
Just consider this: a non minified and uncompressed version of Jquery is 290Kb whereas a minified and compressed version is 90KB. You just saved 200KB or 70% of the download size!
Preconnect is a relatively modern type of link element that became popular with HTML5 and HTTP2. The idea behind it is super simple but very effective. By adding one or more preconnect tags to the
<head> element of your website you tell browsers that, down the line, you will eventually download something from that domain. Browsers can initiate a connection and essentially prepare whatever they need to instantly download something from that domain. This as you can imagine can speed things up for you - especially if you are downloading fonts, images and JS. Using preconnect could not be simpler. Before you call on any CSS and JS in your
<head> element add one of these:
<link rel="preconnect" href="https://domain.com/" crossorigin>
And that's it. Later on if you're downloading something from domain.com like an image or JS or CSS it will be faster because the browser is already ready for it. To give you an idea here are top 3 most common preconnect scenarios:
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin><link rel="preconnect" href="https://www.google-analytics.com/" crossorigin><link rel="dns-prefetch" href="https://yourid.cloudfront.net">
Use a CDN
Today with cloud providers like AWS, Azure and CloudFlare using a CDN couldn't be easier and it has a big performance impact! A CDN or a Content Distribution Network simply takes time files you upload (CSS/JS/images) and stores them across multiple different servers in various parts of the world. So let's say you have a visitor from India and your server is in the Us. If you are using a CDN for your assets then that CDN will serve those assets from a server in India rather than the US one. This will reduce latency and load times but also enable parallel resource downloading since the files are downloaded from a different domain. Another great thing about CDNs is that they are already optimized for performance. Everything we had to do to tweak our server earlier is already done for us 🤟🏻 If you are worried about pricing - don't be. Using a CDN nowadays is super affordable especially for the impact it has on performance.
Go back to basics
I've always been a fan of minimalism except when it comes to Apple devices 🥺 Guilty as charged. But when it comes to front-end development I love minimalism to a fault. What I mean by minimalism is simple: reduce the number of resources you are using in your pages. This time under resources I don't just mean images and JS but rather fonts, various CSS frameworks, JS frameworks and dependencies. When we are talking about fonts my rule is 1 custom font with a maximum of 2-3 weights. If I really really have to, I will include a second font but then I will try to reduce the weights as much as possible. And yes I understand you should make your website look pretty but not at the cost of extreme performance.
Another really trivial and stupid problem i repeatdy have seen happen is that developers include multiple versions of JQuery or Bootstrap or some other plugin. I’ve noticed this goes to extremes with Wordpress themes and plugins. It’s like a frenzy of repeat includes. Every plugin simply piles on it’s own Bootstrap version, Jquery version or something. Make sure you nip that because you really don’t wanna be loading multiple useless libraries.
Finally, think about what you actually need. Do you need a 150KB animation library for CSS and animating that one section on the home page? Can that be done using native CSS or JS. Do you really need JQuery, an Ajax Form plugin and a Form validation plugin to make an HTTP request? Do you need a 200KB parallax plugin that requires another dependency or can you make a similar effect with CSS. Do you really need another library to tell time with JS?
Consider the fact that an average modern F1 car has 5000 parts and weights around 750 KG whereas a regular car has around 30 000 parts and weights 1300 KG. Just let that sink in. Do you want your website to be like an F1 car or like your neighbors Toyota Camry?
Optimize your server
Your infrastructure has a significant role in load times and performance. If you have a lousy server nothing you do will help you. Especially if the server is located in a different part of the world and most of your users are accessing it from across the pond. There are easy wins that you can do to make sure you get the best performance with as little as possible.
The first thing is to make sure that you are running on HTTP2. It's not that complicated to install it in case your hosting provider isn't running on that by default. HTTP2 is much faster than HTTP1. It's also much newer so it has a lot more features that deal with a lot of performance issues that HTTP1 had. One of the biggest things that HTTP2 can do is download resources in parallel. Coupled with other features HTTP2 makes a huge difference and you should find a way to get your website on it.
Next up if you are developing on top of the LAMP stack and you are using PHP then go check if you are running PHP 7+ at a minimum. PHP has been kicking ass in terms of performance in recent versions like PHP 7 and PHP 8. Just by upgrading from PHP 5 to 7 you will get 60% better performance and render times. PHP 8 also contains a lot of JIT improvements which again makes the jump from 7 to 8 worth it.
Another thing you can easily do is adjust the server configuration to make it even faster. This includes making sure you are compressing resources like CSS/JS, sending the correct mime types, taking advantage of browser cache and others. To save you some time I'll share my custom Apache configuration I've been using for years.
The first step would be to create a new Apache config with our performance settings. Open your terminal, SSH to your server and navigate to
/etc/apache2/conf-available/ and type in:
sudo curl https://gist.githubusercontent.com/cindreta/e536faa5494d0a0be409d435757ff9a7/raw/0a24629059e243a44d2caf5d1e95ce1c8df4822f/performance.conf - o performance.conf
This will download the custom performance configuration from a gist on my Github and save it as a file called
performance.conf which we will include in our default Apache config.
Now that we have the file navigate to
/etc/apache2/sites-available/ where you should find all your Apache Vhosts. The default one should be called
000-default.conf. Simply do sudo nano 000-default.conf and before the end tag
</VirutalHost> simply add our custom config like so:
Save the changes and reload the Apache server by issuing a command:
sudo systemctl restart apache2.If apache starts normally then everything is ok, if we messed something up or you are missing some Apache modules like mod_deflate, mod_rewrite apache will throw an error and you can either try to debug what’s up or remove the config file from your vhost.
An additional note I would like to mention: you could have used .htaccess to enable the configuration but I would suggest you don't. The reason is, you guessed it, performance. Adding complicated and long config options to
.htaccess actually slows down the Apache server because it has to do more work to compile that. I don’t like messing around with servers also but it’s worth doing it via config files like shown.
HTML is the most forgiving language on planet Earth. If you make a mistake like forgetting to close a tag or mistype the tag name it will still do it’s best to render and show the content. A lot of this has to do with browser engines but the fact is you can get away with pretty much anything. And people tend to abuse that. There are around a 100 tags in HTML spanning from more common like
<h1> to weird ones like
<kbd> and others. Yet people mostly use 10 of them and probably the one that is used the most is the
<div> element. I've seen this trend phenomenon 10x with these "new kids on the block" learning HTML via React or Angular...In short learn HTML and use appropriate tags. If you are building a list then use
<ol>. If you are displaying titles then use
<h3>... And guess what - the numbers have a meaning 😊.
<h1> would imply it's the most important title in the page hence use it accordingly. Same goes for other elements on the page like
Writing good, semantic, meaningful HTML helps the browser render faster but also it saves time on paint events, style recalculations and similar. Another benefit of writing good structured HTML is the on site SEO aspect of it. Google and other engines love when you make their job easier and use tags that have meaning. It also helps anyone else reading your source to better understand what you tried to do, what is what and similar. So just use HTML as sir Tim wanted you to.
Another small but interesting tip is to minimize the amount of white space and empty lines also helps with performance. You can even do this automatically by using server side plugins mod_pagespeed for Apache and Ngix. Of course if you are using a back-end programming language which compiles your HTML into views, like Laravel, then there are packages for that like HTMLMin and others.
I've seen many, many instances where CSS was able to replace a shape or even a background image. So by writing maybe 10 lines of CSS you save 50-100KB in transfer data on those images. The main reason why most websites are slow is because they use too many images or pile on too many JS plugins to do basic things like hovering, animations and effects. CSS is good at all of those things - you just need to learn how to use it.
Another important practice you can apply is writing better and more optimized CSS. Yes - that is a thing. You can also do your website an injustice if you write sloppy and bad CSS. So let's just name a few things you can do to write better CSS:
- the less lines of CSS you can write - the better
- the shorter your selectors are - the better
- run all the animations on the GPU vs the CPU
- stop supporting ancient browsers
- use shorthand properties when you can
- don't overwrite - learn browser defaults and framework resets
- separate media queries into its own files
- don't bloat your code with third party addons/plugins that you don't understand
The sooner you start practicing these things the faster you will see results. The best thing about this is you can directly edit CSS rules in a browser and test in literary seconds. So get to it.
Hope some of these help you reduce your load times and improve your performance in one days work. Some will take longer but they will also make you a better developer in the long run. At the end of the day performance is a give and take between design, style and functionality. You should be walking in the middle of that line for the best of both worlds.