Yeison Daza
5 min read

How to Load Our Website Faster

As frontend developers, our goal is to deliver better experiences to users. One of the main things we can do to achieve this is to make our applications load as quickly as possible.

There are several studies with real-world cases of companies that, by optimizing their site load times, have managed to sell more, get more visits, and overall positively impact business profitability. So this becomes a critical topic.

To make our site as fast as possible, we can use a wide variety of techniques:

  • Minify our code
  • Compress our assets (gzip, brotli, etc.)
  • Load only the code that’s actually needed
  • Load optimized images at the right size, etc.
  • Use lazy loading for images, avoiding loading images the user can’t see
  • Use CDNs that are as close as possible to our users
  • Properly cache our assets so we don’t download them multiple times
  • Only transpile the necessary JS code for the browsers we want to support
  • Don’t block page rendering with asset loading

Many of these can be achieved fairly easily using the right tool, but today I want to talk about one that, in my opinion, isn’t used as much and can have the biggest impact with just a few lines of code.

Preload and Prefetch

Preload and Prefetch are web standards that let us improve the performance of our site by taking control of when the resources that matter to us get loaded.

Preload is like telling the browser, “Hey, download this soon because the user is going to need it right away,” and the browser starts downloading it even while it’s still reading the HTML.

Prefetch is like telling the browser, “Hey, download this but it’s not super urgent.” Maybe the user will need the resource at some point, and the browser decides when the best moment to download it is. If the user navigates to a different view, the download will still continue in the background.

Remember, it’s important not to use this to load every single resource on your site. With great power comes great responsibility.

How do you use preload and prefetch?

To use them, you need to declare them using link tags as early as possible in the head of your site. You mainly need three attributes:

  • rel defines whether to use preload or prefetch
  • href the path to the resource
  • as the type of resource

So, for example, if you want to preload your site’s styles, you’d do:

<html>
  <head>
    <link rel="preload" href="/static/styles.css" as="styles">
    <link rel="preload" href="app.js" as="script">
    <link rel="stylesheet" href="/static/styles.css">
  </head>
  <body>
    <script src="app.js"></script>
  </body>
</html>

Making this small change, we can see some results like the images below.

In this first image, we see the Lighthouse result without using preload. The page became visible at around 700ms.

In the second one, using preload for the styles, the page is visible at around 300ms.

This example only uses preload on a single CSS file. Imagine how many assets your project has that are blocking your site’s load.

Now imagine someone lands on the home page and you know they’re likely to visit /about, and you’re using code splitting. You could start prefetching the script needed for that page.

<html>
  <head>
    <link rel="prefetch" href="about.js" as="script">
  </head>
  <body>
    <h1>Home</h1>
    <a href="/about">Sobre mi</a>
  </body>
</html>

Once the user lands on the home page, the browser will at some point download the script needed for /about, making the load of that page much faster.

What content types can we use?

  • audio
  • document
  • embed
  • fetch
  • font
  • image
  • object
  • script
  • style
  • track
  • worker
  • video

Things to keep in mind

  • If you use preload on resources that won’t be used immediately, you’ll get a warning in the console.
  • If a resource is already cached (service workers, for example), it shouldn’t be downloaded again.
  • You can see the priority of each resource using the network tab in the developer tools.
  • If the resources you preload/prefetch have valid cache headers, they get stored in cache.
  • When loading fonts, you need to use the crossorigin attribute, even if you’re loading them from the same domain.
  • Don’t try to load absolutely everything using this technique.

Fonts

One of the most critical assets is fonts, and they’re often the ones blocking page rendering. We can tell the browser that they’re very important and should be downloaded soon:

<head>
  <link
    rel="preload"
    href="https://fonts.googleapis.com/css?family=Rubik:300,400,500,700"
    as="font"
    crossorigin
  >
  <link href="https://fonts.googleapis.com/css?family=Rubik:300,400,500,700" rel="stylesheet">
</head>

Also remember to use font-display: swap so the browser will show the content with the fallback font and swap it as soon as the font loads, without blocking the render.

Now technically we’re still blocking page rendering. With critical assets, we don’t have a choice — we have to load them. With preload, we’ll get them downloaded as soon as possible. But with non-critical assets, we can load them lazily without executing them right away:

<body>
  <script>
    var preload = document.createElement("link");
    link.href = "app.js";
    link.rel = "preload";
    link.as = "script";
    document.head.appendChild(link);
  </script>
</body>

And when we want to use it, we simply inject it into the site:

<body>
  <script>
    var script = document.createElement("script");
    script.src = "app.js";
    document.body.appendChild(script);
  </script>
</body>

Preload elements based on resolution

Since preload/prefetch use the link tag, we can use the media attribute to customize when we preload assets:

<link rel="preload" as="image" href="imagen.png" media="(max-width: 600px)">

With webpack

If you use webpack to build your project, you can also use this technique. Just use the preload-webpack-plugin plugin, and since version 4.6.0, support was added so that when you use code splitting, you can use a magic comment to define whether you want to use preload or prefetch on that chunk:

import(
  /* webpackChunkName: "modal" */
  /* webpackPrefetch: true */
  "Modal"
)

Final words

This approach to handling assets is used by projects like Next.js and Gatsby.js, achieving great results. Try it out in your projects and let me know how much faster things load now.