Which WPO techniques have become obsolete with the use of HTTP/2?

Ramón Saquete

Written by Ramón Saquete

When we move our website from HTTP/1.1 to HTTP/2, some Web Performance Optimisation techniques continue to work as usual, while other techniques, which with HTTP/1.1 considerably improved performance, have gone on to offer an insignificant improvement, and some of them can even make performance worse. This is something we need to keep in mind, given the importance of WPO for search engine rankings and user satisfaction.

To understand when these situations can arise, we first need to understand how HTTP/1.1 and HTTP/2 work.

How HTTP/1.1 works

As you all probably know, websites download many different files. When the HTTP/1.1 has to request many files, it can only do it one at a time, meaning that if the browser knows that it needs to request the files: file1.jpg, file2.jpg, file3.jpg, … what the browser does is first request file1.jpg, and until the request reaches the server and the server returns the entire file, the browser cannot request file2.jpg. Again, until it doesn’t receive file2.jpg, it cannot request file3.jpg, and so on. As a result, the browser spends quite a lot of time blocked, unable to do anything, while the requests and responses travel over the network.

To try and minimise the time the browser spends not doing anything with the HTTP/1.1 it paralyses the download by opening various connections, in a way that the browser with two open connections can request file2.jpg and file3.jpg at the same time, one for each connection, but it won’t be able to request any other file until one of these two files finishes downloading, so it continues to be stuck for some amount of time. Moreover, this solution results in these two open connections having to fight for the available transmission speed, not taking full advantage of it, and it gets progressively worse the more open connections there are. For that reason, browsers limit the number of simultaneous connections to a low number, usually 5 or 6. In the following image we can see an example with 3 simultaneous connections:

How HTTP/1.1 works

How HTTP/2 works

The HTTP/2 allows the browser to request all the files the website needs, at the same time and using just one single connection, returning them all at the same time as well. Its network flow diagram would look like this:

How HTTP/2 works

To do this, it applies serial multiplexing, which is a common technique in data transmission. It consists in dividing the files into chunks, and send a chunk of each, in the following way and order: first chunk of file1.jpg, first chunk of file2.jpg, first chunk of file3.jpg, …, second chunk of file1.jpg, second chunk of file2.jpg, second chunk of file3.jpg, …, and so on.

Multiplexing
HTTP/2 multiplexing: the responses are divided into chunks on the server, to be sent all at the same time and recompose on the client, in a way that it makes it look as if the download is happening in parallel.

As a result, and due to the way the protocol works, the browser doesn’t spend stuck all that time, and the transmission speed is taken much better advantage of.

Moreover, the browser can assign priorities to the transmission of files, on those which are needed to paint the website immediately, which means the server will send the chunks of the most important files first. With HTTP/1.1 something similar happened, because files were ordered by priority in the browser’s request queue, but this did not ensure they would reach the server in the same order. With HTTP/2, files do not have to wait in a queue, instead they are directly sent, and download priorities are handled much better, because the server knows which ones it needs to return first.

HTTP/2 introduces other optimisation improvements, such as compressed headers, binary format, and removal of redundant information, all of which reduce the amount of information to be transferred, but neither of them is as effective as multiplexing. The only changes we need to keep in mind to know which optimisation techniques become obsolete with this new protocol are multiplexing and the fact that HTTP/2 keeps the TCP connection active.

🤓 Multiplexed and serial file transmission is key to understanding which WPO techniques become obsolete with the use of HTTP/2.Click To Tweet

When can we use HTTP/2?

Both the client and the server need to enable HTTP/2, to be able to use this protocol. Presently, all browsers allow HTTP/2, but this is not the case with the crawlers used by search engines to crawl websites, including Googlebot. This means the website will be indexed and downloaded with HTTP/1.1. Another mandatory requirement is to use the TLS protocol under HTTP/2 to offer HTTPS. This is a restriction imposed by all browsers to promote use of HTTPS, as they do not allow use of HTTP/2 without secure communication, while specs and server do.

Moreover, the server needs to allow the use of a TLS protocol extension called ALPN (Application-Layer Protocol Negotiation), which is used to negotiate with the server whether the communication is going to be made with HTTP/2 or HTTP/1.1. As an alternative to this extension, the NPN (Next Protocol Negotiation) was used, with the same purpose, but on 31/05/2016 Google updated its browser to only allow ALPN, which forces the server to have an updated version of the operating system to use this and be able to enjoy HTTP/2. Google enforced this because ALPN is much faster, as it prevents an additional roundtrip whereas NPN does not.

