- A sprite tends to have fewer bytes than separate images, because of image format overhead and better compression when combining similar things.
- The same may be true for zipped CSS/JS.
- What about CSS/JS/image parsing overhead?
- Even though HTTP2's request overhead is substantially less than HTTP1, fewer HTTP requests shouldn't make your site slower.
So the best practices will be outdated. Harmful? Not so sure.
(It's still faster under HTTP/1.1 to concatenate because of the overhead of making multiple HTTP requests and the parallelization limit, but one of the perf gains of HTTP2 is that since extra requests are cheap caches can be targeted and granular. Changes to a single script won't necessitate redownloading a giant concatenated bundle — you only need to download the single script that got updated.)
Further, if any image on the sprite sheet is currently visible, the entire sprite sheet must remain in memory, when otherwise the browser could free the memory of all the non- visible images. And it may sometimes be necessary to use a much more expensive drawing path when drawing sprites to ensure that pixels from one image don't bleed into another image.
These negative effects will be felt most severely on resource-constrained mobile devices, where it matters most.
One should always measure when making decisions about performance, but in an HTTP2 world my recommendation would be to avoid sprites in most cases.
Also, most if not all browsers use GPU to render web pages. And spriting actually comes from gamedev/GPU world [1], where many textures are baked/combined into a big one because it's efficient from performance/memory layout POV.
A final thought, what about server IO becoming a bottleneck when it needs to read hundreds of small files from disk for each request?
I welcome HTTP2 but I'm not too sure on the timeline for rollout and if it will end up being an "IE6"-type thorn in my side. Even if we are split 50-50 between HTTP1 and HTTP2 it sounds like the best approach is keep doing what you are doing... Either way I don't think sprites/concating/minifying is going anywhere anytime soon.
I agree that the existing approaches are very much valid though, but I also look forward to not having to concatenate javascript files anymore. We've developed a lot of tooling to work around issues that stem from that, and it doesn't address the problem of needing a varying set of javascript files on a per-page basis easily.
Or, as I like to put it: "Birds of a feather compress better together."
HTTP1 supports pipelining requests.
> HTTP2 also uses compression, unlike HTTP1, and so the size of the request is significantly smaller - and thus faster.
'significantly'? How much is that?
> HTTP2 multiplexes; it can send and receive multiple things at the same time over one connection.
If that one connection stalls, multiple things won't be transferred.
Plus it introduces new protocol overhead.
Also, an HTTP/1.1 server, when configured properly, will use compression as well.
They designed a new compression algorithm called HPACK specifically to compress headers in HTTP2: https://http2.github.io/http2-spec/compression.html
In small HTTP/1.1 requests the headers can be much larger than the content, which is part of the motivation for combining files into one request.
Head-of-line blocking makes the HTTP/1.1 pipelining perform poorly. Multiplexing is a more performant solution than pipelining.
Here's some worthwhile reading on the subject: http://http2.github.io/faq/#why-is-http2-multiplexed
> 'significantly'? How much is that?
Depends. In HTTP/1.1 request headers weren't compressed, and you generally have a ~1500 byte limit for a request to fit in a single packet. If you crossed that threshold, and if compression brings you back under (it certainly might), you could see 2x or better perf gains on time-to-first-byte depending on how many packets your initial request was being broken into.
> If that one connection stalls, multiple things won't be transferred.
While true, it's still often easier to optimize a single saturated connection than multiple ones for a variety of reasons (slow start, congestion, etc). More reading on the subject: http://http2.github.io/faq/#why-just-one-tcp-connection
Personally I'm really excited about HTTP2 being deployed. It makes the web fast by default — no need to concatenate or domain shard once it's widely deployed — and adds extra opportunities for performance (e.g. server push) that we haven't seen yet.
QUIC is a solution for that - It's Google's answer to TCP, and dealing with multiplexed connections. I recommend taking a look.
Edit: answering my own question: http://stackoverflow.com/a/807161
Supposedly they separate all these little features out (no telnet client or tftp client!) for security. But it's really a cover-your-ass style that results in worse security for many users which just install everything trying to make stuff work. Dynamic compression being separate is a great example of that.
And in those cases HTTP 1.x vs HTTP 2.x is a moot discussion anyway.
For instance, is there an asset pipeline that will concatenate and minify all my JS for HTTP/1.1 clients, but minify my JS separately for HTTP/2 ones, and build versions of my HTML page that references the two different assets depending on which HTTP protocol is in use?
The article is misleading on this, but those HTTP/1.1 best practices aren't slower when served over HTTP2. HTTP2 will still be faster than HTTP/1.1.
- Spriting and concatenation will not be worse under HTTP/2, just (mostly) unnecessary.
- Splitting content across multiple domains will be 'harmful', in that you're enduring multiple TCP handshakes instead of one. But this is no worse than HTTP/1.1
- Minification is unchanged. It will still decrease the download size. Although I sometimes find that the difference after compression is trivial on many modern sites, so is often not worth the decrease in readability/debuggability.
I could buy that what I should do is wait a few years, until the majority of my users are HTTP/2 instead of HTTP/1.1, and then optimize everything for HTTP/2 and still work (slowly) on HTTP/1.1. But at the moment it's not clear why I should care: my options seem to be really fast on HTTP/2 and really slow on HTTP/1.1, or kinda fast on HTTP/2 and kinda fast on HTTP/1.1.
Caching could be an issue, but if you're frontending with a reverse proxy, you could append another querystring parameter for http2 then do caching in the proxy level.
Let's say I have a site that uses best practices for HTTP/1.1, and loads within 2 seconds without caching. It sounds like the article saying that switching to HTTP/2 will make my site slower.
What I've read so far in other places is that the site should by default (no modifications) be faster, it is just wont be optimized until I remove all my hacks for HTTP/1.1
Run slower than the same site with the HTTP 1.1 'hacks' removed
Run faster than the same site serving via HTTP 1.1.
In most cases.
I understand the points made about sharding and concatenating (and also the limits of the arguments), but the short article just mentions cookie-less domains and then just seem to forget about them. So this practice is still valid? Or is there some feature in HTTP2 that also obsoletes this?
A reluctance to change your markup should not be a reason to resist a change to HTTP2, if and when it is actually available.
1) How can they coexist on the same server? I googled a little but maybe with the wrong keywords. I found this but it's pretty shallow on details http://nginx.com/blog/how-nginx-plans-to-support-http2/
2) I still want to serve HTTP1 optimized content to HTTP1 clients. I hope web servers are going to let us serve different content based on protocol version. Maybe the application server needs to know about it too.
Anybody here with first hand experience?
At the protocol level, this is covered by section 3 of the HTTP/2 spec: http://http2.github.io/http2-spec/index.html#starting
For https:// URIs, the client and server agree on which version to use as part of the TLS negotiation. For http:// URIs, major browsers won't be using HTTP/2 at all, but if they did, the spec defines a mechanism similar to websockets: the client makes an HTTP/1.1 request with a special Upgrade header, and the server responds by changing protocols in a coordinated way.
But, by continuing to use the old hacks, your site won't be as fast as it could be. It's an opportunity cost. Some of those opportunities being:
- increased cache granularity (avoids invalidating a whole sprite or concatenated bundle when just a single part changes)
- parallel downloading of files that were previously bundled into one file
- fewer DNS lookups, now that you're not sharding
- less energy/memory usage in the client because you're not decoding/remembering whole sprites
And the subtlest, biggest win:
- simplifying your build process.
Well, that's the rub, isn't it?
When are we going to possibly be in a state where we know our website is going to be served over HTTP2?
Not for a while, probably? Not just wait until all the browsers support HTTP2, it's wait until the browsers that _don't_ support HTTP2 are a small minority.