Running JavaScript tasks is often the source of the most common website performance issues. Avoiding so-called long tasks and blocking the main JavaScript (JS) thread is one of the most important strategies for improving performance. In this article, we’ll take a look at how long tasks can impact site performance, as well as at the steps you can take to address them.

Summary

What is a long JavaScript task?

Browsers perform page display operations in a single thread, so it is crucial that the task execution time in JS is no more than 50 ms. If this indicator is exceeded, the phenomenon is called a long task. When it occurs, the user notices an increased load on the browser. In this case, clicks on page elements are delayed, scrolling becomes jerky, or the page does not respond at all.

Also, in addition to the site code (execution of JS), the formation of long tasks can be influenced by network speed and processing power. For instance, if long-running tasks block the main browser thread due to low processing power, the browser will not be able to process user data quickly enough, leading to a delay in page response.

It’s worth mentioning that long tasks can occur when changing the style of an element via JS, for example, when a block height changes, forcing a recalculation of coordinates on the page: recalculate style => reflow, repaint.

Why are long JavaScript tasks bad for Core Web Vitals?

The FID metric (First Input Delay or waiting time before the first interaction with content) is the most affected by long tasks. The browser’s main thread is not uniformly busy throughout a page’s lifespan, so FID can vary greatly, depending on when exactly the user first interacts with the page. As a result, some users may not experience any latency at all, while others immediately face the overload symptoms we’ve already discussed. That’s why it’s important to understand how to search for long tasks and optimize code to improve your site’s FID.

FID directly depends on real users’ behavior and, as already mentioned above, it is unique for each of them. The key here is behavior monitoring, which can be done with a Core Web Vitals Monitoring tool to perform optimization based on real data.

How to find and measure long JavaScript tasks? 

The following services will help us with this:

Chrome DevTools

In the Performance panel, record the web page loading trace.

Look for red flags in the flow area. “Tasks” are shown in gray.

Hover your cursor over the bar to see how long the task took to run and whether it’s considered a “long” one.

To find out the source of a long task, select the gray taskbar. In the slide panel at the bottom select Bottom-Up and Group by Activity options. You’ll see which actions contributed the most to running the task.

​​

Webpagetest.org

Blocking the main thread for 50 ms is shown in the diagram using red blocks. This event also blocks user input. The green color means that the thread is not blocked.

Long Tasks API

We can measure long tasks in any application after subscribing to the PerformanceObserver interface with the following code:

var observer = new PerformanceObserver(function(list) {

    var perfEntries = list.getEntries();

    for (var i = 0; i < perfEntries.length; i++) {

        // Process long task notifications:

        // report back for analytics and monitoring

        // …

    }

});

// register observer for long task notifications

observer.observe({entryTypes: [“longtask”]});

// Long script execution after this will result in queueing

// and receiving “longtask” entries in the observer.

General recommendations for eliminating long JavaScript tasks

  • Run Web Workers code in a separate thread, allowing the main thread to focus on other important tasks, such as parsing HTML, preparing the render tree, rendering pixels, responding to user input, etc.
  • Break JavaScript code marked as long tasks into smaller tasks, using the “setTimeout/requestidlecallback/requestAnimationFrame” functions. It will make the main thread run as efficiently as possible and perform all operations without any delays.
  • Ease network load when loading a page (make as few network requests as possible, load them as late as possible, preferably after the FID event).
  • Delay unused JavaScript by using async or defer.

How we solved the long JavaScript tasks issue in Prism

Clickio Prism uses advanced technology to create a fast-loading, mobile-optimized version of a website. When developing Prism, it was important to ensure pages loaded quickly, without any negative impact on user experience, so we took the following actions to eliminate long JavaScript tasks:

  • Divided long tasks into smaller ones using the requestidlecallback/requestAnimationFrame function.
  • Got big data that doesn’t interact with the DOM (using Web Workers). 
  • Created a loading widget scripts queue.
  • Reduced the processes CPU load when loading the page (reducing the number of requests and transferring data while rendering the page).
  • Loaded some third party trackers with the partytown.js library.

By incorporating technical tweaks such as these, alongside other features such as a global CDN and smart lazy loading, Prism can make a significant difference to site performance and user experience. In fact, on average publishers using Prism see visitors spending 45% more time on their site and a 59% increase in their session RPM.

To find out more about Prism and set up a free trial, click here.