6

How to cache page loaded via ajax with pushState URL so that reloading page from server can be avoided? For instance,

page 1: /foo.html. click button, send ajax request, get response and update the page. History pushState as a new page /bar.html.

   history.pushState({}, '','/bar.html');

At this point, we like the browser to cache the current page as /bar.html.

window.onpopstate = function(event) {
  // browser is not loading page automatically for back/forward
  if (event.state)
    location.reload();
};

When clicking back/forward button, the /bar.html should be loaded from browser cache. But it is loaded from server again. How to achieve this? that is, let the ajax updated page treated as regular GET /bar.html, and cached by browser. how?

Thanks for any clue. Dave

Dave
  • 487
  • 1
  • 6
  • 19
  • _“How to achieve this?”_ – the same way you would achieve it, were AJAX and pushState not involved at all. – CBroe May 18 '14 at 03:06
  • how to tell browser to cache it as new URL? Thanks. – Dave May 18 '14 at 03:38
  • 1
    You simply make your AJAX request again when the user navigates to that history entry again – and if you have implemented proper caching, then the browser will take the data from cache instead of requesting it again. – CBroe May 18 '14 at 03:43
  • set response header Cache-Control: max-age=86400. Chrome/FireFox browser does not cache it. onpopstate: location.reload() always requests the page again from server. – Dave May 18 '14 at 05:10
  • Well that’s kinda what `location.reload()` does in reality … but who said anything about using that method in the first place? – CBroe May 18 '14 at 05:19
  • window.onpopstate = function(event) { if (event.state) location.reload(); }; Reload page for browser back/forward button. What is the correct way of doing it? Thanks. – Dave May 18 '14 at 05:46
  • And _why_ exactly would you do that …? – CBroe May 18 '14 at 05:47
  • Without the onpopstate, the browser will not load the page automatically for back/forward. – Dave May 18 '14 at 05:49
  • 1
    When using the History API, you have to handle what content gets displayed when the user navigates back and forth, that is correct. But nobody is forcing you to do that by _reloading_ the page … You used AJAX already to fetch the content and then put it into the DOM, right? So what is keeping you from doing _exactly that_ again (and thereby making use of the browser’s cache, when it will realize, “hey, I have already loaded that content once before already, so I don’t have to make a new HTTP request here, but I can _answer_ that AJAX request by taking the data out of my cache”) …? – CBroe May 18 '14 at 05:53
  • making use of the browser’s cache? do you mean the browser page caching or web storage in html 5? If the stateObject keeps the ajax response, it still needs the base DOM to update. Where to keep the base DOM? actually need to keep the whole DOM after ajax update somewhere. – Dave May 18 '14 at 06:03
  • _“making use of the browser’s cache?”_ – well isn’t that what your question is all about? I am talking about the “normal” browser cache for HTTP requests here (as were you before already, with `Cache-Control` header etcetera). And the DOM for the content loaded via AJAX you will automatically get when _making_ that AJAX request – _again_ … so where’s the actual problem here? – CBroe May 18 '14 at 06:07
  • I edited the post and hope it is easier to understand the issue. – Dave May 18 '14 at 06:18
  • Not really. And the comment `// browser is not loading page automatically for back/forward` makes it even more unclear – well isn’t that _why_ you are using the History API in the first place? If you just want the browser to load pages “normally” – then why use the History API, why use AJAX …? – CBroe May 18 '14 at 06:23
  • the best way is to load from browser cache, not from server. I do not know how to make browse cache it as a regular page(GET). – Dave May 18 '14 at 14:42
  • Mostly by setting appropriate HTTP headers regarding cache behavior – so do some research on that. – CBroe May 18 '14 at 18:11
  • @CBroe I think you might be missing Dave's point. I asked a similar question here: http://stackoverflow.com/questions/27356774/is-pushstate-inferior-to-hashbangs-when-it-comes-to-caching , I may be misunderstanding Dave though. – Hello World Dec 08 '14 at 12:00

1 Answers1

5

If you enable http caching adding the appropriate headers in your responses (Cache-Control, Expires, Last-Modified etc.) then these responses will be stored in cache. There is not one cache. There is the server's cache and downstream caches (ISP, proxies, browser). One of these is the browser's cache.

Suppose that you cache the responses. Have in mind that an http response will be cached no matter its content-type (html, json etc.) So, you load page A, then click on a link that updates the page with ajax and the url with the history api. This is page B. Then you visit page C. The responses A, B and C are stored in browser's cache. But if you go back to page B the browser doesn't automatically load it since you have used the History api for that url. It just updates the url and fires a popstate event.

  1. One approach is to listen to popstate and manually make the same ajax call. Since the response B is already stored in browser's cache, it will be retrieved from there (if it has not been changed in the server).
  2. Another approach would be to store the data retrieved from ajax in an object called state and associate it with the pushed url:

    state = { your_key: your_value }
    history.pushState(state, title, url)
    

    Then on back button catch the popstate event, get its associated state object, access your data and modify the page.

    $(window).on('popstate', function(event) { 
       var state = event.originalEvent.state; 
       if (state) { 
          // use it to modify the page 
       }else{ 
          // ajax call to get the data 
       }
    });
    

    In this case if state exists you don't actually use the browser's cache to retrieve the response.

Have in mind that the state object is stored in client's disk and is of limited size. Thus it is better to store in the state object a reference to the data (for example an id) and store the data itself in memory. This assumes though that you have a Signle Page Application all pages of which are loaded with ajax. (A normal page loading will clear your client's memory)

dimyG
  • 687
  • 9
  • 19