HTTP/1.x vs HTTP/2

One of the ongoing changes that is being made to the web is the transition from HTTP/1.x to HTTP/2. What is this change? What’s the difference between the two? How should assets be handled differently from one to the other to ensure good performance?

HTTP/1.x

Before we get into what the change is, let’s talk about HTTP/1.x. This way of delivering information over a network has been around since 1997. Basically, after doing a DNS lookup (or getting it from cache), then a TCP connection, then a SSL negotiation (if it’s being served over HTTPS), the browser then makes a series of requests. HTTP/1.x is limited to six connections per origin: it must go through this process for each chunk of six assets that it wants to download. Thus, if you’ve got many different assets, like a bunch of stylesheets, it will take more time because for each chunk of assets, the client has to go through the negotiation process to get them.

Because with HTTP/1.x each asset on the page might be outside a chuck of six, best practice was to reduce the number of files on the critical render path as much as possible. This is why CSS is usually bundled in one file. This is why you have sprites with a bunch of different images in one file and CSS to point to one part of it. (What a headache!). JavaScript was put into all one file for this reason as well.

An example of a sprite by [Yug](https://commons.wikimedia.org/wiki/User:Yug)
An example of a sprite by Yug

The Change

You can see that the “best practices” that HTTP/1.x encouraged are not good:

  • Large bundled files

If you made one small change, you needed to cache bust and reload a large CSS or JavaScript file
– Couldn’t benefit as much by dividing files by section of site

If styles A and B are needed for the homepage and A and C needed for the product page, it’s still better to have A, B, and C lumped together.
– Sharded Domains
I mentioned above that with HTTP/1.x, you’re limited to loading six assets at a time from a given host. In order to get around this, you might load your code from origin.rei.com and your images from images.rei.com. That way, you can have 6 files loading from origin and six from images at the same time. The problem with this is that for every different host, you have to wait for a new negotiation.

  • Sprite Maintenance Nightmare

It’s not that big a deal to no longer use an icon that you no longer need in a sprite image, but if you need to add a new credit card type to a checkout sprite, now things need to be redone. Sure, there are tools that take some of the pain away: it’s still a headache.

There had to be a better way. In 2009, Google started experimenting with a new protocol called SPDY. Sites that started using this protocol saw up to a 50% reduction in page load times, a significant victory. The lessons learned from SPDY were incorporated into a new specification for HTTP, HTTP/2.

HTTP/2

HTTP/2 changes this. Now, instead of needing to shard domains and lump everything in the same file, HTTP/2 creates a two-way stream between the client and the server. The header is compressed, which reduces the weight, especially when sending many small files. Different streams can be prioritized, which leads to prioritized files ending up at their destination quicker.

Performance Implications

Surprisingly, even after 2.5 years of HTTP/2 being in the wild, the best practices for the front end aren’t firmly established. Backend implications are clear: don’t shard (have different origins)

Clear Front End Best Practices

There are definite gains that you can make on the front end:

  • Unbundle files

Because HTTP/2 is streaming and doesn’t have the six asset limit at a time, you can now be smarter about dividing and caching resources.

Unclear Front End Best Practices

Some implications aren’t as clear right now

  • Eliminate inlined styles and scripts?

Amazon Cloudflare ran an article in which they asserted that it would be best if developers stopped inlining styles, scripts and other resources (like SVGs). They point out that because these resources aren’t cached, users have to download them each time they visit. Not only that, it breaks the streaming priority. They assert that this will slow the time to first paint. Instead, they recommend removing inlined assets and use the push feature of HTTP/2.

I’m not sure that this is the best way to get time to first paint down. Theoretically, for first visit, you could deliver the HTML with things inlined, still download the assets in the background after load and cache them. Then, on a return visit (marked by a cookie), you could deliver the non-inlined version that refers to the files you’ve already cached on the client.

Amazon’s recommended approach sounds cleaner, but testing would need to be done to see if it’s faster for first paint. If you’ve seen any articles about time to first paint with HTTP/2, I’d love to hear about them.

As you can see, the front end best practices around HTTP/2 haven’t solidified yet. I’ll be running some experiments in the coming months to find out more and I’ll let you know the results. In the meantime, please pass along any articles you’ve seen about this topic so I find things I may have missed!

Sources:
Tim Kadlick’s web performance workshop at #perfmatters.
High Performance Browser Networking by Ilya Grigorik
New Relic article on HTTP/2
Cloudflare article on HTTP/2
HTTP/2 Spec

Leave a Reply

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