Site speed is important. It affects your users' experience directly, and a good user experience is extremely important to help drive sales and keep customers and visitors happy. Not only does it improve your site's UX, but a correctly configured website eats fewer resources and offloads work from the main server as well.
In this post, I'll discuss what I learned while getting an A grade on GTMetrix on codedamn - a platform for developers to learn programming in a new way. Let's start!
#1: Compress Images
Raw images are highly compressible, and you'd be surprised to find out how much bandwidth and data you could save just by compressing all your images.
For production sites, I recommend tools like TinyPNG CLI which can compress your images on server in a directory. Here's a quick peek of how TinyPNG saved over 2MB on a high res photo I uploaded on their site:
The great thing is TinyPNG allows 500 images free per month, so for a small to medium site, you can almost always stay inside the free quota!
#2: Code Splitting AND Bundle Splitting
Code Splitting means that you split your code up into various chunks and lazily loading them when needed. You always need this on your site
Bundle Splitting refers to splitting individual files generated by code splitting further down into smaller bundles. This improves caching on browsers as well as bytecode caching by browsers.
Although bundle splitting can be frowned upon as you increase HTTP requests, HTTP/2 has little to no impact on multiple requests until concurrency limits hit. And fortunately concurrency limits are in the range of hundreds of requests.
So if you're not making hundreds of HTTP requests (which you're probably not), you should be good with bundle splitting.
For code and bundle splitting, you need to integrate your project with a module bundler like parcel or webpack.
Once you configure them correctly, they work like magic. And they can really bring down the load both on your server and on the client's browsers.
They do this by caching resources and not downloading resources you don't currently need - like, why would you want to send the JS code for
/about route when I'm on
You should also minify your JS/CSS builds. For webpack, there are plugins like UglifyJS available. This helps reduce the size by trimming whitespaces, comments, shortening code, and so on – which will eventually reduce the size of the contents.
#3: Do not use shared hosting services
If you're a developer or someone who has a basic understanding of how to work with bash a little, there's simply no reason to go with shared hosting services.
In almost every case, either you can host your static assets for free on sites like GitHub pages, or you can go with more controlled options like cloud hosting. Almost all these cloud hosting players like AWS, Google Cloud, and DigitalOcean provide so many free credits that you can consume a lot of their services for free for a long time!
In some cases, shared hosting is cheaper than alternatives like $5 DigitalOcean hosting. But these servers have very limited resources allocated to your website, which degrades the overall site performance. Jailed shells, shared vCPUs, and limited RAM are some things to begin with.
Since we, as developers, always want to be in control, and going with a IaaS or a PaaS is always a solution.
Although you can go with any cloud provider of your choice, I would recommend DigitalOcean - the one I use for codedamn currently. It is dead simple to setup, and you can get $100 worth of free cloud credits with this link.
Choosing a cloud provider can really give you resources and infrastructure which will automatically bump your server performance (and your site performance) a bit.
#4: Set HTTP Expiry headers
Just like we discussed above, caching is extremely important to setup correctly. HTTP expiry headers inform the browser what to cache and for how long. Cached resources are not fetched from the remote servers, so it's important not to cache main entrypoint resources like
index.html - the first file you serve. You must also implement cache busting appropriately.
Again, for module bundlers like webpack, you can implement cache busting by having
[contenthash] in the name of the bundles it spits out. Also, this requires that browsers never cache your
index.html or any other HTML file you're using as an entrypoint to your site. How can we achieve that?
For static file serving and HTTP expiry headers, use NGiNX. NGiNX can manage all of that stuff for you. Here's a sample configuration recommended for setting HTTP expiry headers:
This configuration simply sets caching off for
text/html resources. For others, it sets it to the maximum possible time the browser can hold the cache.
Note that this configuration strongly relies on the fact that you have your cache busting mechanisms implemented in your module bundler (like the
[contenthash] we talked about above).
#5: Enable Brotli Compression
Brotli compression is a compression algorithm designed by Google, which is 20-25% more efficient than the well-known GZIP compression.
Brotli compression can be implemented on sites, again, using NGiNX. Let's take a look at an example of what happens when Brotli compression is enabled:
The first file size is 3.33 MB - without compression.
When it is compressed using Brotli - the size drops to 572KB.
When it is compressed using GZIP - the size only drops to 783KB.
Brotli saves over 200KB compared to GZIP, and over 2.5MB compared to no compression. And it is not even performing at its peak! That's over 82% compression! Very cool.
That's basically it! Without going much into the details of how to implement these specific techniques, we covered some of the most important things to consider when speeding up your site.
I did not go into the specific details as your mileage may vary with your server setups and configurations - but the general concept remains same.
Make sure you follow these best practices and let me know what you think by saying Hi on my twitter handle.