Published on: February 14, 2023
6 min read
Learn how to identify and fix some root causes for high Total Blocking Time.
Our world overwhelms us with information that is more accessible than ever. The increasing rates of content production and consumption are gifts that keep on giving. We can't seem to keep up with the information thrown at us. We're limited by our cognitive limitations and time constraints, and a recent study concluded the result is a shortening of attention spans. Websites are no exception.
Users who interact with your website want feedback, and want it fast. Preferably immediately! Website performance has become an important factor in keeping users engaged. But how do you measure how unresponsive a page is before it becomes fully interactive?
Many performance metrics exist, but this blog post focuses on Total Blocking Time (TBT).
TBT measures the total amount of time tasks were blocking your browser's main thread. This metric represents the total amount of time that a user could not interact with your website. It's measured between First Contentful Paint (FCP) and Time to Interactive (TTI), and represents the combined blocking time for all long tasks.
A long task is a process that runs on the main thread for longer than 50 milliseconds (ms). After a task starts, a browser can't interrupt it, and a single long-running task can block the main thread. The result: a website that is unresponsive to user input until the task completes.
After the first 50 ms, all time spent on a task is counted as blocking time. This diagram shows five tasks, two of which block the main thread for 140 ms:
Many tools measure TBT, but here we’ll use Chrome DevTools to analyze runtime performance.
As an example: We recently improved performance on GitLab's View Source page. This screenshot, taken before the performance improvement, shows eight long-running tasks containing a TBT of 2388.16 ms. That's more than two seconds:
As you might have guessed by now, reducing the time needed to complete long-running tasks reduces TBT.
By selecting one of the tasks from the previous screenshot, we can get a breakdown of how the browser executed it. This Bottom-Up view shows that much time is spent on rendering content in the Document Object Model (DOM):
This page has a lot of content that is below the fold – not immediately visible. The browser is spending a lot of resources upfront to render content that is not even visible to the user yet!
So what can we do? Some ideas:
content-visibility: auto;
CSS property ensures the rendering of off-screen elements (and thus irrelevant to the user) is skipped without affecting the page layout. (example)requestIdleCallback
method can be used to render content after the browser goes into an idle state.
(example)Frameworks such as VueJS and React are already heavily optimized. However, be mindful of how you use these frameworks to avoid expensive tasks.
This screenshot shows the Bottom-Up view of a task. Much of the task time is spent on activities from third-party code in the VueJS framework:
What improvements can we make?
v-memo
enables you to cache parts of your template. The cached template updates and re-renders only if one of its provided dependencies changes.v-once
ensures the element and component are only rendered once. Any future updates will be skipped.requestIdleCallback
you can defer the execution of the non-critical tasks. (example)By using three of the methods suggested above, we reduced TBT from about 3 seconds to approximately 500 ms:
What did we do?
content-visibility: auto;
CSS property.Remember, the size of the decrease always depends on how optimized your app already is to begin with.
There is a lot more we can do to improve TBT. While the specific approach depends on the app you're optimizing, the general methods discussed here are very effective at finding improvement opportunities in any app. Like most things in life, a series of the smallest changes often yield the biggest impact. So let's iterate together, and adapt to this ever-changing world.
“Adaptability is the simple secret of survival.” – Jessica Hagedorn