To be able to enjoy HTTP/2 both the client and the server need to enable it, and work with HTTPS and ALPN 👍🏽Click To Tweet

Despite all these requirements, HTTP/2 has already replaced HTTP/1.1 on more than 25% of websites, and its growth is of approximately 10% per year. There are also rumours that Googlebot could start using it any time.

WPO techniques that become obsolete with the use of HTTP/2

Keep-alive header

The server response header “Connection: Keep-Alive” makes the HTTP/1.1 to keep the TCP connection open after downloading a file, so that the TCP doesn’t need to open and close the connection with each downloaded file. This is important, because TCP creates a roundtrip for opening the connection, and another roundtrip for closing the connection, in addition to the roundtrip needed to transfer the file with HTTP (roundtrips should be avoided because the data transfer over the network is one of the tasks, which takes the longest when a website is loading). This is how it works:

  • First roundtrip:
    1. The TCP sends a request from the client to the server to open the connection.
    2. The server returns a response with the acceptance and an identifier of the connection.
  • Second roundtrip:
    1. The HTTP requests a file from the client.
    2. The server returns the requested file.
  • Third roundtrip:
    1. The TCP requests to close the connection from the client.
    2. The server accepts to close the connection.

If it needs to download another file, it repeats all the steps, but if it leaves the connection open, it will only need to request the new file.

HTTP/2 always leaves the connection open and ignores the “Connection: Keep-Alive” header. This means that, if our website uses HTTP/2, it will only make our headers weigh more.

Reduce the number of requests

There are various WPO techniques allowing to reduce the number of requested files. As I’ve already said, when requesting several files with HTTP/1.1, the browser gets blocked. With HTTP/2, this no longer happens, rendering these techniques obsolete. But let’s better analyse what happens with each of them:

Unify CSS and JavaScript files

The unification of CSS files isn’t going to make a considerable difference with HTTP/2, as it did with HTTP/1.1, but if we’re already doing this, we can leave it as is, because the HTML is going to be slightly smaller, as it has less references to files. To unify JavaScript, however, will make more sense, because this way we can load the unified file asynchronously in the header, without fear of errors as a result of dependencies between files. And so, by unifying JavaScript we don’t get a reduction in requests, but we will if we load the Javascript asynchronously with the async attribute, because this way we aren’t blocking the painting of the page. With the synchronous load, on the other hand, when the browser runs into a <script> tag, it has to wait for the JavaScript to run, before it can continue to analyse the HTML.

CSS Sprites

This technique consists in unifying various images into one, then cropping them using CSS and placing them where they’re supposed to go on the page. This technique is no longer effective, and the only thing we can do –if we’re lucky– is if we unify visually similar images, the unified file may end up weighing a little less than the images on their own. In any case, this is a tiny improvement, so the CSS sprites technique is no longer worth using for optimisation. If we want to do it for code organisation purposes, though, it’s a whole other story. If used, try not to unify images that are not going to be used, as it will unnecessarily increase the file size. I, personally, do not recommend it, because when we implement changes, we could forget the images we no longer use in the sprites.

Inlining images with DATA URIs and CSS code in the HTML

Inlining images with DATA URIs consists in placing images in text strings inside the CSS file, or directly in the HTML, instead of linking them. Including the CSS inside the HTML with the <style> tag prevents us from linking it in a separate file. These techniques can be applied for two purposes: to decrease the number of requests, and/or to deliver critical resources immediately. The first reason is made obsolete with HTTP/2, but the second one regarding critical resources continues to be valid. Critical resources are files, which are going to be used for painting important parts of the page (mainly those located in the above the fold, or without scrolling).

Inlining an image prevents the browser from having to request a file that used to be linked from it, thus avoiding a roundtrip. For example, let’s imagine we have an HTML file, which links a CSS file, which in turn links an image. Regardless of the protocol, this generates 3 roundtrips, because each file will inevitably be requested one after the other, because we need to have the previous one to know which one is the next. But if we inline the image in the CSS, when we download it, we’ll already have the image, meaning we’re saving ourselves an additional roundtrip. Or, we could inline the CSS in the HTML with the <style> tag and with the image, and we wouldn’t have to download additional files once he HTML has been downloaded, preventing two additional roundtrips. The problem with this technique is that the images and the CSS inlined directly in the HTML are not stored in the browser’s cache, so it’s not recommended for websites with many recurring visitors. So, in summary, these techniques, when used correctly, still make sense.

