How to mix AJAXy page updates with the Back button so that the updates are still there when the user returns? How to mix AJAXy page updates with the Back button so that the updates are still there when the user returns? ajax ajax

How to mix AJAXy page updates with the Back button so that the updates are still there when the user returns?


Embedding Google Maps into the page disables the bfcache (I'll use the mozilla term for lack of a standard one) because the maps page loaded in an <iframe> uses an unload listener.

The possible reasons for a page not being cached for fast back navigation in Firefox are listed on MDN: Using Firefox 1.5 caching. Your problem is listed as "the top-level page contains frames that are not cacheable", which is confusing, I'll try to clarify it later. (Other browsers probably use similar heuristics, since these rules were developed to avoid breaking existing content - see also this answer, it has some links.)

The correct way to fix this would be to befriend someone at Google and then nag them until they remove the onunload listener at least from maps' embedded pages.

In general you shouldn't ever rely on bfcache working or not working for a particular page. It's just an optimization for the common case. Since it's an optimization, it could be disabled, for example when the system is low on memory. It also won't work if the user restarts the browser before going back, or closes the tab and picks 'undo close tab', as you noted in the bug.

You should either restore the page's state from JS or mark the page as not cacheable (using an HTTP header). The former results in a better user experience, of course. @Adam Gent's suggestion looks correct, I'll have to check what Firefox problem he refers to.


The reason bfcache works this way is:

  • If the browser runs an onunload handler, then restores the page via bfcache, the page could be broken, since scripts often remove the event listeners in the onunload handler (to "clean up", which is not really necessary except in old IE versions)
  • if the browsers stopped running onunload handlers in a page on the basis that the user might return to the page and they'd like to cache it, the authors would complain.
  • if a page in an iframe can't be cached, restoring a cached outer page and reloading the inner page would break them sometimes (e.g. if both pages are same-domain, the outer page can hold references to objects in the frame, which won't be valid after the inner frame is reloaded). So if an iframe is not cached, neither is the parent page.

The reason the page is still loaded from the (disk) cache when you hit "back" is that presumably you specified that the content you sent to the browser can be cached. The browser has no way to know that you update the page on the server in parallel with making the DOM changes to it.

Hope this helps.


[edit]I'll elaborate on the "mark the page as not cacheable" idea above. To make web browser cache work for, and not against you, it's important to remember that HTTP is a protocol for retrieving resources. For example, the HTML page identified by the URL http://bbb.akshell.com/broken is a resource. When you serve a resource over HTTP you specify how long the browser's copy of the resource will be valid (i.e. matching the canonical version of the resource on the server).

When, as in your testcase, the resource is an HTML page with the item selected by the user marked up in a special way, the resource may change at any time (every time the user changes the selection). This means that the honest HTTP response when serving this resource would be "don't cache, may change at any time". The browser would then reload the page from the server every time it needs to load the page -- correct behavior, but at the cost of slowness for the user.

An alternative approach, appropriate for things like switching between multiple in-page tabs would be to associate each selection with its own URL. A page with two tabs would correspond to two resources (and two URLs) -- one for each tab. Both resources could be (HTTP-)cached by the browser. Changing the URL and the page's content could be implemented without the roundtrip to the server via pushState.

Another approach, which seems more applicable to your case, in which you save the user's input on the server: separate the app UI and the user's data into different resources (i.e. a static (HTTP-)cacheable HTML page with JS, loading the user data from a separate non-cacheable URL). Request the user data and update the UI on load.[/edit]


If you don't care about old browsers you could use a combination of local storage and pushstate.

Using @lucian.pantelimon 's solution + pushstate + localstorage should get you what you want.

<script>window.addEventListener("popstate", function(e) {    alert("hello"); // do my restoration from localstorage.});</script>

@TimWi is right that if the browser doesn't fire an event your kind of "up shit creek".

One thing you might want to investigate is a truly gross hack of a frameset (ala reddit/google images/linkedin article style).

EDIT: Looks like the pushstate events don't get fired off when the back button is pressed on a remote site back to your site.

EDIT 2: It looks like my firefox v 10.0 has problems with pushstate. It works fine in chrome.


This trick will clear bfcache for FireFox:

   window.onunload = function(){}