Lighthouse

How to quickly improve website performance

Nowadays, websites should be fast, otherwise visitors will leave your website before they have seen the most important content of your website. It’s obvious, but it can be quite a challenge with all the interesting (frontend) assets that make your website so great once it’s fully loaded.  In this post, I’ll describe some quick wins to improve the performance of your website.

I often use Google’s Lighthouse tool to identify points that should be improved. Lighthouse provides suggestions to improve the speed of your website, but also gives suggestions for a better user experience (usability) and SEO.

Running a Lighthouse audit is easy. Just open the developer tools in Chrome, select the ‘Audits’ tab and run the audit. Some issues pointed out by Lighthouse might be a lot of work to fix. For example, it may turn out that images don’t have alt tags. It’s clear that this should be fixed (and how you can fix it), but it’s a lot of work to go over all images in the website and add the alt tag one by one.

Additionally, there are some suggestions that I choose to ignore. Lighthouse suggests to serve images in a next-generation image format, but the browser support for this feature is rather poor at the moment of writing.

However, there is a range of quick wins that greatly improve the speed and user experience, and which are easy and quick to implement: caching of static assets, text compression, adding a manifest file, add a SSL certificate and compressing the javascript and css.

Technology

We often build websites using Laravel and we use Laravel Forge for the configuration of our (web)server. Although Forge takes care of many things for you, there are some quick wins you can easily configure yourself.

Because a nginx web server is installed by default by Forge, this post will present some nginx configurations to improve the performance of your website.

If you use a different web server, the steps below are still important, but the configuration specifics differ.

Caching

Caching of static assets like javascript, css and image increases the performance of your website because your browser has to download those assets only once. Caching is done by setting global caching headers for your website.

To set the caching headers, you first have to locate the nginx configuration file. If you are using Laravel Forge, login and navigate to the website you’re optimizing. At the bottom, you’ll find a button ‘files’. Click and choose ‘Edit Nginx configuration’. Without Forge, you have to locate the config file yourself. It can be at a different location, as described here.

Add the following lines of code to the server block:

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
    expires 10d;
    add_header Cache-Control "public";
}

I use an expiration time of 10 days in this example for all file types. If you want to use different expiration times for different types of files, just add multiple location blocks with different times.

Adding this code to the nginx configuration file will likely increase the Lighthouse score for performance.

Text compression

Enabling text compression is another quick win for a much better performance. GZIP compression is easily enabled via the nginx configuration file.

#GZIP
# Enable gzip compression.
gzip on;

# Compression level (1-9).
# 5 is a perfect compromise between size and CPU usage, offering about
# 75% reduction for most ASCII files (almost identical to level 9).
gzip_comp_level 5;

# Don't compress anything that's already small and unlikely to shrink much
# if at all
gzip_min_length 256;

# Compress data even for clients that are connecting to us via proxies,
# identified by the "Via" header (required for CloudFront).
gzip_proxied any;

# Tell proxies to cache both the gzipped and regular version of a resource
# whenever the client's Accept-Encoding capabilities header varies;
gzip_vary on;

# Compress all output labeled with one of the following MIME-types.
gzip_types
application/atom+xml
application/javascript
application/json
application/ld+json
application/manifest+json
application/rss+xml
application/vnd.geo+json
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/bmp
image/svg+xml
image/x-icon
text/cache-manifest
text/css
text/plain
text/vcard
text/vnd.rim.location.xloc
text/vtt
text/x-component
text/x-cross-domain-policy;
# text/html is always compressed by gzip module

Adding this code to the nginx configuration file will likely increase the Lighthouse score for performance.

SSL certificate

Nowadays, it’s common to install a SSL certificate on a websites to keep the data of your users safe. Apart from security considerations, adding a SSL certificate is good for SEO, because Google started to mark websites without encryption as ‘not secure’.

Technically, adding a SSL certificate is easy. If you’re using Laravel Forge for deployment, navigate to your website, switch to the SSL tab and click ‘LetsEncrypt’. After activation, your website is secured by a free SSL certificate.

Without Laravel Forge, you have several options. For example, you can install Let’s Encrypt manually (follow the instructions on their website), obtain a free certificate from Cloudfare or purchase a certificate from another dedicated SSL certificate provider (and follow their installation guide).

If this is the first time you install a SSL certificate, make sure to redirect all traffic from http to https

Add a manifest file

Progressive Web Apps (PWA) are nowadays a popular topic, because it’s an opportunity to give users the experience of a native app. The first step in converting your website into a PWA, is adding a manifest file. The creation of this manifest file is easy: save a file named ‘manifest.json’ to the root of the public folder. Next, reference the manifest in theof your website:

