preface

Recently, while researching the vue-CLI 3.0 build project, I found the following usage in the index.html generated after the build:


<link as=style href=/css/app.f60416c7.css rel=preload>Copy the code
<link as=script href=/js/app.69189fdd.js rel=preload>Copy the code

This touched my knowledge blind area, in line with the purpose of literacy, studied the link tag, found that this small function is quite powerful, the above is to achieve the preload function, understand some English, a see preload will roughly know.


Have previously been preloaded technology, like prefetch, subresource etc., about the difference between the two and preload, this is another topic, interested can search, don’t want to search, as long as you know the two weak compared to the preload force to go, The prefetch browser is a little bit more compatible, and these three have their own preferences and application scenarios. We won’t go into details, but let’s expand preload in detail.

Function introduction:

Preload is a new Web standard designed to improve performance and make FE’s control over loading more granular. It gives developers the ability to customize load logic without the performance penalty of script-based loaders.

A basic use of preload is to load resources ahead of time. Although most resources based on markup languages can be found early by the browser’s preloader, not all resources are based on markup languages, such as those hidden in CSS and JS (fonts, images, etc.). When the browser finds that the page needs these resources, it has to go through the process of loading and executing the rendering again, which degrades the user experience and delays the rendering of the page.


Preloader profile

If the HTML parser encounters synchronous Script when creating the DOM, the parser stops creating the DOM and executes the script instead. So, if resource retrieval only happens when the parser creates the DOM, the involvement of synchronous scripts leaves the network empty, especially for external script resources, and of course, in-page scripts can sometimes cause delays.



Preloaders are designed to optimize this process by analyzing the browser’s early parsing of HTML documents (a process called tokenization), finding tags that might contain resources, and aggregating the urls of those resources. The output from the tokenization phase is sent to the actual HTML parser, and the collected resource URLs are sent along with the resource types to the fetcher, which loads them sequentially based on their impact on page loading speed.


Benefits of preloading:

  1. Having the browser preload the specified resource (which is not executed after preloading is complete) and execute it when it needs to be executed separates the loading from the execution without blocking the rendering and window.onload events.
  1. Preload specified resources in advance, especially font files, so that no font appears until the page is rendered, loaded, and then the page font flashes to the desired font.
  1. With the onload event, you can customize the resource after preloading the callback function.

Attributes involved:

Application Scenarios:

  • Contains media

A nice feature of elements is that they can accept a media attribute. They can accept media types or valid media queries as attribute values, which will enable you to use reactive preloading!

Let’s take a look at a simple example (see the source code on Github or an online example) :

<head>Copy the code
  <meta charset="utf-8">Copy the code
  <title>Responsive preload example</title>Copy the code

Copy the code
  <link rel="preload" href="bg-image-narrow.png" as="image" media="(max-width: 600px)">Copy the code
  <link rel="preload" href="bg-image-wide.png" as="image" media="(min-width: 601px)">Copy the code

Copy the code
  <link rel="stylesheet" href="main.css">Copy the code
</head>Copy the code
<body>Copy the code
  <header>Copy the code
    <h1>My site</h1>Copy the code
  </header>Copy the code

Copy the code
  <script>Copy the code
    var mediaQueryList = window.matchMedia("(max-width: 600px)");Copy the code
    var header = document.querySelector('header');Copy the code

Copy the code
    if(mediaQueryList.matches) {Copy the code
      header.style.backgroundImage = 'url(bg-image-narrow.png)';Copy the code
    } else {Copy the code
      header.style.backgroundImage = 'url(bg-image-wide.png)';Copy the code
    }Copy the code
  </script>Copy the code
</body>Copy the code

Copy the code

You can see that we have included a media attribute in the element, so that when the user is on a device with a narrower screen, the narrower image will be preloaded, and on a wider device, the wider image will be preloaded. Then we still need to append the appropriate image to the header element — window.matchmedia/MediaQueryList to do this (see Testing Media Queries for more information).


  • Font preloading

Web fonts are a common example of a critical resource that was discovered late. But in the current stage of front-end development where user experience is critical to the front end, web fonts are also critical to page rendering. Font references are buried deep in THE CSS, and even if the preloader parses the CSS in advance, there is no way to determine whether the selector containing the font information will actually apply to the DOM node. So in order to reduce FOUT(flash of unstyled text) flickering, the font file needs to be preloaded. With preload, a line of code takes care of it:


<link rel=preload href='font.woff2' as=font type='font/woff2' crossorigin />Copy the code


NOTE :

The Crossorigin attribute is required when loading fonts, even if the fonts are not cross-domain and are on their own company’s servers, because the user agent must obtain font resources in anonymous mode (
Why is that?).

The Type attribute ensures that the browser only retrieves resources it supports.



  • Dynamically loaded, but not executed

