H2 has built-in support for interesting concepts like prioritization and re-prioritization of requests. Unfortunately, most impls in clients and servers are either not full or not very good:
I recommend googling "http/2 prioritization" and checking blogs and talks from Andy Davies and Pat Meenan. The subject is super interesting and inherently hard; browsers need to make certain assumptions whether scripts, fonts or CSS are more important and should be prioritized and it's non-obvious how to handle it best.
https://github.com/andydavies/http2-prioritization-issues
https://medium.com/dev-channel/javascript-loading-priorities...
It's useful for much more than that; I'd actually argue stream multiplexing is most useful outside of the browser in bespoke HTTP APIs, because that's a place where you can just stumble on cases where high fan-out requests are useful. For the browser case you're often limited by things like pagination, while JS/CSS can be amalgamated.
Not that it isn't good for small images too! But APIs benefit a lot as well and I think that's easily forgotten.
> If your website has a lot of small files served
What about JSON/GraphQL APIs?
Reponses need to be sent in the order the requests were made, since there is no _request id_ for the client to know which response is for which request.
This is a major annoyance with HTTP/1.1 pipelining, since it then becomes the client responsibility to send requests in an order that minimizes latency.
Say you want to retrieve 1) a huge background image of the website and 2) a small js script at page load time. If you send 1) then 2), you have to wait for the background image to come first.
Not only this is bad for client user experience, but it also means that the server cannot send responses in real-time, it has to buffer all subsequent responses until the previous ones are sent, creating bloat.
HTTP/1.1 is the worst.
Technically, this could have been mapped with an additional header alone.
Something like HTTP/1.2 that features a header like Transfer-Request-Id: 13337
While I agree with the sequential pipelining case I'd argue with the abuse from the other perspective. Clients have now much more power to re-request things in a suboptimal order, because the server still accepts it.
There's no cryptographic signatures on buffers that could allow a dictionary on what has been sent already, and what has not, which would fix the issues that a client can re-prioritize and re-request resources that will drain the server.
The beauty of HTTP/1.1 (apart from slowloris) was its simplicity and cacheability for reverse proxies.
Now with H2 shit can hit the fan real quic once a new LOIC comes out because it has a whole new attack surface for DDoS scenarios, where even a single client can take down a server in those circumstances (aka when a server blindly accepts re prioritization requests).
But I would agree that HTTP/1.1 isn't good when it comes to transport hop specific headers (everything Transfer-...) because they allow crafted packets like HTTP smuggling that can trick a reverse proxy and backend because there's no way to validate the packets on a lower level when it comes to their Origin.
This is something I would've hoped SPDY/QUIC would address, because they are a real security risk embedded into the nature of the protocol.
HTTP/1.1 as documented looks like the simplest pipelining should work. But too many HTTP/1.1 servers in the wild by the point browsers began trying to enable pipelining were getting this wrong. Users don't care that "technically your bank's web server is non-conforming and you should contact them to report the issue" what they hear is just "Don't use our broken web browser".
Whereas with H1 browser opens up to 6 connections, downloads 1 file on each, then once the response comes it tells "ok now gimme another file" etc. (Another RTT until it comes back). That's many round-trips saved.
This is probably mostly useful when downloading many small images. It can be also useful for splitting JS into smaller bundles to favor cache hits for returning visitors. (An be also useful to serve ES modules without or with minimal bundling; however in practice bundling is still useful given that modern JS apps have 100s/1000s of files and small files overhead still matters at such numbers).