How to fix Lighthouse’s `bf-cache` rule when “the page has an unload handler in the main frame”
I recently encountered a Lighthouse error for the bf-cache
rule, which is when the “Page prevented back/forward cache restoration” and described with “Many navigations are performed by going back to a previous page, or forwards again. The back/forward cache (bfcache) can speed up these return navigations. Learn more about the bfcache.
The reason for my application was “the page has an unload handler in the main frame,” meaning that a script was calling window.addEventListener('unload', ...)
somewhere in my app. This ended up being to Cloudflare’s Rocket Loader analytics script, and I wasn’t willing to drop the feature in its entirety.
To save the rest of the feature, I needed to prevent unload
event listeners from binding. The solution was a simple hotfix, swapping all unload
event listeners with pagehide
event listeners.
(function(w) {
w.addEventListener = function addEventListenerSpy(type, listener, options) {
if (type === 'unload') {
Window.prototype.addEventListener.call(w, 'pagehide', listener, options);
return;
}
Window.prototype.addEventListener.call(w, type, listener, options);
};
})(window);
By loading this script synchronously, Rocket Loader’s asynchronous instantiation will instead bind its event listeners to the pagehide
event. This solution provides relief, whether bound by Rocket Loader or otherwise.