Render-Blocking Resources
Tags: webperf, css, javascript, tutorial
Published: 2020-02-22 14:32:22

### WHAT ARE RENDER-BLOCKING RESOURCES?

Render-blocking resources are resources that prevent the browser from rendering any processed content. And by default, CSS and HTML are render-blocking resources because the browser can not render content until the [CSSOM](https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model) and [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) are constructed.

These render-blocking resources block the first paint of a website or web application.

To prevent this, we can do the following:
- Identify render-blocking resources,
- Identify critical resources,
- Reduce/eliminate render-blocking resources.

#### IDENTIFYING RENDER-BLOCKING RESOURCES

A Lighthouse audit flags the following resources as render-blocking:
- A `<script>` tag that:
    - Is in the `<head>` of a HTML document,
    - Does not have a `defer` attribute,
    - Does not have an `async` attribute
- A `<link rel="stylesheet">` tag that:
    - Does not have a `disabled` attribute. When this attribute is present, the browser does not download the stylesheet.
    - Does not have a `media` attribute that matches the user's device.
- A `<link rel="import">` tag that:
    - Does not have an `async` attribute.

#### IDENTIFYING CRITICAL RESOURCES

To reduce the impact of render-blocking resources, identifying critical resources is an important part of the process. To do this, we make use of the [Coverage Tab](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage) of the Chrome DevTools. 

The Coverage Tab allows us to see how much of our code is being used versus how much is being loaded.

To open the Coverage Tab, first open Chrome DevTools via `CMD + ALT + I` on MacOS and `CTRL + SHIFT + I` on Windows. Then:
- Click the Chrome DevTools Options Icon on the top bar
![Chrome Top Bar](https://i.ibb.co/CVgShYS/Screenshot-2020-02-16-at-22-53-52.png)
- Go to More Tools and select Coverage
![Coverage Option](https://i.ibb.co/8BWK3pB/Screenshot-2020-02-16-at-22-59-33.png)

![Coverage Tab](https://i.ibb.co/3F1dbwb/Screenshot-2020-02-16-at-23-03-46.png)
                                 COVERAGE TAB

Clicking on the reload button reloads the website and therefore captures the coverage/usage of several files that were requested by the web page.

![Coverage of AliExpress.com](https://i.ibb.co/4jZYTGT/Screenshot-2020-02-16-at-23-09-18.png)

The Coverage Tab shows us information such as the resource URL, resource file type, total file size, its unused bytes and a visualisation of used versus unused bytes.

Clicking on the resource URL, Chrome DevTools opens the file indicating the used (critical) and unused (non-critical) lines of code.

![Indication In File](https://i.ibb.co/f9NKdfL/Screenshot-2020-02-16-at-23-33-40.png)

Styles in CSS and code in JavaScript are marked in two colours in the Coverage Tab:
- __Red (non-critical)__: These are styles that apply to content not immediately visible and code not being used in page's core functionality.
- __Blue (critical)__: These are styles that are required for first paint and code that's critical to the page's core functionality.

#### REDUCING/ELIMINATING RENDER-BLOCKING RESOURCES

Once you've identified render-blocking and critical resources, you can go ahead and eliminate the different types of render-blocking resources:
- Render-blocking stylesheets,
- Render-blocking scripts and
- Render-blocking imports

##### ELIMINATING RENDER-BLOCKING STYLESHEETS 

Eliminating render-blocking stylesheets can be done through inlining critical styles required for the first paint inside a `<style>` block at the `head` of the HTML document. Then load the rest of the styles asynchronously using the `preload ` link (`<link rel='preload'>`) which [defers unused CSS](https://web.dev/defer-non-critical-css).

You should also consider automating the process of extracting and inlining "Above the Fold" CSS using the [Critical tool](https://github.com/addyosmani/critical/blob/master/README.md).

Another approach to eliminating render-blocking stylesheets is to split up those styles into different files, organised by media query. Then add a media attribute to each stylesheet link. When loading a page, the browser only blocks the first paint to retrieve the stylesheets that match the user's device. Below, is an example of how this can be done. 

```html
<link href="style.css"    rel="stylesheet">
<link href="style.css"    rel="stylesheet" media="all">
<link href="portrait.css" rel="stylesheet" media="orientation:portrait">
<link href="print.css"    rel="stylesheet" media="print">
```
In the example above,
- The first declaration is render blocking and matches in all conditions.
- The second declaration is also render blocking: `all` is the default type so if you don’t specify any type, it’s implicitly set to `all`. Hence, the first and second declarations are actually equivalent.
- The third declaration has a dynamic media query, which is evaluated when the page is loaded. Depending on the orientation of the device while the page is loading, `portrait.css` may or may not be render blocking.
- The last declaration is only applied when the page is being printed so it is not render blocking when the page is first loaded in the browser.

Finally, you'll want to [minify](https://web.dev/minify-css) your CSS to remove any extra whitespace or characters. This ensures that you're sending the smallest possible bundle to your users.


##### ELIMINATING RENDER-BLOCKING SCRIPTS

As with render-blocking stylesheets, once you've identified critical code, move that code from the render-blocking resource URL to an inline script tag in your HTML document. When the page loads, it will have what it needs to handle the page's core functionality.

If there's code in a render-blocking resource URL that's not critical, you can keep it in the URL, and then mark the URL with `async` or `defer` attributes.

Code that isn't being used at all should be removed.

##### ELIMINATING RENDER-BLOCKING IMPORTS

For non-critical HTML imports, mark them with the `async` attribute. As a general rule, `async` should be used with HTML imports as much as possible.

```html
<link rel="import" href="file.html" async>
```

### CONCLUSION

This post elaborates on one of the ways to optimise the First Paint(FP) and First Contentful Paint(FCP) metrics by avoiding render-blocking resources.

In the next post, we look at how we can cache critical resources to improve performance on repeat visits.