Accelerating sites with the help of "early tips"

Published on August 23, 2018

Accelerating sites with the help of "early tips"

Original author: Andrew Betts
  • Transfer
Sites are still loading too slowly. At the most critical moment of the boot process, the feed is often almost completely idle. The new technology proposed by the engineer FastI's Kazuho Oka will help to better use this critical first couple of seconds.

Have you ever downloaded a website on your phone - and looked for 10 seconds on a page without text? No one likes to sit and look at a blank screen while some unusual font loads. Therefore, it makes sense to postpone the loading of such important things to the earliest possible time. Preload Link rel = preload had to partially solve the problem. The first thing the browser does is to parse the HTTP headers, so this is the perfect place to point to the preloading of a resource that will definitely be needed later.

Internet is slow by default.

Let's see what happens if you don't use preloading. The browser can start downloading resources only after it has discovered that it needs them. This happens most quickly to the resources that are in the HTML during the initial analysis of the document (for example, <script>, <link rel=stylesheet>and <img>).

Slower downloads resources that are found after building the render tree (this is where the page slows down because of the font loading, because to understand this, you first need to load the style sheet, parse it, build the CSS object model, and then render tree).

Resources that are added to the document using JavaScript loaders that are triggered by events likeDOMContentLoaded. If you put it all together, we get a non-optimized and rather meaningless waterfall. Much of the time the channel is idle, and resources are loaded either earlier than necessary, or too late:

Link rel = preload helps a lot

In the past few years, the situation has improved thanks to Link rel = preload . For example:

Link: </resources/fonts/myfont.woff>; rel=preload; as=font; crossorigin
Link: </resources/css/something.css>; rel=preload; as=style
Link: </resources/js/main.js>; rel=preload; as=script

Thanks to these directives, the browser can start loading resources immediately after receiving the headers and before starting to analyze the HTML body:

This is a significant improvement, especially for large pages and critical resources that would otherwise be discovered late. Especially for fonts, but anything can become a critical resource, for example, a data file needed to load a JavaScript application.

However, we can do more. After all, the browser does not do anything between the moment when it finishes sending the request and when it receives the first bytes of the response (a large green fragment on the initial request is higher).

We engage the time "server reflection" using the "early tips"

On the other hand, the server is really busy. It generates a response and determines whether it is successful or not. After database access, API calls, authentication, etc. the server may decide that the correct answer is a 404 error.

Sometimes the server thinking time is less than the network latency. Sometimes much more. But it is important to understand that they do not overlap. While the server is thinking, we are not sending data to the client.

But it is interesting that before generating the answer you already know some styles and fonts that need to be loaded to display the page. After all, error pages usually use the same corporate identity and design as regular pages. It would be great to send these headers Link: rel=preload even before the server works . It is for this purpose that the standard of "early prompts" is conceived.Early Hints , specified in RFC8297 from the HTTP Working Group, was authored by my colleague Kadzuho Oku from Fastly. Appreciate the magic of several status lines in one answer :

HTTP/1.1 103 Early Hints
Link: <some-font-face.woff2>; rel="preload"; as="font"; crossorigin
Link: <main-styles.css>; rel="preload"; as="style"
HTTP/1.1 404 Not Found
Date: Fri, 26 May 2017 10:02:11 GMT
Content-Length: 1234
Content-Type: text/html; charset=utf-8
Link: <some-font-face.woff2>; rel="preload"; as="font"; crossorigin
Link: <main-styles.css>; rel="preload"; as="style"

The server can record the first, so-called “informational” response code as soon as it receives the request, and issue it to the network. Then it will determine the real reaction and its generation. Meanwhile, in the browser, you can start preloading much earlier:

Of course, this will require certain changes in browsers, servers and CDN, and some browser developers have expressed reservations about the difficulties of implementation. Therefore, it is still unclear when these headers can be put into operation. You can track progress in public trackers for Chrome and Firefox .

We expect that ultimately you will be able to give Early Hints headlines directly from Fastly, while still sending requests in the standard way. We have not yet decided how to expose the interface through the VCL, so please let us know if you have any suggestions for this!

But what about HTTP / 2 Server Push?

With HTTP / 2 comes a new technology called Server Push, which seems to solve the same problem as Link rel = preload in the Early Hints response. Although it really works (and you can even quickly generate custom pushy from the edge servers in Fastly), but there is a significant difference on several points:

  • The server does not know about the availability of the resource at the client, so it often pushes it unnecessarily. Due to network buffering and latency, the client usually cannot cancel sending before receiving the entire content. (Although there is a possible solution to this problem, in the form of the proposed Cache Digest header , on which Kazuho works with Yoav Weiss from Akamai).
  • Running resources are bound to a connection, so it is easy to start a resource that the client does not use, as it tries to get it through another connection. Clients may need to use a different connection because the resource is in a different source with a different TLS certificate or because it is retrieved in a different credential mode .
  • H2 Push is not very consistently implemented in different browsers. Therefore, it is difficult to predict whether it will work or not in your particular case.

Either way, Early Hints and Server Push offer different tradeoffs. Early Hints tips provide more efficient use of the network in exchange for additional packet exchange. If you assume a low network latency and a long time to think about the server, then Early Hints is the right solution.

However, this is not always the case. Let's be optimistic and imagine that humans will soon settle on Mars. They will view the web pages with a delay of 20-45 minutes for each packet exchange, so the additional exchange is extremely painful, and the server time is insignificant compared to it. Server Push wins easily here. But if we ever browse the web from Mars, we’ll rather download some kind of data package, something like the web packages we ’re currently offering andsigned exchanges .

Extra Bonus: Accelerated Minimizing Request

Although Early Hints is supposed to be used primarily in the browser, there is an interesting potential benefit for the CDN. When Fastly receives many requests for the same resource, we usually send only one of them to the source, and the rest are placed in the waiting queue. This process is known as request collapsing . If the response from the source includes Cache-Control: private, then all requests should be removed from the queue and sent to the source individually, because we cannot use one answer to satisfy several requests.

We cannot make a decision until the answer to the first request has been received, but if Early Hints support, if the server issues an Early Hints response with the Cache-Control header, then we know much earlier that the queue cannot be minimized into one request, but instead immediately send the source all requests from the queue.

Order less critical content with priority tips

Early prompts are a great way to access some of the most valuable objects in the queue (waterfall): when the network is idle, the user is waiting, there is only one request on the way, and there is nothing on the screen. But as soon as HTML is loaded and the page is analyzed, the number of resources that need to be loaded increases dramatically. Now it is important not to load resources as quickly as possible, but to load them in the correct order. Browsers use a strikingly complex array of heuristics to independently determine the download priority, but if you want to override them, in the future this can be done with the help of Priority Hints :

<script src="main.js" async importance="high"></script>
<script src="non-critical-1.js" async importance="low"></script>

With this new attribute of importance, developers can control the order of loading resources in the event of competition for the network. It is possible that low priority resources can be deferred until the processor and the network are released, or depending on the type of device.

Can it be used?

Neither early prompts nor priority prompts have yet become standard. Recently H2O, the HTTP / 2 server used and supported by Fastly, has begun to use Early Hints (see PR 1727 and 1767 ), and it intends to implement Priority Hints in Chrome , as well as actively tracking 1xx responses. At the same time, there is no harm in starting to send Early Hints right now - and if you want to get ahead of the trend, go ahead!