Ajax, back button and DOM updates
Asked Answered
O

7

118

If javascript modifies DOM in page A, user navigates to page B and then hits back button to get back to the page A. All modifications to DOM of page A are lost and user is presented with version that was originally retrieved from the server.

It works that way on stackoverflow, reddit and many other popular websites. (try to add test comment to this question, then navigate to different page and hit back button to come back - your comment will be "gone")

This makes sense, yet some websites (apple.com, basecamphq.com etc) are somehow forcing browser to serve user the latest state of the page. (go to http://www.apple.com/ca/search/?q=ipod, click on say Downloads link at the top and then click back button - all DOM updates will be preserved)

where is the inconsistency coming from?

Orpha answered 28/7, 2009 at 17:5 Comment(6)
Interestingly, Apple is remembering the state without modifying the hash.. hmmmRuthanneruthe
Apple looks like they are just manipulating response cachingMariannamarianne
As others have already suggested this is not something related with javascript or ajax. You should remove those tags to get correct answers.Hungarian
The Apple example is poor. If you contract a search area[ex:products], click your link, then press back, the DOM is not preserved. you are looking for a Hash Solution which many have suggested.Mariannamarianne
When I hit the back button, Apple does not remember what page of search results I was on at all. Using IE7. You need a hash solution. See: Facebook.Malcah
I don't understand the Apple example.Innings
P
114

One answer: Among other things, unload events cause the back/forward cache to be invalidated.

Some browsers store the current state of the entire web page in the so-called "bfcache" or "page cache". This allows them to re-render the page very quickly when navigating via the back and forward buttons, and preserves the state of the DOM and all JavaScript variables. However, when a page contains onunload events, those events could potentially put the page into a non-functional state, and so the page is not stored in the bfcache and must be reloaded (but may be loaded from the standard cache) and re-rendered from scratch, including running all onload handlers. When returning to a page via the bfcache, the DOM is kept in its previous state, without needing to fire onload handlers (because the page is already loaded).

Note that the behavior of the bfcache is different from the standard browser cache with regards to Cache-Control and other HTTP headers. In many cases, browsers will cache a page in the bfcache even if it would not otherwise store it in the standard cache.

jQuery automatically attaches an unload event to the window, so unfortunately using jQuery will disqualify your page from being stored in the bfcache for DOM preservation and quick back/forward. [Update: this has been fixed in jQuery 1.4 so that it only applies to IE]

Pontiff answered 28/7, 2009 at 18:37 Comment(13)
you totally nailed it. both, reddit and stackoverflow are using jquery while basecamp and apple are using prototypejs. this pretty much explains everything.Orpha
+1 interesting ( not cross browser though ) the question is far different than when it started...Mariannamarianne
it will be probably cross-browser because I can reproduce it on my Internet Explorer as well. I'm sure every webbrowser with javascript enabled had to deal with this problem anyway. but this is really a mess, when you think about that, back button should always get people to the page that they've seen last with all DOM updates, javascript state etc. developers shouldn't break this by doing something in unload event and if they do, webbrowsers shouldn't try to fix the problem by not using bfcache at all. whole unload event is one big joke. I'm sure 99% of time it's used to patch memory leaks.Orpha
Specifically, IE memory leaks. :) The jQuery unload event also happens to fix a (completely unrelated) bug in Firefox 2. But it's unnecessary for other browsers. dev.jquery.com/ticket/3015 I suppose I've heard of other uses for onunload, like outbound click tracking or saving webapp state, but I've never had a reason to use it myself, and if developers want to make their sites slower and more painful for their users (I hate how navigating back to reddit comment pages resets comment collapsed state), that's their prerogative.Pontiff
In both example pages, the load event fires when I hit back using Google Chrome 3.0. Seems like Chrome has no bfcache? Your examples work as described using FF 3.5. This is very helpful in understanding the problem, thanks. Anyone seen a general solution using jQuery?Retinite
So has anyone ever hacked the jquery framework and removed the unload event it adds.Practical
The unload event is only attached for IE not for firefox and chrome. Latest version of safari preserves the dom state without the dev having to do anything.Practical
I know this an old post - but I don't this answer the question. unload events do not currently invalidate cache, at least in Chrome and Firefox.Vi
@Vi This answer is specifically about the page cache. Unload events still invalidate the page cache in Firefox 28. Chrome 33 still doesn't have a page cache.Pontiff
@Pontiff - look at two examples, both have unload event, and the DOM elements do not retain on back-button. I guess that's what I'm looking for - how to break the "back-button" cache, to force the browser to re-cache a page that has DOM udpates.Vi
related to this: after reloading a page with BFCache, AJAX calls are cached as well (ignoring a max-age=60 header). AJAX content is cached even if user force-reloads (Shift+F5). How can force the browser to reload my AJAX content and still keep the whole page in BFCache? Any specific caching headers I can shoud use?Wilona
Most recent issue related to Chrome is 511340 Investigate faster back/forward page navigationPublus
Seems that Chrome has bfcache as well now web.dev/bfcache/#browser-compatibilityTriplicate
H
17

I've been trying to get Chrome to behave like Safari does, and the only way I've found that works is to set Cache-control: no-store in the headers. This forces the browser to re-fetch the page from the server when the user presses the back button. Not ideal, but better than being shown an out-of-date page.

Hunker answered 20/1, 2013 at 20:25 Comment(1)
This is the correct answer to the original question. If you want to force a server reload on the back-button, use cache-control 'no-store, no-cache, must-revalidate'. Chrome wants no-store, and IE wants must-revalidate. For other browsers (and w3c) no-cache is enough.Hatter
M
3

Facebook remembers page state by modifying the hash identifier in the URL for ajax requests. These changes are recorded in browser history, so when the user clicks the back button, the hash changes to what it was before. So then it is implied that you will need some Javascript to monitor the has identifier and react when it is changed by the browser. Andreas Blixt has a hash monitoring script available.

Malcah answered 28/7, 2009 at 17:20 Comment(1)
as of today it diesn't do so can tell me what facebook does nowYogi
B
3

This has nothing to do with the hash (#) symbol.

If you would check apple's HTTP headers, it's simply caching the page.

Bernabernadene answered 28/7, 2009 at 17:47 Comment(1)
Apple example is poor, they are not "saving" page state, his assumption the DOM is preserved it wrongMariannamarianne
D
2

Using the URL hash/fragment identifier is a pretty common way to hook/remember state in a web application that relies on Ajax and DOM updates.

Check out the Really Simple History project for some ideas. It's possible to monitor the URL for changes to the hash, and rsh does this, taking into account browser differences.

Dulcinea answered 28/7, 2009 at 17:34 Comment(0)
S
1

For anybody running in problems with Rails and this -- your issue isn't bfcache (I thought it was) -- it's the turbolinks gem. Here is how to remove it.

Hopefully this'll save you some time and banging your head against the wall.

Supermarket answered 27/9, 2014 at 14:15 Comment(0)
M
0

What you are looking for is for some type of URL hash management. The # in the url is for client side only.

When you change the state of the back with JS, then you update the data in the # of the url.

Also you add some type of polling that monitors if the hash has changed, and loads the state of the page based off the new data in the hash.

Take a look at this:

http://ajaxpatterns.org/Unique_URLs

Mariannamarianne answered 28/7, 2009 at 17:16 Comment(2)
this has nothing to do with the hash symbol.Bernabernadene
You are wrong, he is looking for the most common way to preserve page state in an AJAX solution.Mariannamarianne

© 2022 - 2024 — McMap. All rights reserved.