Jon Fletcher 2020-07-16

How do I minimize main thread work?


The TL: DR

  • Remove third-party JavaScript 
  • Utilize web workers to do tasks off the main thread
  • Cut the complexity of your styles and layouts
  • Stick to the PRPL pattern
  • Minify and defer CSS

Every browser has a renderer process that effectively transforms code into a page that can be used and interacted with. It's in the main thread where most of this is processed. The main thread parses HTML and CSS to apply specified styles for the content. It also parses, evaluates, and executes the JavaScript.

Think of the main thread as your local bartender. They are able to handle most of the day-to-day tasks in the bar — the barrel changes, the debit card receipts — but if they are busy when a customer tries to order a drink, that customer is going to exit the page— The mean bars. This is important because the main thread also processes user events. 

So, if the main thread is occupied when a user interaction comes in, your web page will not respond to this interaction. 

With Time to Interactive a major component in Lighthouse Scoring, publishers need to minimize main thread work wherever possible. Improve your user experience, speed up your page, reduce your bounce, and help increase your Lighthouse score 

Here are 5 ways you can minimize main thread work: 

1. Do you really need that third-party Java script?

Often the main culprit behind heavy main thread work is third-party JavaScript. The more JS there is on your page, the more time the browser will need to parse, compile, and execute it. You can evaluate this using the Network panel to measure how long your page load takes. For the ultimate in real-world conditions, turn on network throttling and CPU throttling so you can get a real mobile experience. 

Block the URLs or domains responsible for third-party scripts you believe are an issue. Reload the page and re-measure how long it takes to load without the blocked third-party scripts. One effective approach is to lazy-load third-party content after the main page content loads. As a heavy part of the process, lazy loading ads can help cut down main thread work. 

2. Let web workers do the heavy lifting 

As the features and functionality of web apps increase in complexity, the main thread has more to do, making the possibility of bottlenecks more likely. In addition, because of the different capabilities of every device, it makes it almost impossible to predict how long it will take to run the code on the main thread. 
A workaround for this problem is to execute code off the main thread (OMT) using Web workers that operate alongside the main thread. Web workers support parallel work by allowing you to give a thread a function, which runs in parallel with the rest of your program. 

3. Reduce the complexity of your style and layout 

Adding or taking elements away, changing classes, animations all force the browser to recalculate element styles, layout, and flow, forcing the browser to check to see if any of the changes require layout to be calculated, and for that render tree to be updated. This forces the main thread to spend time on this 'style calculation'. 

Roughly 50% of this time is used to calculate the computed style for an element Reducing the variations between styles and elements across pages, reduces the scope and complexity of style calculations. For the lightest main thread work, avoid large, complex layouts and layout thrashing. 

4. Utilize the PRPL Pattern 

PRPL is an acronym that describes a pattern used to make web pages load and become interactive, faster. 
It stands for: 
  • Push critical resources for the initial URL route. 
  • Render the initial route. 
  • Pre-cache remaining routes. 
  • Lazy-load and create remaining routes on demand. 

Preload is a declarative fetch request that tells the browser to request a resource as soon as possible. Lighthouse recommends inlining critical JavaScript and deferring the rest using async, as well as inlining critical CSS used above-the-fold. This improves performance by eliminating round-trips to the server to fetch render-blocking assets. service workers can fetch assets directly from the cache rather than the server on repeat visits. 

This not only allows users to use your application when they are offline, but also results in faster page load times on repeat visits. specifying some kind of indicator to let the code know when a resource is in the viewport. 

You can declare a "lazy" image url, and the actual image url, simply by giving your image tag a class of "lazy"; for background images for divs, use classes ".lazy-background" and ".lazy-background.visible". As expected, these lazy loading libraries exist to help accelerate the implementation of lazy loading 

5. Minify and defer CSS

CSS files have to be downloaded and parsed before a browser can display a page. If these CSS files are large, it's going to clog up the main thread for a long time, slowing down your page load and the time it takes to respond to user interactions. 

Minify CSS

CSS files can be bloated unnecessary characters, comments, whitespaces, or tabs. If you remove these unnecessary characters safely, it will reduce the final size without affecting how the browser actually renders the styles. The process is called minification and will help to reduce main thread work. But, writing CSS code without these characters is unnatural and difficult. One way is to write your code as normal and add a minification step using Webpack.

Defer non-critical CSS

It's important to know that CSS files are render-blocking resources: they have to load before the browser can get to interactions on the main thread. This means large styles will give your main thread more work to handle. Luckily, not every line of CSS is necessary to make crucial content. 

The Coverage Tool in DevTools will show you which CSS classes are critical to the page load. Extract the critical CSS from the coverage tool, and load them in a block at the head of the page. You can then load the non-critical classes asynchronously, reducing the work of the main thread.

This makes your page interactive, and the perceived load time much faster. Not only will this help to improve your Lighthouse score, but it will also cut your bounce rate and increase dwell time as users don't have to wait to start using the page. 

If you want to improve another key stage of the page load process, check out the guide to speeding up First CPU Idle here

Latest Articles

‹ Back to Blog Home

Get the headlines

Sign up to get the best headlines direct to your inbox

Your name
Your email