A few weeks ago I was asked if Accesto could help to optimize a popular online store selling natural cosmetics. Of course we can! I thought. That is what we do for a living, we improve existing web applications like SaaS, marketplaces, or eCommerce sites. Thus I thought it would be an optimization like every other. But it wasn’t.
Quick wins for website speed
Although every online product is unique, they usually struggle with similar web performance pitfalls. Non-optimal database queries, poor caching, too large images/resources, or unused imports, to name a few. Usually, there are a few things that can be fixed relatively quickly and will result in quite a speed boost. Our CTO recently gathered such tweaks for you in his blogpost on top 5 hacks to fix slow web applications.
Top performance, which will hold the exponential growth of users, cannot be achieved overnight. But if your website is slowing down, and you haven't yet put a lot of effort into its optimization, there is a high chance that it can be refined in a quite reasonable time. Like in one of our recent stories where we managed to decrease website loading time by 97% in just 4 hours of work.
The case of natural cosmetics eCommerce seemed similar. The store owner sent me an email on Friday morning with the Google PageSpeed Insights report. It evaluated the overall site performance on 61/100 for desktop, and 42/100 for mobile. Not a tragedy, but indeed a lot of room for improvement. Great! We will apply a few quick tweaks that will speed up the website and I will have good news for a customer even before the weekend!
Let’s start with a website audit & checking Core Web Vitals
We already knew the overall score for this website - our starting point for optimization. This score is a composition of 6 metrics evaluated by PageSpeed, which for that particular site presented like this:
Quick look at the metrics and we see that 4 out of 6 metrics look fine (Web Vitals), but the remaining two: Speed Index and Largest Contentful Paint (LCP) seem way too high. Understanding these metrics helps to decide where we shall start our optimization, how much we should improve, and whether we can find some low-hanging fruits. Each of these metrics has a different weight (importance). To see how exactly they influence the overall score you can use the scoring calculator.
Although PageSpeed evaluated both SI and LCP as poor ones, LCP has a higher weight (25%), so improving it will have the highest impact on the overall score. LCP is one of 3 important metrics introduced by Google, called Core Web Vitals. Ok, but what exactly is this LCP? In short - it is the time at which the largest visible part of website content is painted. This content could be an image, a large block of text, or any other element that occupies a significant part of the screen when the website loads. And the faster this element is displayed to the user, the better.
Knowing that, we could assume that perhaps some product image or banner is too large, not scaled properly, or maybe not compressed. Or maybe images are served by PHP and not cached? Few basic checks should show us what is going on.
We used a Lighthouse tool built-in Chrome web browser to profile the website. We were looking for any performance pitfalls, but the audit results were… surprisingly good! The site wasn’t performing that bad at all! Server response time was quite decent, images were served in a modern format and with proper sizing. All the site assets were properly optimized and served with proper cache policy. They even used some of the Progressive Web App capabilities to make the site work smoothly.
Ok, so maybe it was a traffic related issue? Maybe site speed is good as long as the number of users using it is low? Worth a try. It is quite a common situation, many websites are tested only on a small number of users. When the user base grows website starts to clog. More on that topic you can read in my post on why new users can kill you web application. I did a few checks with the website load testing tool k6.io, but nothing, still a decent response time.
We also dug into the code to do some checks, but it only confirmed what was already obvious to us. Someone already did a great job to optimize this website. We weren't asked just to do the basics, they know how to do that themselves. We were asked because none of the popular tweaks worked. Great, finally some challenge!
Profiling the website performance
It was a time to dive deeper and do a step by step analysis. First of all, we had to figure out which site element was taken to calculate the LCP. Performance tool built-in Google Chrome shows a precise timeline of all the elements requested, loaded, and painted. It also indicates moments when LCP and other metrics are measured.
Analysis of this timeline confirmed our assumptions - the Largest Contentful Paint element was one of the product images on the homepage. Why is this image displayed so late to the user? We checked the image format and size, and all looked good. Actually, the image itself was loaded in just 122 milliseconds. So why did this image appear after almost 6 seconds if it loads in just a fraction of that?
We analyzed the timing of that particular image, and what surprised us was that it started to load after 5.7s since the website was requested. But why? Server response time was decent and all images should begin to load as soon as the browser receives the HTML from the server, right? Well…
Lazy loading done wrong
The title of this article already revealed the diagnosis - yes, it was a lazy loader that delayed fetching that image. But why? Isn’t the lazy loader one of the most common mechanisms that improve the website speed?
Lazy loader prevents images from being fetched if they are not in the current viewport. This minimizes the amount of data transferred in situations when only part of the site is seen by the user (eg. user views only the top of the page). Usually, it is good and makes the website load visibly faster. Usually...
Results of website optimization
There are many ways to solve this problem. We could get rid of the dependency on the external library or execute the lazy loader earlier than in onload. But the quick fix was to simply switch off the lazy loader for images that are always seen above the fold (the portion of the webpage that is visible without scrolling). This simple solution took just one line of code and did a job. Just see how the website speed improved:
It took us a few hours to find the cause of the poor LCP and finally add this single line of code. Website optimization is usually not about coding, it is analytical work of searching, digging, and investigating. Of course, this wasn’t the end of the optimization, still room for improvement. But we were surprised how much Core Web Vitals score improved with a simple fix in a lazy loader. This made me curious so I also checked other popular eCommerce websites and I was surprised. Many of them did have the same issue! Seems that lazy loader is seen as a great, out of the box solution for optimization, but very often added carelessly. And adding it too quickly (too lazy?) may actually harm the overall site speed. So be careful and don’t add stuff to your site just because everyone does it!