What’s in an audit? How do I start? Is there a single way to go about it, or are there many?
Table of Contents
- Steal my process
- The two types of audits
- The two scenarios
- Load time discovery: the steps
- Runtime discovery: the steps
Steal my process
More and more people in the web development industry are beginning to see the incredible convenience of having a fast-loading website. It’s good for the users, it’s good for conversions, it’s good for the numbers, it’s good for everybody. Reasonably, people are starting to approach this topic. What’s in an audit? How do I start? Is there a single way to go about it, or are there many?
That’s why I decided to outline the entire process I use when I audit a website for performance, so here it comes! Feel free to steal away ;)
The two types of audits
To me, the term performance audit feels kind of general. I prefer to differ between load time audit and runtime audit. Also, I usually either perform an high level audit or a really specific looking-for-something audit. Lastly, I like to call the former discoveries, the latter investigations or troubleshooting, so let’s clear things up a bit.
There are two types of approaches that one can take:
- High level discovery: you start with general metrics and tests to have a sense of the overall performance of the site. It is not a superficial work by any means, though. There are two very specific goals that need to be attained: to get a clear picture of the state of the website, and to cross out common issues. Typically, it answers the questions: is there a need for fix? Is this website respecting a baseline performance budget? Does it follow established best practices? Is gzip in place? Is it served over HTTP 2? Static assets are served via a CDN? And so on and so forth.
- Troubleshooting specific to a particular issue or aspect: this one, in most cases, represents a follow up of the previous one. It is tailored to the problem at hand and it is difficult to reduce to a checklist of stuff to look for. Typically, you end up diving deep into the browser timeline trying to figure out what is the root cause of the problems you identified in the previous step.
The two scenarios
Each approach can be applied to various scenarios, but I usually end up working with these two:
- Load time scenario: you analyze meaningful metrics that tell you whether or not your website loads fast enough. You identify the font loading technique in use, look for render blocking resources that are in the critical rendering path, you assess — if valuable — the time it takes for the site or app to be interactive.
- Runtime scenario: discoveries of this type can be very different from case to case. Typically, I focus on scrolling performance and heavy animations. You identify elements that get repainted often (e.g — on scroll, or on click), check whether animations are hardware accelerated, and so on.
Load time discovery: the steps
Let’s address the more practical side of it, giving you a bullet list of every step I take when going for loadtime discoveries. So far we’ve established two types of perf audits and said that one can focus on either load time or runtime. Now, let’s see an actionable list of steps that you can take on your website today.
The following are exactly the steps I take when auditing a website:
- Open webpagetest.org.
- Select Moto G, Mobile 3G with 200ms RTT.
- Check first and repeat visit and run the test.
- Write down the Time to First Byte.
- Eyeball First Paint and First Meaningful Paint from the strip view and compare those to the Time to First Byte. If there is a noticeable difference it usually means that the site is either loading render blocking resources or something else is preventing the browser from streaming the HTML.
- Try to identify the Time to Interactive by looking at the yellow blocks in the timeline view. This exercise is not accurate by an means, but it helps understanding what the load on the main thread is. (Usually, fat yellow blocks mean that the main thread is blocked for most of time, thus the site is usually unresponsive)
- Take a look at the network breakdown to look for anything standing out: I’m thinking big images, huge script bundles, several different web fonts, and so on.
- Go through the strip view again, this time comparing it to the network breakdown, in order to identify those blocking resources that are fetched before the FP happens (or before the FMP)
- Open the site and manually inspect the code, looking for best practices: minification, compression, HTTP2 where possible, CDNs, embedded critical CSS, and so on. This step can usually be sped up by PageSpeed Insights and the Performance audit of the Chrome DevTools
- Try to identify the font loading technique (typically, none). Fonts get a special treatment for, in my experience, they are the most common cause of difference between FP and FMP. Indeed, on slow networks, so many websites are killed by a FOIT (Flash Of Invisible Text) that is due to the way web fonts are loaded.
From this point on, I usually have enough data points and observations to guide further analysis. If nothing stands out, you can pat yourself in the back: your website is great. On the other hand, if something came up during the discovery process, you can dive deeper and attack every problem one by one. This is usually what I call investigations or troubleshooting, and usually leads to fixes and further insights.
Runtime discovery: the steps
In this last part, I’m giving you a bullet list of every step I take when going for runtime discoveries.
First, a quick reminder: in a runtime discovery you focus on those metrics that can tell you if your website runs smoothly enough. The aim is to answer the questions: Does it respond quickly upon interaction? Is scrolling acceptable? Etc..
However, runtime audits can be very different from case to case. Typically, I focus on scrolling lag and heavy animations smoothness. The right thing to do would be to record small interactions on the timeline and see the how long frames are. Then to try to identify the cause of long frames by digging in the callbacks and the render process. It is a pretty accurate, yet slow and painful process, so I like to start by looking for common issues. It is faster and typically ends up solving most performance problems.
Here is a brief list of what I usually watch out for:
- Check the usual suspects of repaints: sticky elements (position: fixed) that can cause paints on scroll, parallax effects, and so on. It is really important to understand that, when optimizing for shorter frames, paints are your harshest enemy. Cross out as many common causes of repaints as you can, it can save you so much time and effort.
- See if animations are taking advantage of hardware acceleration when possible. Most of the times it boils down to promoting elements to their own layer, so that the GPU can do its thing.
- Enable “Paint Flashing” on Chrome and see what gets repainted on scrolls or on other basic interactions (hover, clicks, and so on). Go through the main interactions (scrolling top to bottom and back, clicking on core elements, interacting with stuff..) and see if there is any green area lighting up.
From there, it is pretty much a matter of what the main activity of the site in question is. Improving runtime performance is an exercise of asking the right questions for the site at hand:
- What is core the users’ experience?
- Is it an animation? Or is it scrolling?
- Is the site responding well upon interactions (as per the RAIL recommendations)?
- Regardless of how the loading time of the first screen, are secondary routes fast to load? Can they be preloaded? Or cached?
- Can secondary features (or videos, or images, or any other content) be fetched at runtime?
I’ll be honest, there is no concrete secret recipe when it comes to crafting a great experience on the Web. If I had to find some guidelines I’ll say this: you need to empathize with the users and try as hard as possible to let their journey be flawless, while exploiting the idle time (e.g — while the user is reading, or thinking) to lazy load functionalities and content. Try not to lock the main thread for long at once, and may the force be with you.