Hacker News new | ask | show | jobs
by matsemann 1954 days ago

    shouldBypassBackForwardCache()
    // Google Docs used to bypass the back/forward cache by serving "Cache-Control: no-store" over HTTPS.
    // We started caching such content in r250437 but the Google Docs index page unfortunately is not currently compatible
    // because it puts an overlay (with class "docs-homescreen-freeze-el-full") over the page when navigating away and fails
    // to remove it when coming back from the back/forward cache
Millions of pages have this bug, because of Safari's broken navigation. Nice that the big players get the browser to fix it for them. For instance, a common issue is you click a button that becomes disabled and shows a spinner while working, before forwarding to a new page. If you click back from the new page, Safari will render the previous page exactly as it was when leaving, so in a broken loading state (instead of starting it from scratch).
4 comments

What makes it broken, out of curiosity? Is there a spec anywhere that suggests that behavior is incorrect? Or is it just because it's not what Chrome does?
Yeah, I'm interested too. I might be wrong, but AFAIK there aren't any specs on how a browser should implement forward/back buttons, right?

I'm personally getting a ton of mileage on the Safari's much more stable forward/back cache, the fact that you can go back reliably gives me more comfort than other browsers where going back usually refreshes the page (although I can't really explain how this is much better). I personally feel that this bug is more of a web app bug rather than the browser.

The closest you get for how browsers should act regarding history is part of the HTML spec here: https://html.spec.whatwg.org/multipage/history.html

Of course, the exact implementation is not specified, browsers are free to either implement cached behavior, which I think Firefox does as well, or just a naive refresh.

I think the closest is the pagehide event

https://html.spec.whatwg.org/multipage/browsing-the-web.html...

Which appears to be supported in Safari, just like all the other browsers.

There's a metabug on HTML at https://github.com/whatwg/html/issues/5880 about defining how various platform-exposed features behave in the face of a bfcache (backwards/forwards cache).
Why shouldn't it show it in the same state? Seems like a reasonable thing to do.
If it was a static page, then sure. But for dynamic pages or SPAs it more often than not leads to going back to a page in a broken state. Other browsers have better heuristics for when this cache is used. So Safari's behavior is unexpected, even so that the big guys are taken by surprise it seems. I don't really mind either way, the main thing is that it's inconsistent.

It's not a huge deal, but it's just one of many small things making Safari annoying when developing. Especially since it cannot be tested without owning an Apple device.

GNOME Web is a webkit browser to name an example of non-Apple Web browsers.

From my perspective this is an application bug, and relying on heuristics is a bad idea. If a change should be made, it should be to make it explicitly the web apps task to handle on its own.

> But for dynamic pages or SPAs it more often than not leads to going back to a page in a broken state.

Definitely a page concern, not the browsers. This problem is also easy to fix and a solution has been known for many years by now: handle navigation via the URL always! (or, modern take: via the history API). A modal opens? The URL should change and because the URL changed to that specific path, show the modal. Now users can bookmark or go back/forward without any issues of pages being broken.

Conceptually I'd say that clicking a link and then clicking Back should be the same as right-clicking the link and opening it in a new window, and then closing that window.

But it wouldn't surprise me if "web apps" makes this hard for some reason.

In my mind the forward back buttons apply to the URL. So you are going back and forward in URL history, as if you were typing the URL in fresh each time. In the old days the back forward buttons were right there next to the URL on the toolbar.

It just occurred to me that on mobile, the back button is not associated with the URL at all, so its not surprising that people don't associate it with that anymore.

I think safari desktop hides the URL as well.

No, it's just one of too many things, big and small, making browser web apps annoying. The entire point of a browser was a relatively simple viewer app that renders docs ok on most devices; not an opionated renderLikeChrome mode. If the basic concept of leaving a page for linked content, then coming back can't be handled without heuristics, then clearly the web app model is broken af.
Sounds more like an issue with the web apps to me.
There is no spec to conform to to work around these cache issues. (IE was even worse in the past, shutting down the back forward cache if devtools were opened. Have fun debugging that)

But imagine Windows opening an app, drawing the last known interface state and then skipping half of the app startup code. Should apps deal with that too, or would it be considered a Windows bug?

The spec. doesn’t cover this case explicitly, but the general gist of RFC 2616 is very much on the side of “don’t reload things”:

> History mechanisms and caches are different. In particular history mechanisms SHOULD NOT try to show a semantically transparent view of the current state of a resource. Rather, a history mechanism is meant to show exactly what the user saw at the time when the resource was retrieved.

https://tools.ietf.org/html/rfc2616#section-13.13

If a web application depends on the browser reloading the page when the user presses the back button, then I think it’s fair to call that a bug in the web application. It is “trying to show a semantically transparent view of the current state of the resource”, which is explicitly called out as incorrect behaviour by the spec.

RFC 2616 is long obsolete; the section you cited is now https://tools.ietf.org/html/rfc7234#section-6 and is substantially reworked. The chunk you refer to has been removed, because it no longer reflected reality in any way. Even as originally specified, as a SHOULD, it wasn’t ever practical to implement completely because of memory requirements. Since 1999, a lot has changed, and the fact of the matter was that the original recommendation just didn’t make sense any more, worded as strongly as it was. So instead they’ve switched it round to essentially say that you may redisplay an earlier-retrieved representation (rather than that you SHOULD NOT do the opposite).
Modern applications for Windows (UWP) and iOS do use tombstones. The app's memory itself is completely suspended/saved to disk, and then the state is restored. The app startup code is _not_ called again.
It has been a while since I wrote iOS app code but I’m pretty sure iOS does not, although the libraries provide a mechanism you have to save and restore state yourself. And iOS doesn’t swap, it just kills apps when it needs memory.

Anyway, how would you handle connections to remote servers?

>Especially since it cannot be tested without owning an Apple device.

Yes very annoying. They dont have to bring Safari on Windows, but at least WebKit on Windows would be nice for testing. In the mean time, Otter for Cross Platform Browser [1], or you could do Gnome Web with Windows WSL2.

[1] https://github.com/OtterBrowser/otter-browser

You can test GNOME Web (Epiphany) just fine, which does use the same engine.
I'm actually having a similar issue with my web app currently and I'm not sure what the best way to solve it would be. I was thinking of setting a checkbox in an invisible form when the page loads initially, and force a real reload if the checkbox was previously set, but that seems like a terrible hack. Any ideas?
We use this to force a refresh: https://stackoverflow.com/a/13123626/923847

Or you can use that event to fix what's wrong on the page without a refresh if possible (remove a modal, enable the button again etc)

Great! Looks like a proper way to do what I was trying to do. Thank you!

My web app is a game, so fixing everything without a refresh is unfortunately pointless for the most part, and forcing a refresh also ensures players are running the latest version if they've been away for a while.

I've actually been dealing with this issue. Does anyone have an easy way to resolve it? It causes some pretty nasty rendering issues in our app.
https://stackoverflow.com/a/13123626/923847

Can force a refresh when the page us navigated back to. Or use that event to fix whatever state your in.

Full refresh defeats the purpose of a spa unfortunately. I just tested that event and it actually doesn't appear to fire when navigating backwards, only when the page is initially shown...which contradicts the comments in that code.
Maybe you misunderstand the original issue. This is when navigating back to a "new" page, not internally in a SPA. But this issue mainly happens when navigating back to a page with dynamic behavior (typically a SPA or other interactive application).