The underlying theory was that over the then-current HTTP/1.1 protocol, each additional HTTP request would add latency and thus page-loading time. Multiple separate files would take longer to download than an equivalent concatenated file.
Fast-forward a decade and the HTTP protocol has undergone a major revision to HTTP/2. HTTP/2 addressed several issues with HTTP/1.1 and aimed to enhance overall performance, simplicity, and robustness of the protocol. As for HTTP requests, concatenating files to minimize total HTTP requests may no longer be considered the best practice.
This article will examine the history of the HTTP protocol to provide context for the updates in HTTP/2 and shed light on how these improvements may be leveraged to optimize page-loading times of websites.
Hypertext Transfer Protocol (HTTP) is a fundamental component of how the internet operates. When you visit a website, say http://example.com, in your browser (Google Chrome, Safari, Microsoft Edge, Firefox, Opera, etc.), your browser sends an HTTP request that gets routed to the server hosting example.com. This HTTP request will look like the following (all of this happens behind the scenes to you as a user):
GET / HTTP/1.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36
Accept-Encoding: gzip, deflate
From the very first line, we can see that the browser is making a GET request to the “/” (root) URL at example.com via an HTTP/1.1 request (this server has yet to be updated to use HTTP/2). In plain language, the browser is asking to be shown the page at the home or root of example.com. Some other information is passed along with this request, though it is not important to understand for now.
Assuming that everything goes well (i.e., that you are connected to the internet, and that the server is running normally), the server will then return an HTTP response that looks like this:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Date: Fri, 13 Sep 2019 19:11:27 GMT
Expires: Fri, 20 Sep 2019 19:11:27 GMT
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT
Server: ECS (sec/9739)
<!-- ... html continues ... -->
From here, we see that an HTTP/1.1 response has been sent with the status code of 200 (OK). The HTML code that renders this web page in your browser is also sent. (See https://http.cat/ for a fun representation of the various HTTP status codes.) This is the basic premise of HTTP: a browser (or client) sends an HTTP request to a server, and the server responds in turn with an HTTP response.
Diving a bit deeper, HTTP runs over a TCP/IP connection, a set of network transport protocols for machines to communicate with each other (in our case, your web browser and the server). This gets into networking, which is beyond the scope of this article, but the important point here is to appreciate that how HTTP interacts with TCP can dictate page-loading performance. For example, HTTP/1.1 brought the vital advancement over HTTP/1.0 of maintaining the client-host connection via a request-header ‘keepalive’ flag, wherein subsequent client requests could recycle an existing TCP connection to the server for improved network efficiency (notably, each request had to wait for any previous requests to finish). For a good primer on this, see Chua Hock-Chuan’s HTTP (HyperText Transfer Protocol). Such an improvement was prompted by the drive for increased performance, a theme we see repeatedly throughout the history of the HTTP protocol.
Following the early days of HTTP/0.9 and HTTP/1.0 in the early-to-mid 1990s, HTTP/1.1 became an official standard around 1999 and achieved widespread adoption. It included some important performance optimizations over its predecessors, such as the aforementioned ‘keepalive’ connections.
After many years of global use, performance limits in HTTP/1.1 were being tested as both users and developers came to expect near-instantaneous response times for websites. In early 2012, the HTTPbis working group — the Internet Engineering Task Force’s HTTP Working Group, a consortium of various HTTP implementers, users, and experts — announced the new HTTP/2 initiative. (For more detail, read Ilya Grigorik’s Brief History of HTTP.) HTTP/2 provided many improvements over HTTP/1.1, which we will now explore.
HTTP/2’s main advantage over HTTP/1.1 is performance. Akamai made a clever demo illustrating HTTP/2’s up to 2x speed increase:
This drastically reduced load time is the result of several new features in HTTP/2:
HTTP/2 encodes HTTP requests and responses in binary in contrast to the plaintext encoding of HTTP/1.1. Binary encoding is less error-prone (it more accurately handles whitespace, capitalization, blank lines, and line endings) and is more efficient to parse.
The asynchronous delivery of responses in HTTP/2 over a single TCP connection generates a new question: which requests should be delivered first? For example, a stylesheet should have a higher priority than a small logo file. Stream prioritization allows more important assets to be prioritized and thus delivered faster. Individual streams are assigned a ranking integer between 1 and 256 and can be given dependencies on other streams. This process is largely handled on the browser side but has sadly found suboptimal implementation in all current browsers.
Sending less data — i.e., compressing the text content of HTTP headers — is always faster, ceteris paribus.
Ilya Grigorik and Surma’s Introduction to HTTP/2 goes into more detail on the multiple advantages of HTTP/2.
While performance enhancements are highly desirable in web development, adoption can be hindered by difficult implementation procedures and complex code changes. Fortunately, HTTP/2 is enabled via a server upgrade, which should require no website code modification in the majority of cases (unless more advanced optimization techniques are effected — see the next section, ‘HTTP/2 and site optimization’). HTTP/2 is also backward compatible, so older browsers will still be able to access an HTTP/2-enabled server over HTTP/1.1.
Having remained largely ignorant of the onset of HTTP/2, I was delighted to find that my website was delivered over the HTTP/2 protocol, without any updating or configuring on my part (Yes, my homepage comes in at a hefty 4.8 MB download, contradicting my earlier remark about web-page optimization. For now, this is a case of do as I say, not as I do):
As support for HTTP/2 required updates to both web servers and web browsers alike, adoption was low at its inception in 2015 but has since grown substantially: current usage of HTTP/2 sits at just over 40% at the time of this writing. Most modern browsers also started supporting HTTP/2 in 2015. Its use should steadily increase going forward.
Here are a few tips on how to leverage HTTP/2 in web development:
- Enable HTTP/2. To verify that your site is running HTTP/2, open your page in Chrome Developer Tools (or equivalent), click the Network tab, reload your page, and see if “h2” appears under Protocol, as in the above screenshot. If your site is not yet running HTTP/2 (which will appear as ‘http/1.1’), your web server may need to be upgraded.
- Stop concatenating assets. The old optimization practice of reducing the total number of HTTP requests made by a page no longer necessarily holds. The general recommendation with HTTP/2 is to deliver small, granular resources with optimized caching policies (such that changes to one file would require clients to re-download only that particular file instead of a massive concatenated file). However, unique situations must be addressed individually, as Craig Silverstein explains in Forgo JS packaging? Not so fast.
- Eliminate domain sharding. Domain sharding is the practice of splitting web page resources (images, scripts, etc.) over multiple domains to maximize the number of concurrent TCP requests over HTTP/1.1. This technique has been obviated by multiplexing in HTTP/2.
- Stop inlining assets. Inlining assets is the practice of embedding stylesheets and scripts directly into an HTML page to reduce total HTTP requests. Again, this issue has been largely resolved by HTTP/2 multiplexing.
HTTP/2 is here, let’s optimize!, a slideshow by Ilya Grigorik, gives a great visual overview of these HTTP/2 optimization strategies.
Certain optimization techniques intended for HTTP/1.1 are still considered good practice: minimize Domain Name System (DNS) lookups, use Content Delivery Networks (CDNs), compress assets during transfer, leverage browser caching, and minimize asset filesizes. HTTP/2 For Web Developers, by Ryan Hodson, goes into more detail on these techniques.
HTTP/3, previously known as HTTP-over-QUIC, is the next major revision to the HTTP protocol and aims to further reduce client-server latency and page-load times. It accomplishes this by forgoing the familiar TCP network transport layer for the newer QUIC (Quick UDP Internet Connections) transport layer. QUIC is already being tested on certain websites such as YouTube. For more information on this upcoming standard, see Tonino Jankov’s What Is HTTP/3 — Lowdown on the Fast New UDP-Based Protocol.
We have seen how HTTP/2 implements several improvements over its predecessor HTTP/1.1. These translate into better real-world performance on websites. Such advantages coupled with optimized website design deliver ever-better experiences to users and developers alike, a trend that will continue with increasing HTTP/2 adoption and eventually HTTP/3 adoption.
- 5 Ways to Improve Your Website’s PageSpeed Using HTTP/2, Bernt Fuglseth.
- Brief History of HTTP, Ilya Grigorik.
- Introduction to HTTP/2, Ilya Grigorik, and Surma.
- HTTP/2 For Web Developers, Ryan Hodson.
- What Is HTTP/3 — Lowdown on the Fast New UDP-Based Protocol, Tonino Jankov.
- Forgo JS packaging? Not so fast, Craig Silverstein.
- How HTTP/2 Is Changing Web Performance Best Practices, Clay Smith.