JavaScript functions do not rerun when returning to page due to bfcache in Chrome
Describe the current behavior
JavaScript functions intended to run once per page load are cached by the browser. When you navigate away from the page and then come back, the function does not run again. Instead, it retains only the last computed value or state from the previous run.
<div class="animate">Hello World</div>
{% javascript %}
document.addEventListener('DOMContentLoaded', function() {
const element = document.querySelector('.animate');
element.classList.add('move');
});
{% endjavascript %}
{% stylesheet %}
.animate {
display: inline-block;
transition: transform 0.3s ease-in-out;
}
.animate.move {
transform: translateX(300px);
}
{% endstylesheet %}
When navigating away from the page and then returning, the function does not run again, and only the last state from the previous run is shown.
Expected behavior
The function should rerun whenever the user returns to the page, rather than relying on workarounds such as:
window.addEventListener("pageshow", (event) => {
if (event.persisted) {
myFunction();
} else {
myFunction();
}
});
Screenshots / Video
Environment
- Browser(s): Google Chrome Version 142.0.7444.162
- Device: Desktop
- OS: macOS 15.6.1
Additional context
We have seen similar problems, for instance in the Dawn theme, where users have been using hacks to update their cart. Why does Shopify have a hard time with bfcache? We don’t see this problem in other frameworks.
- [x] @134037051
Thank you for sharing this context, @Liam-hi!
When we use the {% javascript %} tag in a snippet, as shown in the example below, the JavaScript code will load in a URL like https://store.myshopify.com/cdn/shop/t/123/compiled_assets/snippet-scripts.js.
Snippet
{% javascript %}
console.log("Example")
{% endjavascript %}
Inside that snippet-scripts.js file, we have an immediately invoked function, as illustrated below, which clarifies the need for the workaround mentioned earlier:
(function () {
console.log("Example");
})();
Your proposal for a different life-cycle is intriguing, and it could be feasible by implementing something like {% javascript on: "pageshow" %}, extending the tag's behavior. However, we can't just change how the JavaScript is loaded, as that would affect existing users who rely on the current behavior of the {% javascript %} tag.
With that in mind, is there anything else in the {% javascript %} tag that you would like to see differently? This might help us identify other key points developers feel are missing in that tag, and we may revisit it with even more context.
Thank you.