The contents of manifest.json should be something like this:

{
"name": "PLint-sites Webdesign en webapplicaties",
"short_name": "PLint-sites",
"icons": [
{
    "src": "/images/icons/app-icon-48x48.png",
    "type": "image/png",
    "sizes": "48x48"
}, {
    "src": "/images/icons/app-icon-96x96.png",
    "type": "image/png",
    "sizes": "96x96"
}, {
    "src": "/images/icons/app-icon-144x144.png",
    "type": "image/png",
    "sizes": "144x144"
}, {
    "src": "/images/icons/app-icon-192x192.png",
    "type": "image/png",
    "sizes": "192x192"
}, {
    "src": "/images/icons/app-icon-256x256.png",
    "type": "image/png",
    "sizes": "256x256"
}, {
    "src": "/images/icons/app-icon-384x384.png",
    "type": "image/png",
    "sizes": "384x384"
}, {
    "src": "/images/icons/app-icon-512x512.png",
    "type": "image/png",
    "sizes": "512x512"
}
],
"start_url": "/",
"scope": ".",
"display": "standalone",
"orientation": "portrait-primary",
"background_color": "#fff",
"theme_color": "#1D197B",
"description": "Websites, Webshops en webapplicaties | PLint-sites Webdesign, Sittard.",
"dir": "ltr",
"lang": "nl-NL"
}

Of course, you have to make sure that the app icons you’re referencing actually exists. Also note that only adding a manifest doesn’t mean that your website is now a fully functioning progressive web app. You have to do more, like adding a service worker, show a webpage when the user is offline and give users the possibility to add your website to their home screen. However, those additions require more effort and are beyond the scope of this post. A detailed description on how to achieve this for the Vue framework can be found in this post.

Minimizing JS and CSS

Javascript and css are an essential part of every website, but the corresponding files can be quite large and may cause long loading times. The size of those files can be significantly reduced by minimizing the JS and CSS files.

In Laravel, Mix is used for the compilation of the frontend assets, so you only have to do a production run using npm run prod. It minimizes the assets and removes all console.log statements. However, you can simply do more by extracting third party libraries (that don’t change so frequently as your own code) in a separate bundle. This way this bundle is downloaded only once. A default Laravel install comes with jQuery, Bootstrap and Vue installed. To extract these libraries you need to do two things:

  • add the following code to the webpack.mix.js file (found in the root of the project).
    mix.js('resources/js/app.js', 'public/js')
    .extract(['jquery', ‘bootstrap’, ‘vue’])
  • 3 (!) files will be created in the public/js folder and the order of including them in your layout file is important:
    <script src="{{ mix('js/manifest.js') }}">
    <script src="{{ mix('js/vendor.js') }}">
    <script src="{{ mix('js/app.js') }}">

More info on the configuration of Mix can be found in the Laravel documentation.

If you don’t use Laravel, most modern Javascript frameworks are equipped with a build pipeline to minimize JS and CSS files.

Optimizing images

Ideally, all images on your website should be optimized and they shouldn’t be larger than strictly necessary. However, if this is not the case, updating all images can be a huge task. In this situation it’s likely best to focus on the images with very large file sizes. Nowadays, there are still websites that have a huge full-width (background)image on their homepage, causing a long loading time. Optimizing such images may lead to a significant performance win.

Additionally, with responsive images you can make sure that users get images served in a size that’s relevant for their screen size. The medialibrary package developed by Spatie has very good options to achieve this.

SEO and best practices

Lighthouse performs some checks related to SEO and best practices. Some of their suggestions are easy and quick to fix, in case you haven’t done so:

  • Add (meta)tags to the <head> of the html document, for the title, meta description, and language. Additionally, add a viewport meta tag and specify the initials scale.
  • Make sure that search engine are allowed to crawl your website (i.e. there shouldn’t be a robots meta tag set to ‘no-index’.
  • Add a robots.txt file.
  • Add a sitemap.

Suggestions are welcome!

I’m a web developer and I spent most of my the time writing code to build great web apps for my clients. Obviously, a web app should be hosted somewhere and the hosting environment should be optimized for good performance. During the last years, I learned a lot on the subject, but I’m not a ‘real’ system administrator nor a devops engineer (yet). Any suggestions for further improvements are welcome!


Mijn Twitter profiel Mijn Facebook profiel
Leonie Derendorp Webdeveloper and co-owner of PLint-sites in Sittard, The Netherlands. I love to create complex webapplications using Laravel! Latest post
Running queues for multiple applications on the same server with Laravel Horizon

Leave a Reply

Your email address will not be published. Required fields are marked *