Improve Core Web Vitals

Webperf: improve core web vitals, be careful with chart libraries

Vincent Vallet
Voodoo Engineering
Published in
6 min readNov 2, 2021

--

In this article, we will see how to reduce the blocking time (and many other things) of your application through a real example using a chart library. Performance (and user experience in general) are critical today to keep your audience engaged and to create a feeling of satisfaction.

In addition, any performance issue can affect your business and your reputation.

A Google study using millions of page impressions found that when a site meets the recommended thresholds for the Core Web Vitals metrics, users are at least 24% less likely to abandon a page before it finishes loading.

Core Web Vitals

summary of core web vitals

Core Web Vitals are a set of metrics and guidelines to help developers to analyze performance and trace back to the issue's root cause. You should keep in mind that this is just a tool, and reaching all the thresholds (even 100% for every category) doesn’t mean you have the best user experience. They are just indicators that can help you to improve your product. As Tammy Everts said:

Performance is about people, not just metrics

If you want a full description of Web Core Vitals you can follow this documentation.

Chart library impacts on web performance

The main conclusion is that every time you want to display a chart you have to:

  • load a chart library, and thus prevent the rest of your app from loading
  • draw a chart, and thus block the browser for a certain amount of time

If you have multiple charts to display on the same page you will increase the global loading time of your app and increase user frustration.

The idea is to render the whole app before taking care of charts. Moreover, all libraries allow you to display charts “smoothly”, with simple animation. So it doesn’t disturb your users if you delay the chart display.

Measure core web vitals with lighthouse and chrome dev tools?

In this example, we use VueJS and ApexCharts.JS but the idea remains the same whatever the framework you use.

Let’s see what my lighthouse scores were, before any optimizations.

Lighthouse global scores

As you can see it’s not that bad for “Accessibility”, “Best Practices” and “SEO”, I didn’t lose all my frontend knowledge after years in backend and DevOps :)

The one indicator that is not satisfactory here is “Performance”, and upon closer inspection in the Performance section, we can clearly see that the main issue is the “Total Blocking Time”.

Lighthouse performance details

And Lighthouse provides some reasons as to what caused such a high blocking time. We can exclude the issue of cache policy as we are in a dev environment without a proper caching policy. So the conclusion is that we have too many DOM elements.

Lighthouse performance details

This follows a certain logic as every chart displayed on the page adds a lot of elements to the DOM. One chart can represent more than a hundred HTML tags.

And of course, the worst score is on mobile phones:

Performance score on mobile

Not surprisingly, the blocking time is still the main issue and it’s higher than on a desktop.

Now, how to find the root cause? Another detail provided by Lighthouse was the “unused javascript” which seems a little bit high. It means we are probably loading too many dependencies and are not using them all or perhaps not at 100% of their capacity. It gave me the idea to use Chrome’s “code coverage” tool.

It gives the same output as Lighthouse. We can see that we are using only 27% of our javascript, but we need more details. Here are the details if we run the same tool on a dev environment (without concatenation, minification, etc).

Here we are, as you can see the main issue is the ApexChart lib. We have loaded it but are not using all the features.

It’s a good reason to delay the loading and display of everything related to charts after the page is completely rendered.

How can I optimize my core vitals score when using a chart library?

The first step is to lazy load all the charts. I have a simple component that wraps the ApexChart library called MainChart. Here is the simple change to do when you call this component:

Before

After

In addition, you can add a variable, like displayto control when you want to draw the component with the v-ifproperty.

The second step is to lazy load the whole chart library in order to import it only when necessary.

Before: in your main.js file

After: in the file of your main chart component

That’s all to delay everything concerning charts. Of course, the first step should be reproduced for every chart in your app.

Web core vital scores after optimizations

Lighthouse scores after optimizations

Completely different to our previous results. With just a few simple changes, we saw “Performance” jump from 68 to 99, and this was made possible by reducing thetotal blocking time.

We reach 0 blocking time

So we reach 0ms of total blocking time with only a simple technique, lazy loading, and a quick modification in our code.

The main improvement was to minimize the amount of unused javascript, the coverage tool shows the optimization.

Code coverage after optimizations

And of course, the perception of better performance can be seen on mobile too.

Lighthouse score after optimizations on mobile

The website used in this example is QualityOfJSPackages, an attempt to measure the global quality of the Javascript packages ecosystem. You can find the repository here: https://github.com/wallet77/qualityofjspackages-website

Conclusion

As seen in this article, a mere detail can have a strong impact on your application’s performance and the solution can be as simple as a few lines of code. Chart libraries can have a huge impact on your website’s loading time because they run a lot of Javascript and they interact with the DOM to add a lot of elements.

To find and track performance issues we should use a variety of different tools like Lighthouse, Chrome dev tools, Core Web Vitals, etc. They are great solutions to facilitate our work and to make the web faster.

Finally, different auditing tools will generate slightly different reports with varying info across the indicators we mentioned, the same goes for reports generated online when compared to those done on your own desktop.

The goal here is to see the impact of all your optimization efforts, no need to reach 100% at all costs, that would be a waste of energy. The difference between scores of 99 and 100 is likely to be barely visible to the user, and the most important thing is to make navigating your app as smooth as possible.

Sources

https://web.dev/vitals

--

--