Cache issues with Forwards and Back history in Safari

Posted by: Alex on February 27, 2019

Safari has this neat feature in that it saves the page exactly as it was when it was left by the user, so that if you go backwards or forwards to it using the browser buttons (or shortcuts) it doesn’t have to reload the page and instead it can load the saved snapshot state.

This creates a super smooth feeling when jumping back and forth between sites in your back or forward history, however, it’s not necessarily the experience that users always expect.
One common situation is with hamburger/drop-down menus, leaving a site whilst the menu is open means that if you go back/forwards to the site it still remains open, most users would expect the menu to be closed like when you first load a site.

As a side note it’s worth mentioning that Firefox also uses this caching behaviour in most circumstances, so the solutions we provide also work for Firefox back button history caching issues.

Now, why are we discussing this, well it was a long rabbit hole of a development issue, on one of our client’s sites we wanted to ensure a few of the features and settings of the site reset when the user used the back button in their Safari browser. This proved particularly difficult to solve. We tested all types of JavaScript event methods, from window.onbeforeunload, window.unload, document.visibilitychange, window.onpopstate events, through to .htaccess configs to try and create a solution.

Eventually, after several hours, we managed to create a reliable solution using a combination of the pageshow and pagehide events.
However, like most things in web development and coding—that wasn’t the end, we had only been testing in iOS 10.3+ and when it came to testing in iOS 9.3 the issue remained, in that the site wasn’t resetting as we hoped. With fingernails firmly dug into our scalps we continued investigating.

We began testing a bunch of other sites to see if they had this issue, and surprisingly most sites had this quirk, here’s the Reddit website, for example, the menu stays open when using an iPad’s back/forward buttons on iOS 9.3:

Finally, we found a site that had the behaviour we were expecting and began trying to figure how it was accomplished, a complete local copy of the example working site was made. For the most part our local version was exactly the same, however, when testing it still had the issue!

Positively bald and exhausted by now we were at the end of our tether for such a small issue, thinking there must be some kind of clever server-side logic happening we began adding some no-cache headers and other bits to tell the browser not to cache the site (mostly just to test for the moment), still no luck. It was then we ruled out the only remaining difference we could think of… the live example site that was working was running on HTTPS, we installed a local SSL certificate for our mirror of the example site and.. it worked!

So to cut a long story short, enabling HTTPS, along with the following JS events solve forward-back-cache issues in Safari (tested in iOS 9.3 and up) and Firefox too.

function unloadingWebsite() {
    // Do something just before the user leaves:
    // Eg: Hide/close your menu/reset settings/clear cookies etc, whatever you need to do.
    document.body.classList.add("unloaded");
}
window.addEventListener("pagehide", function() {
    unloadingWebsite();
});
window.addEventListener("pageshow", function() {
    // You can use the pageshow function if required to double ensure that everything is reset on the page load.
    // Most of the time the "pagehide" event will provide the solution.
    unloadingWebsite();
});

Just fill the unloadingWebsite() function with the code that should run to set the website back to standard.