Was it a lack of browser support? or that it didn't really work with CDNs?
Was it a lack of browser support? or that it didn't really work with CDNs?
The server is never able to truly know if the asset is actually required by the client
Early hint is better, probably: the server quickly tells the client it will need those assets. The client can then decide if they must be fetched, or if they are already available.
Now, the user comes back and asks for index.html again: do you send everything again? Surely the resources are still in the user's cache. If you don't, how do you know what to send? Only the user's browser knows what's in can't and what's not.
So you face the choice: speed up first visits but waste bandwidth for subsequent visits, out slow down first visits but speed up subsequent visits.
Probably because it's a game changer only if you're at google/amazon/meta (or slightly smaller) scale.
For everybody else its largely a huge complexity addition, and it's essentially ignored.
It took a long time for them to "understand" the data, and that HTTP2 was not very useful, especially when compared the impact of changing CDN, or optimising for CDN caching.
> it was problematic as Jake Archibald wrote about previously, and the performance benefits were often difficult to realize
Edit:
Clicking through to the linked post by Jake, <https://jakearchibald.com/2017/h2-push-tougher-than-i-though...>, problems mentioned are
- browsers had buggy implementations which wouldn't (always) use the pushed data. In that case, you've (as a web server) kept the connection busy and sent bytes for nothing
- browsers ignore max-age when using push cache. Given that the time between pushing and using is usually <1 second, that seems fine to me? Don't get this one. Further down is another caching header caveat. Just don't push data to the cache that you don't want it to cache?
- pushed data is dropped when the connection closes. Seems like a simple fix to me: keep data around until you navigate away from the page or the tab gets unloaded for any other reason. Or keep the connection open while the page renders because there might be more requests anyway, like for an image or commenter's avatar
- different pages using the same connection can use each other's cache, so if you "open in a new tab" two links and one of them already pushed the /css/main.css then the other doesn't need to anymore. This sounds like a very useful feature, not a reason to remove push at all. Further down in the article, under a separate point, it says "Once the browser uses something in the push cache, it's removed", which sounds like this mechanism can't work at all and they'll steal each other's resources instead?! Surely that's not the case, since it makes the sharing entirely useless?
- if you use authentication, make sure to send it along when requesting e.g. a font via JavaScript because otherwise it can't use the cache because you're not the same user. Okay, sounds reasonable and like a simple thing to do
- not all browsers implemented cross-origin pushing
Finally, there's a concluding paragraph starting with
> There are some pretty gnarly bugs around HTTP/2 push right now, but once those are fixed I think it becomes ideal for the kinds of assets we currently inline, especially render-critical CSS.
This doesn't sound like a reason to remove push altogether. Quite the opposite?
The tl;dr: its hard to predict ahead of time what resources browsers really need, so often you send the wrong thing or the non ideal thing. End result is the practical performance benefit was much smaller than the theoretical one.
I didn't read in the post what you said its tldr is supposed to be; maybe I read over it
By the time you visit the second page on a multi-page site, you are likely to have almost all stylesheets, scripts, and common images already cached. This means you will reject almost all of the resource the server tries to push to you. Even on the first page, modern browsers are very quick to identify resources they need to load, both from headers and the early parts of the document. They load those resources concurrently while they are still parsing the document, so they are rarely blocked for a noticeable time.
Meanwhile, single-page sites have evolved to a point where the entire application is contained in one or two heavily optimized, minified scripts. You just load that one script and you're done. Most small images these days are SVG embedded right in the source code, so again, there's little need to push other resources.
The only time a modern website makes you to load a lot of unanticipated resources is when those resources are used for tracking and advertising. They can't be pushed because they live on different origins.
This isn’t true of most websites - look at the developer tools traces - because it’s terrible for performance to optimize for the IE6-era browser design. With those kind of bundles, you have to push a ton of content which didn’t change any time one byte of any resource changes. Since HTTP/2 substantially reduced the cost of multiple requests any site which has repeat visitors will benefit enormously from letting the bulk of the content which hadn’t changed be cached and only refetching the few responses which actually need to be updated.
On the other hand, sites with lots of separate static assets are often split into multiple origins. Images from a CDN, fonts and libraries from another CDN, and API endpoints on a "serverless" platform somewhere else. These sites won't benefit much from having Push enabled, either.
Of course with HTTP/2 it's better to serve as many resources as possible from a single origin. But that doesn't sit well with the recent trend of sprinkling your stuff across buckets and lambdas, duct-taped together with CORS. Good ol' Cache-Control still does most of the heavy lifting there.
The premise of http2 push is that those resources could be sent before the first round trip even occured - before any link headers or request body is available.
Which is kind of two things - the round trip of network latency and also the backend latency of how long it takes to make the resource.
The solution was to give up on the round trip network latency, but concentrate on backend latency. Which you can do by sending link headers before the resource is finalized, or if you cant even do that, by sending a 103 response.
The new solutions are still leaving some latency on the table. Price to be paid for simplicity.
The other side of that coin, is if you really care about the latency of those resources for clients who dont have them cached, you can just embed them in the html document.
I don't know the history here, but nginx seemed to have a solution (which was removed) to be able to conditionally attach pushes to a location directive based on a cookie, and then set that cookie to know if it was a first visit. Seems simple enough? Did it actually never work or something?
"Should" is doing a lot of work there. For dynamic resources this is often very not true. On the other hand i suppose the landing page is often highly optimized.
The cookie approach does seem like the most common approach to that problem. I have no idea how well it worked.
A more traditional multi-page website, on the other hand, can benefit a lot from putting a CDN in front of it. Once the main dynamic resource has been generated, the rest of your assets can be loaded from edge servers closer to your users. When RTT is on the order of 10ms, it doesn't really matter whether you push or pull.
Edge caching is great if resources can be shared. Sometimes resources are per-user.
SPA's that involve dynamic per user content still have to load it to show the user anything interesting.
Edge caching is definitely not 10ms for everyone. Depending on who you are targeting that could be a reasonable assumption, but it is definitely not true of the world at large.
and, probably in situations where the benefit of decreasing "time to first render" is big enough, there it makes sense to have a server that is coupled to the various low-level bits (load balancer connection tracking info, TLS session info, User Agent header, and Cookie of course) and for new sessions it can produce an optimized response payload.
That leads you to one of two paths:
1. The web content needed should be communicated to the server by the client; either requests are made with Fetch with additional parameters, or via a service worker which can then populate the cache itself. However, once you are supplying logic in the page to handle these resources, there are other approaches you can make - such as having a service worker populate the cache by downloading a single archive and unpacking it.
2. The other option would be for content which is specifically never meant to be cached, such as live updates of a sporting event. There is no API however to support this, and we already do have things like WebSocket to do this.
It wasn't given enough time, would be my guess. First Apache release that included HTTP2 support was in late 2015, same year HTTP2 RFC finished going through the process. In 2017 there still was browser inconsistency on how server push was handled (one of the reference articles in the sibling comment link). nginx implemented support for push somewhere around 2018 (based on wikipedia information).
All those changes need to trickle down. Versions available in stable distros, config defaults etc. First time I've enabled http2 on my Apache servers, was in 2020 (and there are likely application servers out there that still don't support it directly in 2024).
I suppose that some solution could have been implemented so that my Python app can tell nginx to stream certain static resources over a given connection… but the tools for that never surfaced. Most HTTP frameworks don’t support push.