Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

History pushState and cache page

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

like image 302
Dave Avatar asked May 18 '14 03:05

Dave


1 Answers

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)

like image 186
dimyG Avatar answered Sep 21 '22 14:09

dimyG