Web Performance Calendar

The speed geek's favorite time of year
2024 Edition
ABOUT THE AUTHOR
Photo of Joan León

Joan Leon is a web performance consultant and co-founder of PerfReviews, helping businesses of all sizes optimize the speed and efficiency of their websites. He is also a Google Developer Expert in Web Performance and a Cloudinary Ambassador. Find him on LinkedIn and BlueSky.

I’m passionate about Web Performance—from identifying performance issues, monitoring (synthetic and RUM), metrics, implementing product culture, training development teams and other stakeholders, speaking at meetups and conferences, tools, and snippets.

When it comes to tools, my favorite is Chrome DevTools.

  • They are integrated into the browser (desktop, that is), making it quick and easy to get detailed information about the site we’re analyzing.
  • Organized into different categories: Elements Inspector, Console, Debugger, Network, Performance, Memory, Application, Lighthouse, etc.
  • Constantly evolving to help us identify areas for improvement—huge thanks to everyone on the Chrome DevTools team.

One tool I find particularly useful for performance analysis is Overrides, “hidden” in the Sources tab.

I say “hidden” because, in my experience, many people are unaware of this feature. I believe it’s a very powerful feature—not just for debugging Web Performance, as we’ll see today—so if you didn’t know about it, I invite you to explore its functionality and possibilities.

Send Me the URL

Whenever someone tells me their website has performance issues, I always say, “Send me the URL,” and immediately open DevTools.

With DevTools, we can quickly gather key data, such as server response times, resource count, file sizes, priorities, caching, formats, and more. Running Lighthouse provides a diagnosis with suggestions for resolving detected issues.

I believe the most effective way to demonstrate a tool is through real-world examples. Many of my conference talks include live audits of event websites, sharing insights on areas for improvement.

For this example, I discussed using Overrides with Stoyan, based on the Web Performance Calendar site, to test hypotheses for performance improvements.

I’m very interested in images and videos—formats, compression, sizes, best practices—so a quick validation could be using modern image formats to reduce image weight, improving download times.

Network tab filtering by images

In the screenshot, we can see DevTools in the Network tab, filtered by images from the article “How does the React Compiler perform on real code”.

In the Resource Type column, we can see the image formats are: JPEG, PNG, and GIF. We can also see that all images together weigh 3.9 MB.

The screenshot shows all the page’s images because I scrolled to the end, simulating reading the article. On the initial load, thanks to the use of loading=”lazy”, 6 out of 20 images aren’t downloaded.

As I mentioned earlier, I’m very interested in image formats, compression algorithms, sizes, etc. From experience, I know we could use other image formats to improve page loading. I’ll also take the opportunity to share the “Learn Images” course by the Chrome team, which will help you understand different image formats and adapt content to your needs.

Validating or Invalidating Hypotheses to Improve UX

Yes, I switched Web Performance to User Experience, since improving web or app performance has a direct impact on UX.

I hypothesize that we can improve page load times by reducing the 3.9 MB size. Let’s see how we can validate this.

Using Overrides

Before setting up the environment for changes, let me explain what happens.
When Overrides is enabled, any file we edit is stored locally in the folder we select (a subfolder is created per domain).

When we reload the page, if DevTools is open and Overrides is active, the browser checks for a local version of any required resources. If it finds one, it uses the local version instead of downloading it from the network.

Note that this invalidates any TTFB (Time to First Byte) references, since the resource is stored locally.

In the Sources tab of DevTools:

  1. Expand the sidebar to see and select the Overrides sub-tab.

Expand the sidebar to see and select the Overrides sub-tab

  1. Select “Select folder for overrides”, which opens a window to choose a folder where edited resources will be saved.

Select folder for overrides

  1. The first time, a message appears at the top asking for write permissions for the folder.

Request access

  1. The selected folder name (e.g., Overrides) appears in the sidebar, and the Enable Local Overrides option is active.
    On the right, we can see the HTML source code we want to modify.

Overrides folder

Now we’re ready to apply changes.

Image Formats

The goal is to convert JPEG and PNG formats to WebP or AVIF (Cloudinary’s AI automatically delivers the best quality/weight format) and GIF to WebP (which supports animation).

There are various tools to compress and change image formats. I often use Squoosh or Squish (by Addy Osmani) for format changes or compression, and Node.js scripts with Sharp for batch processing.

In this case, for simplicity, we’ll use Cloudinary as an image CDN and avoid changing local image references.

