Hacker News new | ask | show | jobs
by mixonic 3554 days ago
Author here, happy this popped up and to see the HN community thinking through it. A few people have brushed off what I sketched as uninteresting and don't see any issues. I'll try to explain it another way (with three years reflection to help).

Single page applications are now quite popular. Most single page apps use a different definition of "back" than browsers do, and there are times when the two treatments conflict.

Many, or most, use a local in-memory database to keep track of information without going to the server. They update that in-memory store as you make changes. For example you see a list of names: Mary, Robert, John. You click Robert and edit the name to "Rob", the name auto-saves. Then you click "back".

Because single-page apps control "back" when in the SPA, they do what most developers want. They return to a semantically correct page, showing Mary, Rob (just edited), John. Tons of apps do this. This is not what the browser does. The browser, if following the "back" specs, would show the out-of-date names of Mary, Robert, and John.

The theoretical conflict can also become practical. Think through this flow:

* Visit /names

* AJAX for GET /api/names

* See Mary, Robert, John

* Edit Robert's name to Bob, autosave

* AJAX for POST /api/name/4 with the new name Bob

* See Mary, Bob, John

* Click on a link, lets say to Mary's website URL

* Mary's website, new domain, loads.

* ...click back

The SPA loads up, and attempts to GET /api/names. However, the bfcache is at play since the native "back" behavior is running. So the stale API response, with the original names Mary, Robert, John is returned. The list of names on the screen is DIFFERENT than what the user saw after they edited.

Additionally most SPA apps presume AJAX calls return accurate data, however here the names are not the names currently in the database. They are only in the bfcache. You can imagine, with more complex data, ways this can cause complex and unforeseen failures.

This is a very poorly understood corner of JavaScript development even today.

[edit]: formatting

3 comments

> So the stale API response, with the original names Mary, Robert, John is returned.

This seems like a bug -- if you click back, it should take you to the page you saw before, not an earlier version of it.

AIUI the bfcache doesn't "remember and replay" API requests; it just caches the entire DOM and JS state.

Do you have something that can demonstrate this behavior?

> Because single-page apps control "back" when in the SPA, they do what most developers want. They return to a semantically correct page, showing Mary, Rob (just edited), John. Tons of apps do this. This is not what the browser does.

This is not necessarily what users want (as evidenced by discussions on this post). Many people want the old page, especially if there's information there (form fields, or other state) that might have gotten lost by a misclick. As someone else noted here, the "back = reload page" behavior can be emulated in the bfcache world by back+reload, but if you don't have a bfcache you can't emulate the "don't lose state" behavior that the bfcache gets you.

It seems like a new meaning is being shoehorned into the "back" button, and then you're complaining it doesn't work.

Sorry :-( You are correct. What I described is not be behavior of the bfcache, it is the network behavior described under the heading "In practice". And there is a link there to a server that can help you play with the behavior.

Apologies for using the wrong term and causing confusion.

> This is not necessarily what users want (as evidenced by discussions on this post).

HN not being representative of an average user aside, I don't disagree. My point is that there are two different expectations of what should happen and they can conflict and cause errors.

> you're complaining it doesn't work

I'm really sad you got that impression. I'm fascinated and think this an architectural problem of the web. My post is an attempt to describe the issue and raise awareness.

>it is the network behavior described under the heading "In practice". And there is a link there to a server that can help you play with the behavior.

Right, except requests aren't being made there, it's just that the devtools seem to say that they are. The scenario you gave as an example (with the /names API call and whatnot) isn't possible AFAICT. Maybe I misread something?

> My point is that there are two different expectations

Yeah, agreed, there are two expectations here.

APIs that let you explicitly invalidate bfcache entries (something on pushState() maybe?) or detect bfcache loads would be interesting, and would let SPAs deal with this problem, perhaps.

What you describe does not sound like bfcache behavior. Bfcache should make it like you never clicked the link, and create no requests. Did you test this? Is something broken?

Separately, do browsers currently return expired data to AJAX calls? Which ones?

As mentioned in response to the other comment here, I was in error to use the term "bfcache". Yes, servers cache AJAX calls, this is described under the section "In practice" and there is a link to a server that can you use to replicate the behavior locally, probably in Chrome.
> Most single page apps use a different definition of "back" than browsers do

That's because SPAs are, at heart, an abuse of the Web and of the power Web browsers offer. They are to the Web what a text editor written in Brainf*ck would be: an abuse of extensibility, rather than of Turing completeness.