Blocking JS & CSS

How SpeedCurve detects blocking JavaScript and stylesheets

SpeedCurve reports the number of critical blocking resources in the page. These are the resources that block rendering. Since it's important that users see your content as quickly as possible, it's important to know what might be causing your page to render slowly.

The main culprits that block rendering are scripts and stylesheets that are loaded synchronously. A great way to avoid this blocking problem is to load your scripts and stylesheets asynchronously. You can do that for scripts by using the async and defer attributes, plus other programmatic techniques. Loading stylesheets asynchronously is less popular but is still possible using techniques like loadCSS.

There's a subtle difference in how scripts and stylesheets block rendering that is worth explaining so that you have a full understanding of the "blocking JS" metric. Synchronous stylesheets block the entire DOM from rendering. Synchronous scripts, however, only block the elements that follow the SCRIPT tag in the DOM tree.

This leads to an interesting question in how to measure blocking JS. Imagine a page that has a synchronous script at the bottom of the page - below all the visible DOM elements. This script, even though it's loaded synchronously, does not block rendering (because all the visible DOM elements precede the SCRIPT tag). 

In order to accurately measure blocking scripts, SpeedCurve does more than just track whether scripts are sync or async. We also determine if the script blocks rendering. We do this by determining if the synchronous script occurs before any of the DOM elements in the viewport. If a script is loaded synchronously and occurs before any DOM elements in the viewport, then we count it as "blocking JS". If it occurs after all the viewport's DOM elements, then it is not counted as blocking (even if it's loaded synchronously).

Pretty complicated. We know! Measuring blocking JS and CSS is difficult to do, but it's one of the most important metrics to track if you want to optimize your Start Render time. We're glad we have both of these metrics. We're also glad this code is behind us. Phew!