How to convince your client to focus on Web Performance: a case study
Tags: webperf, javascript, css, devtools
Published: 2019-12-10 09:33:08

---
title: How to convince your client to focus on Web Performance: a case study
published: true
description: The goal of this PoC was to convince our client to focus on Web Performance without going through the whole internal development process that would take weeks and without having any guarantee of the gains.
tags: webperf, javascript, css, devtools
canonical_url: https://medium.com/@armelpingault/how-to-convince-your-client-to-focus-on-web-performance-a-case-study-35f12385689
cover_image: https://thepracticaldev.s3.amazonaws.com/i/da7w72ims3anqehcngrq.png
---

Web Performance is really one of my daily concerns for the clients I am working with at [Netcentric](https://www.netcentric.biz/).

Sometimes convincing them to focus on web performance is not an easy task: it’s never clear what will be the gain compared to the effort we are putting in it, and as you might already know, web performance is all about measurements.

By the time we decide to implement a feature for our clients, it can take weeks before we can see it live and finally measure the improvements, and there is always the risk that the rewards are not what we were expecting.

I wanted to show one of our clients that we should focus on optimizing what’s happening in the `<head>` section of their page, and again I couldn’t go with my "feeling" that it could be good for their performance. I wanted to show them some real numbers that would help me convince them that it was an important topic.

Luckily today, I was able to find a set of tools that would help me achieve my goal.

# Building a Proof of Concept (PoC)

The first thing to do when it comes to web performance is to get a picture of the current status, so we can easily see the comparison before and after our work.

The Chrome DevTools Performance tab offers a lot of very interesting information, but it can sometimes be really hard to understand, especially for not-too-technical people, with all the information it provides:

![Performance reports are not always easy to understand for non-tech people](https://thepracticaldev.s3.amazonaws.com/i/da7w72ims3anqehcngrq.png)
<figcaption>Performance reports are not always easy to understand for non-tech people</figcaption>

So, I decided to use some custom metrics using the [Performance API](https://developer.mozilla.org/en-US/docs/Web/API/Performance) to get a rough idea of what was time-consuming on the page I was auditing.

The first step was to go to the homepage of our client and use the Overrides feature of Chrome to be able to inject my own piece of Javascript.

First, I [opened Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/open), went to the "**Sources**" tab, followed by the "**Overrides**" panel:

![How to access the "Sources" → "Overrides" panel](https://thepracticaldev.s3.amazonaws.com/i/cwh85u309vpcnbm1qr4l.png)
<figcaption>How to access the "Sources" → "Overrides" panel</figcaption>

From here, I clicked on "**+ Select folder to overrides**" and selected an empty folder I just created (You can also create a new one directly from the dialogue box).

Once selected, Chrome prompts you to allow access to this folder, so don’t forget to click on the "**Allow**" button:

![Chrome prompting you to ask access to your overrides folder
](https://thepracticaldev.s3.amazonaws.com/i/euyzexlu3mxuvk3aadhq.png)
<figcaption>Chrome prompting you to ask access to your overrides folder</figcaption>

Then, from the "**Sources**" tab, I went to the "**Page**" panel and opened my main HTML file (in my case, en.html):

![The HTML source viewed from the "Sources" tab](https://thepracticaldev.s3.amazonaws.com/i/keob6lyo3oxt4n893cca.png)
<figcaption>The HTML source viewed from the "Sources" tab</figcaption>

On the right side, I was able to inject my Javascript for my custom metrics. I used two functions: [performance.mark()](https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark) and [performance.measure()](https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure).

The Performance API is very easy to use, for example:

```javascript
// Start your measure
performance.mark('begin');
// Put everything you want to measure between the marks
// Stop your measure
performance.mark('end');
// Calculate the time difference between your 2 marks
performance.measure('diff', 'begin', 'end');
// View the results in the Performance tab
// or output the results in the console using:
console.log(performance.getEntriesByType("measure"));
```

You should see something similar to this in your console:

![How the measure looks like in the Chrome console](https://thepracticaldev.s3.amazonaws.com/i/etzbxwdoeemaqj0w7kdy.png)
<figcaption>How the measure looks like in the Chrome console</figcaption>

Finally, the code had the following structure for my page:

![Structure of my page after adding the performance marks](https://thepracticaldev.s3.amazonaws.com/i/6qmj9359ce05hv2iufrm.png)
<figcaption>Structure of my page after adding the performance marks</figcaption>

Once done with injecting my performance marks inside my HTML, I switched to the "**Performance**" tab, made sure I selected a "**Fast 3G**" network and "**4x slowdown**" for the CPU, and finally clicked on "**Start profiling and reload the page**":

![Configuration before running the Performance report](https://thepracticaldev.s3.amazonaws.com/i/j81m334cabfchpphg94j.png)
<figcaption>Configuration before running the Performance report</figcaption>

After a couple of seconds, I was able to see my report with some interesting information. The section I wanted to check was the "**Timings**" panel where I could find my custom metrics along with some default user metrics provided by Chrome, e.g. [First Contentful Paint](https://developers.google.com/web/tools/lighthouse/audits/first-contentful-paint) (FCP), [First Meaningful Paint](https://developers.google.com/web/tools/lighthouse/audits/first-meaningful-paint) (FMP), [Largest Contentful Paint](https://web.dev/lcp/) (LCP), ...

![The "Timings" panel shows my custom metrics along with Chrome default ones](https://thepracticaldev.s3.amazonaws.com/i/fwu0to2kyy0wsayry6yj.png)
<figcaption>The "Timings" panel shows my custom metrics along with Chrome default ones</figcaption>

What I saw there was that parsing the `<head>` section was taking **4.40s** (CSS 1.85s + JS 2.55s) for **~50 lines** when parsing the `<body>` section was only taking **0.97s** for **~1300 lines**.

With that, I had a baseline for measuring my improvements. Time to optimise!

The first optimization I tested was adding a `defer` attribute to my Javascript files:

![Adding a "defer" attribute to my scripts](https://thepracticaldev.s3.amazonaws.com/i/cmef29we0z7qnm6newwk.png)
<figcaption>Adding a "defer" attribute to my scripts</figcaption>

So back to my "**Sources**" tab, I opened the HTML file and added the `defer` attribute, and ran a new "**Performance**" test:

!["Timings" panel after adding the defer attribute](https://thepracticaldev.s3.amazonaws.com/i/qm9vjkv8xdoydd0ckaav.png)
<figcaption>"Timings" panel after adding the defer attribute</figcaption>

Checking the "**Timings**" panel again, I could now barely see the JS parsing time, which was down to **8.66ms**. The total `<head>` section was also down to **1.65s**, where most of the time was now only spent on the CSS.

I now wanted to see if I could also reduce the time spent on the CSS. So I went to check the "**Coverage**" tab (cmd+shift+p), opened it and clicked on "**Start instrumenting coverage and reload the page**":

![The "Coverage" tab before starting profiling](https://thepracticaldev.s3.amazonaws.com/i/n1aibewboh76af0ea9gf.png)
<figcaption>The "Coverage" tab before starting profiling</figcaption>

Since I only wanted to see the CSS coverage, I used the filter `.css` and what I could see was that **92% of the CSS I was loading was not used**. (Unused bytes will change in real-time when you start interacting with the page):

![Unused bytes was over 92%](https://thepracticaldev.s3.amazonaws.com/i/naagek2u4xfgno2hyd41.png)
<figcaption>Unused bytes was over 92%</figcaption>

That was a lot of data loaded for nothing, and I wondered if I would have some gain removing unused CSS. To achieve this, I had a couple of solutions and tools like [Purgecss](https://www.purgecss.com/), [uncss](https://github.com/uncss/uncss) or [PurifyCSS](https://purifycss.online/) for example, that could help me remove all the unused CSS on the homepage. I decided to use the last one as it was providing an easy user interface which was enough for my PoC.

For this tool, just put the URL of your website and click on "**Clean up CSS**". (I didn't check exactly how accurate this tool was as I just wanted to have a rough idea in my case).

Once it's done, I clicked on the "**show clean css code**" button and copied the new CSS.

Back to my DevTools and the "**Sources**" tab, "**Page**" panel, I selected my CSS file, pasted the cleaned CSS code I got in the previous step and saved my changes (ctrl+s).

And finally, I ran another "**Performance**" test:

!["Performance" report after applying all my optimizations](https://thepracticaldev.s3.amazonaws.com/i/tpqn4w6m9ny2jrrjnz9q.png)
<figcaption>"Performance" report after applying all my optimizations</figcaption>

In the end, after only those two optimizations, parsing the `<head>` section was only taking 0.63s, and most of this time was spent on the CSS (0.61ms). Knowing that our baseline metric was 4.40s, that was a **total improvement of around ~85%**!

# Conclusion

The goal of this PoC was to convince our client to focus on Web Performance without going through the whole internal development process that would take weeks and without having any guarantee of the gains.

The PoC took me 2 hours to prepare, however, the real development will take a few weeks. Having all of our baseline measurements already done also lets us measure again once we are ready to go live and see the final real gain.