Another interesting scenario is also made possible by preload — when you want to load a resource but don’t want to execute it. For example, if you want to execute a script at a certain point in the page’s life cycle, and you can’t make any changes to the script, you can’t create a so-called runNow () function for it.


Before Preload, there was a limit to what you could do. If your method is to insert the script where you want it to be executed, since the script can’t be executed by the browser until it’s loaded, you’ll have to wait a while. If you use XHR to preload the script, the browser will refuse to reuse the script. In some cases, you can use the eval function to execute the script, but this method does not always work and is not completely free of side effects.


Now with Preload, everything is possible


var link = document.createElement("link");Copy the code
link.href = "myscript.js";Copy the code
link.rel = "preload";Copy the code
link.as = "script";Copy the code
document.head.appendChild(link);Copy the code


The above code lets you preload the script, and the following code lets the script execute


var script = document.createElement("script");Copy the code
script.src = "myscript.js";Copy the code
document.body.appendChild(script);Copy the code



  • Asynchronous loading based on markup language

Look at the code


<link rel="preload" as="style" href="asyncstyle.css" onload="this.rel='stylesheet'">Copy the code


The onLoad event of Preload can modify the REL property after the resource is loaded, making for a cool asynchronous resource load.


Scripts can also be loaded asynchronously in this way


Don’t we already have <script async>? <scirpt async> is fine, but blocks the window’s onload event. In some cases, you might want to do that, but there are always some cases where you don’t want to block the window’s onload.


For example, if you want to load a piece of code that counts page views as quickly as possible, but you don’t want the loading of that code to delay the rendering of the page and affect the user experience, you don’t want to delay the Onload event of the window.


With Preload, it’s done in minutes.


<link rel="preload" as="script" href="async_script.js"Copy the code
onload="var script = document.createElement('script'); script.src = this.href; document.body.appendChild(script);" >Copy the code



  • Reactive loading

Preload is a link that, according to the specification, has a media property (not yet supported by Chrome, but too soon) that makes selective loading possible.


What’s the use? Let’s say your site supports both desktop and mobile access. You want a large interactive map for desktop browser access, and a small static map for mobile is sufficient.


You don’t want to load two resources at the same time. The common practice is to load resources dynamically based on the current browser type based on JS, but then the browser’s preloader can’t find them in time, which can delay the loading time and affect the user experience and SpeedIndex score.


How can browsers discover these resources as early as possible? Or Preload!


With Preload, we can load resources ahead of time, and with the media property, the browser will load only the resources it needs.


<link rel="preload" as="image" href="map.png" media="(max-width: 600px)">Copy the code
<link rel="preload" as="script" href="map.js" media="(min-width: 601px)">Copy the code



  • HTTP headers implement preloading

Another feature of Preload is that it can be rendered via HTTP headers. This means that most of the mark-up language-based declarations described above can be implemented through HTTP response headers. (The only exception is the onload event case, where it is impossible to define an event handler in the HTTP header.)


Link: <thing_to_load.js>; rel="preload"; as="script"Copy the code
Link: <thing_to_load.woff2>; rel="preload"; as="font"; crossoriginCopy the code


This approach is especially useful in situations where the optimizer and the page developer are not the same (that is, the optimizer may not be able or want to modify the page code). Another excellent example is the External Optimization Engine, The engine scans and optimizes the content.



  • Checking Browser Features

All of the previous examples are based on the assumption that browsers support Preload to some extent, or at least implement basic functions such as scripting and style loading. But if that hypothesis doesn’t work. Everything will be however useless.


To determine whether the browser supports preload, we modify the DOM specification to know which values rel supports (whether rel= ‘preload’ is supported or not).


How to do this isn’t in the original article, but Github has a code to look at.


var DOMTokenListSupports = function(tokenList, token) {Copy the code
if (! tokenList || ! tokenList.supports) {Copy the code
    return;Copy the code
  }Copy the code
  try {Copy the code
    return tokenList.supports(token);Copy the code
  } catch (e) {Copy the code
    if (e instanceof TypeError) {Copy the code
      console.log("The DOMTokenList doesn't have a supported tokens list");Copy the code
    } else {Copy the code
      console.error("That shouldn't have happened");Copy the code
    }Copy the code
  }Copy the code
};Copy the code

Copy the code
var linkSupportsPreload = DOMTokenListSupports(document.createElement("link").relList, "preload");Copy the code
if (! linkSupportsPreload) {Copy the code
  // Dynamically load the things that relied on preload.Copy the code
}Copy the code


Browser compatibility:

Caniuse.com lists the browser versions supported by this feature, but don’t worry, in unsupported browsers, this part of the TAB will be ignored and can be smoothly degraded.