I have created a temporary account for this demo, but you can create a Free Tier account for your tests… or even to upload your blog images, but that would be another post. Let’s see how to change the format of the images.

Cloudinary for Optimizing Images

Cloudinary offers multiple ways to optimize images. We’ll use “Deliver remote media files”, which lets us serve images remotely.

Base URL for this test:

https://res.cloudinary.com/dzdb1jkxf/image/fetch/f_auto/

Where dzdb1jkxf is the temporary username and /image/fetch fetches remote images. The /f_auto/ transformation applies automatic format selection based on browser support.

Example

Nadia’s photo (author of the article) is JPEG and weighs 72 kB.

Nadia's photo JPEG format

Cloudinary serves it as WebP, weighing 36.7 kB.

Nadia's photo WebP format

Overrides + Cloudinary

Combining Overrides with Cloudinary:

  1. Return to Sources and select the HTML file.

Sources editor

  1. Update image references:
<!-- From -->
<img src="/images/2024/nadia/re-renders.png" ...>

<!-- To -->
<img src="https://res.cloudinary.com/dzdb1jkxf/image/fetch/f_auto/https://calendar.perfplanet.com/images/2024/nadia/re-renders.png" ...>

Find replace

  1. Save the changes (cmd/ctrl + S), which appear in the Overrides folder.
    Reload the page to use the modified HTML.

index.html in localhost

Verifying Changes

Reload the page to request images via Cloudinary and compare results.

Cloudinary images

Key observations:

  • PNG images are converted to WebP.
  • One PNG was served as JPEG because Cloudinary’s algorithm determined it was optimal.
  • For GIFs, I forced f_auto to f_webp to ensure conversion to WebP.
  • The first load has high TTFB as Cloudinary generates and caches images.

From 3.9 MB, we reduced it to 3.3 MB, improving image loading performance.

Conclusion

Knowing tools for detecting, reporting, and fixing performance issues is crucial. With Overrides, we validated a hypothesis quickly and easily.

Now it’s your turn to validate the value of Responsive Images.

<!-- Sample code -->
<picture>
  <img
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="
      https://res.cloudinary.com/dzdb1jkxf/image/fetch/c_scale,f_auto,w_600/https://calendar.perfplanet.com/images/2024/nadia/re-renders.png 600px,
      https://res.cloudinary.com/dzdb1jkxf/image/fetch/c_scale,f_auto,w_1200/https://calendar.perfplanet.com/images/2024/nadia/re-renders.png 1200px"
    src="https://res.cloudinary.com/dzdb1jkxf/image/fetch/f_auto/https://calendar.perfplanet.com/images/2024/nadia/re-renders.png"
    loading="lazy"
    decoding="async"
    height="300"
    width="200"
    alt="Awesome image"
  />
</picture>

Bonus

I have analysed this article because it is the 2024 post with the highest image weight.
To find out, I used this script, which generates the following output in the console.

=== Analysis Summary ===
Pages Processed: 29
Total Image References: 216
Unique Images: 186
Total Size of All Images: 17.39 MB

Heaviest Page:
URL: https://calendar.perfplanet.com/2024/how-does-the-react-compiler-perform-on-real-code/
Number of Images: 20
Total Size: 3.76 MB

Top 5 Largest Images:

https://calendar.perfplanet.com/images/2024/nadia/checkbox-re-renders-before-compiler.gif
Size: 1.44 MB
Dimensions: 624x350
Type: gif
Used in 1 page(s)

https://calendar.perfplanet.com/images/2024/nadia/compiler-in-motion.gif
Size: 717.36 KB
Dimensions: 724x724
Type: gif
Used in 1 page(s)

https://calendar.perfplanet.com/photos/noam.jpg
Size: 573.60 KB
Dimensions: 800x724
Type: jpg
Used in 1 page(s)

https://calendar.perfplanet.com/images/2024/nadia/components-preview-re-renders.gif
Size: 527.58 KB
Dimensions: 710x400
Type: gif
Used in 1 page(s)

https://calendar.perfplanet.com/images/2024/andrew2.png
Size: 451.48 KB
Dimensions: 1364x1018
Type: png
Used in 1 page(s)

Image Types Distribution:
  png: 75 images
  jpg: 103 images
  webp: 1 images
  svg: 1 images
  gif: 6 images

Analysis completed in 77.88s

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
And here's a tool to convert HTML entities