Using Preload and Prefetch in Your HTML to Load Assets

Alex Jover Morales

Loading assets on a page is one of the most important parts to get right in order to achieve a fast first meaningful paint. Usually, real world apps load multiple CSS, font, JavaScript and image files, and these assets a render-blocking by default, which impairs loading performance.

In this post we’ll explore a new feature called resource hints that allows to preload or prefetch assets and avoid the render-blocking nature of resources.

What Do You Mean by Render-Blocking?

When a request to a resource is render-blocking, it means that the window.onload event will not be triggered until that request finishes. In modern single page apps, most of the frameworks rely on this event in order to start operating. That means that parts of the UI will not start rendering until the render-blocking requests have finished loading.

Consider the following example:

<html>
  <head>
    <link
      rel="stylesheet"
      href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>

    <style>
      html {
        font-family: Roboto;
      }
    </style>
  </head>
  <body>
    Hello

    <script>
      window.onload = function () {
        console.log('Loaded');
      }
    </script>
  </body>
</html>

You might have to change the value of the <link>'s href attribute in-between your tests to avoid it from be cached. You can change the part with Roboto:400,600 to anything else like Roboto:300,400,600.

You can find the code in this JS Fiddle. Please, go ahead and open it in Chrome. Then:

  • Open the devtools with the Network tab and the console
  • Throttle the connection to Slow 3G
  • Run the code, and pay attention to when the Loaded text is logged

The Loaded should’ve been logged in the console right after the CSS file is loaded, as the next image shows:

Load without preload

Preloading

The rel="preload" attribute value can be applied to several file formats, including CSS, JS, fonts, images and more. You should set the corresponding as attribute depending on the type of file. For CSS, the value should be as="style", and for JavaScript as="script".

Let’s change the previous <link> line to:

<link
  rel="preload"
  as="style"
  href='https://fonts.googleapis.com/css?family=Roboto:100,900|Material+Icons'>

Then, if you run it as before and pay close attention, you’ll see that the Loaded log shows up right before the CSS request starts, as the following image shows:

Load using preload

However, you may have noticed that the CSS style hasn’t been applied to the text. That’s because using preload or prefetch only fetches the resource, but it doesn’t apply it. Instead, it keeps it in memory and is up to you to decide when to load it.

For the preload case, you’ll want to apply it as soon as it loads. So you could change it to:

<link
  rel="preload"
  as="style"
  onload="this.rel = 'stylesheet'"
  href='https://fonts.googleapis.com/css?family=Roboto:100,900|Material+Icons'>

By setting the rel attribute to stylesheet, the browser is told to use the resource. But since it’s been already downloaded in memory, it doesn’t download it again.

You can try it out in this JS Fiddle.

Since the solution relies on JavaScript, you could add a <noscript> tag as a fallback when JavaScript is disabled or fails to load:

<link
  rel="preload"
  as="style"
  onload="this.rel = 'stylesheet'"
  href='https://fonts.googleapis.com/css?family=Roboto:100,900|Material+Icons'>

<noscript>
  <link
    rel="stylesheet"
    href='https://fonts.googleapis.com/css?family=Roboto:400,600|Material+Icons'>
</noscript>

Prefetching

Prefetching works similarly to preloading, with the difference that the browser considers the resource as low priority. That’s why it’s usually used in resources that are not required initially, but rather are used at a later point.

You can change the previous example in order to use prefetching:

<link
  rel="prefetch"
  as="style"
  onload="this.rel = 'stylesheet'"
  href='https://fonts.googleapis.com/css?family=Roboto:100,900|Material+Icons'>

The difference is that you’ll probably see it load a bit later given its low priority.

Preloading JavaScript

This example, taken from this Google Developers article on preloading, shows that applying the preloaded JavaScript resource is done a little differently: you must set the src attribute of the file and insert it into the DOM:

<link rel="preload" href="used-later.js" as="script">
<!-- ... -->
<script>
  var usedLaterScript = document.createElement('script');
  usedLaterScript.src = 'used-later.js';
  document.body.appendChild(usedLaterScript);
</script>

* Code snippet reproduced from work created and shared by Google and licensed under the Apache 2.0 License.

Wrapping Up

Preloading and prefetching gives us more power on how the resources are loaded, boosting web performance and allowing for faster Progressive Web Apps. At first I didn’t know why they weren’t working, until I realized they only fetch the resource without applying it… sigh 😌.

Note that resource hints are not supported in all browsers just you, and you may want to use a polyfill in production. If you’re only interested in preloading CSS resources, this polyfill from the Filament Group is a popular solution.

Stay cool 🦄

  Tweet It

🕵 Search Results

🔎 Searching...