There is a new technique for delivering critical resources, so that they’re downloaded with the HTML, which allows the browser to store the files in the cache. It is called HTTP/2 Server Push, a subject I’ll tackle in some other post.

Parallelise the number of simultaneous requests

As we’ve already seen in browsers using HTTP/1.1, they parallelise requests by opening several connections, which, depending on the browser, are limited to 5 or 6, and requests are launched for each of them. This limit is set by the browser for the domain,  so we can increase the number of requests it launches if we use various domains. There are two techniques which do this:

Domain sharding

This technique consists in creating various subdomains to link the resources of our website. For example, for www.humanlevel.com we could have js.humanlevel.com, css.humanlevel.com, img1.humanlevel.com, and img2.humanlevel.com. This way, we have a subdomain from which to link JavaScript files, another one for CSS files, and two for our images.

This technique produces some improvements for HTTP/1.1, if we’re careful not to overdo it with the subdomains and making tests. With HTTP/2 not only we’re not going to get an improvement, it’s actually going to worsen our performance. This is primarily due to the fact that this technique needs additional time to resolve each of the subdomains to their corresponding IPs. With HTTP/1.1 this loss could be compensated with the reduction in time the browser spent stuck, but with HTTP/2 we don’t have this problem, and we waste time on the DNS resolution of additional domains, and making more unnecessary connections. Therefore, if we use HTTP/2 and this technique, it is best we get rid of it.

CDN (Content Delivery Network)

A Content Delivery Network consists in a worldwide reverse cache proxy network (servers which cache the content of a main server) connected directly to the core routers with the same IP. The core routers are Internet’s core routers, and with these proxies connected directly to them we get a faster access to any server, because to reach a server we always have to go through a router hierarchy, which go from the core router to routers, which get increasingly smaller, all the way down to the router connected to the server network. Moreover, core routers are configured to balance the requests to the cache proxy of the closest or fastest CDN.

Thus, by using a CDN we will access the closest and fastest server of the client requesting the website, which is why this technique continues to be useful with HTTP/2. However, we commonly use the CDN to serve static files only, from various subdomains (images, CSS, and JavaScript, while dynamic files (HTML) are served from our server. This is not as interesting with HTTP/2, because we’ll be doing the same thing as with domain sharding, which as we’ve seen, worsens performance, so we should avoid having several subdomains. The ideal configuration for HTTP/2 would be if the CDN served all the resources under the same domain (the website’s own domain). But serving the HTML and all the static files from the CDN is an advanced configuration that only some CDN provide, and it should only be applied when we can cache the content for a period of time.

If we have no other choice but to use the CDN to cache only static resources, either because the CDN provider doesn’t offer other service, or because we want to keep the information updated by the minute, we should use only one CDN subdomain.

In any case, we must ensure that our CDN provider supports HTTP/2, so that the improvement the CDN can offer is worth it.

Conclusions

HTTP/2 on its own is a considerable improvement for a website’s performance, but to make the most of it we must avoid using domain sharding and CDNs under HTTP/1.1.

On the other hand, we can improve performance by using a CDN with HTTP/2 and the website’s own domain, or we could possibly improve it using the website’s domain and only one unique subdomain. Inlining images and CSS in the HTML will also improve performance, if these techniques are used on critical resources and few recurring visitors. It is also a good idea to unify JavaScript files, if it’s to be able to load them asynchronously.

Unifying CSS files and using CSS sprites, while obsolete and no longer worth our time, are not going to affect us negatively if they’ve already been implemented, so we can leave them be. Moreover, Googlebot’s crawlers still use HTTP/1.1, so if we continue to use these techniques for file unification, the performance will improve for them.

Ramón Saquete
Autor: Ramón Saquete
Web developer at Human Level Communications online marketing agency. He's an expert in WPO, PHP development and MySQL databases.

Leave a comment

Your email address will not be published. Required fields are marked *