Web Performance —Resource Hinting

In HTML, link types indicate the relationship between two documents, in which one links to the other using an <a>, <area>, <form>, or <link> element.

This article is more focused on the link types which can be helpful in improving the web performance. It includes dns-prefetch, modulepreload, preconnect, prefetch, preload, prerender.

Prefetch a CSS file, prerender a full page, or resolve a domain ahead of time — and you won’t have to wait for it when it’s actually needed!

DNS- prefetching

A browser has to perform a DNS resolution when it connects to a new third-party domain. (A third-party domain is a domain that’s different from the one your app is hosted on.) This may happen when your site uses a font from Google Fonts, loads React from a CDN, or requests a JSON response from your API server.

For each new domain, resolving the DNS record usually takes around 20–120 ms. It only affects the first resource downloaded from that domain, but it still matters.

<link rel="dns-prefetch" href="https://api.my-app.com" />

href points to the domain name you want to resolve. The scheme doesn’t matter – both https://api.my-app.com and //api.my-app.com would work fine.

Preconnect

In addition to dns-prefetch, preconnect will resolve the DNS but it will also make the TCP handshake, and optional TLS negotiation. Hence it is expensive as compared to dns-prefetch.

<link rel="preconnect" href="https://example.com">

What the connection process includes?
To connect to each site, a browser has to perform the following steps:

  • DNS resolution. Find a server’s IP address (216.58.215.78) for a specified domain name (google.com).
  • TCP handshake: Perform a roundtrip (a message goes client → server → client) to initiate a TCP connection to a server.
  • TLS handshake (only for HTTPS sites): Perform two roundtrips (a message goes client → server → client → server → client) to initiate a secure TLS session (Transport Layer Security).

It can take up valuable CPU time, particularly on secure connections. This is especially bad if the connection isn’t used within 10 seconds, as the browser closes it, wasting all of that early connection work.

<link rel="dns-prefetch" /> vs <link rel="preconnect" />

Using both of these tags for the same domain is not really useful — <link rel="preconnect" /> already includes everything <link rel="dns-prefetch" /> does, and more. Cases where we can use both:-

  • If you need to support old browsers, use <link rel="dns-prefetch" /> as a fallback for <link rel="preconnect" />.
  • You want to speed up more than 4–6 domains. It’s not recommended to use <link rel="preconnect" /> with more than 4-6 domains, as opening and keeping a connection is an expensive operation. <link rel="dns-prefetch" /> is more lightweight, so use it for other third-party domains if you want to speed them up too.

Prefetching

<link rel="prefetch"> asks the browser to download and cache a resource (like, a script or a stylesheet) in the background. The download happens with a low priority, so it doesn’t interfere with more important resources.

Prefetch is a hint to the browser that a resource might be needed, but delegates deciding whether and when loading it is a good idea or not to the browser.

The browser doesn’t do anything with the resource after downloading it. Scripts aren’t executed, stylesheets aren’t applied. It’s just cached — so that when something else needs it, it’s available immediately.

<link rel="prefetch" href="/style.css" as="style" />

href points to the resource you want to download.

as can be anything you can download in a browser:

  • style for stylesheets,
  • script for scripts,
  • font for fonts,
  • fetch for resources downloaded with fetch()

When to use ?

  • You have an e-commerce site, and 40% of your users go from the home page to a product page. Use <link rel="prefetch"> to download CSS and JS files responsible for rendering product pages.
  • You have a single-page app, and you code-split it so that different pages load different bundles. When a user visits some page, ask your router what other pages it links to, and use <link rel="prefetch"> to preload bundles for those pages.

Preload

<link rel="preload"> tells the browser to download and cache a resource (like a script or a stylesheet) as soon as possible. It’s helpful when you need that resource a few seconds after loading the page, and you want to speed it up.

Preload is a declarative fetch, allowing you to force the browser to make a request for a resource without blocking the document’s onload event.

Preload is for current navigation but has an as attribute which enables the browser to do a number of things that subresource and prefetch did not enable.

  • The browser can set the right resource priority.
  • The browser can make sure that the request is subject to the right Content-Security-Policy directives,
  • The browser can send the appropriate Accept headers based on the resource type.
  • The browser knows the resource type so it can later determine if the resource could be reused for future requests
  • preload does not block the window’s onload event
<link rel="preload" href="late_discovered_thing.js" as="script">

The possible as values are :-

  • "script",
  • "style",
  • "image",
  • "media",
  • and "document".

EARLY LOADING OF FONTS

Web fonts are buried deep in CSS, and even if the browser’s preloader parsed CSS, it cannot be sure they’d be needed.

<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin>

Responsive Loading

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

<link rel="preload" as="script" href="map.js" media="(min-width: 601px)">

How is preload different from prefetch and subresource when they all are used to tell browser to fetch things?

  • <link rel=“prefetch”> is a directive that tells a browser to fetch a resource that will probably be needed for the next navigation and hence will be fetched with extremely low priority.
  • <link rel=“subresource”> was originally planned to tackle the current navigation,but shows no way to tell the priority to the browser so is downloaded with a low priority and some times behaves same as it would have without using subresource.

Prerender

<link rel="prerender"> asks the browser to load a URL and render it in an invisible tab. When a user clicks on a link to that URL, the page should be rendered immediately. It’s helpful when you’re really sure a user will visit a specific page next, and you want to render it faster.

<link rel="prerender" href="https://my-app.com/pricing" />

href points to the URL you want to render in the background.

Pre-rendering a page is extremely costly — both in terms of traffic and memory. Don’t use <link rel="prerender" /> for more than one page.

Modulepreload

The <link rel="modulepreload"> spec actually allows for optionally loading not just the requested module, but all of its dependency tree as well.It tells the browser to download, cache, and compile a JS module script as soon as possible.

Browsers that choose to preload dependencies recursively should have robust deduplication of modules, so in general the best practice would be to declare the module and the flat list of its dependencies, and trust the browser not to fetch the same module twice.

As described above, this tag is only useful for preloading ES modules — i.e., modules you’re importing through import ... or <script type="module">.

If you want to preload a regular script, use <link rel="preload" as="script">.

Caching and compiling. <link rel="modulepreload"> not only fetches the module and puts it into the network cache, but also compiles it into bytecode. This means when the module is needed, the browser can start executing it immediately.

Sources:-

https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types
https://3perf.com/blog/link-rels/#dns-prefetch

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store