For a time-consuming navigation (implemented in a Python/Flask backend), it's nice to have visual feedbak indicating that the next page is expected to take some time to load, even when it's just quick DIY devops scripting. To achieve this with little technical overhead I have implemented a loading message like so:
<script type="text/javascript">
function loading(){
document.getElementById("loading").style.display = 'block';
document.getElementById("content").style.display = 'none';
}
</script>
<body>
<div id="loading" class="invisible"> <!-- display: none; -->
Loading ...
</div>
<div id="content">
<a href="/time/consuming/service/call" onclick="loading();">Work miracles.</a>
(Kudos to some answers in another SO question ...)
Works like a charm in all browsers for forward navigation, but when using the browser back
button from the target page in (current) Safari or Firefox, I end up with "Loading ...",
because the display: none;
is kept when the page is reloaded from the browser cache.
In Chrome, the browser back button works fine for this case (which may raise a problem
in other use cases when the user would expect to see the page in the state they left it).
So I think I am missing something here. How can I force the back button to load cached code in the state the browser was loading the last page rather than in the state it was left?
Actually the thing I was missing was the so-called "Back/forward cache" or bfcache. As a performance optimization, bfcache stores the full snapshot of a page, incuding the changes done by my litte JavaScript in Safari, but not in Chrome.
It turned out that we can react on bfcache events easily:
<script type="text/javascript">
function loading(){ // replace content by Loading ...
document.getElementById("loading").style.display = 'block';
document.getElementById("content").style.display = 'none';
}
function makeContentVisisble() { // replace Loading ... by content
document.getElementById('loading').style.display = 'none';
document.getElementById('content').style.display = 'block';
}
</script>
<body onpageshow="makeContentVisisble()"> <!-- called on browser back -->
<div id="loading" class="invisible">
Loading ...
</div>
<div id="content">
<a href="/time/consuming/service/call" onclick="loading();">Work miracles.</a>
That way browser back works smoothly (and fast, without page reload from backend) in both Chrome and Safari.
Find more detail about bfcache in this faily current blog from 2020: https://web.dev/bfcache/