How to Go Go Forward One Page Again Aftr Going Back a Page Android
Back/forward cache
Optimize your pages for instant loads when using the browser'southward dorsum and forward buttons.
— Updated
Dorsum/forward cache (or bfcache) is a browser optimization that enables instant back and forward navigation. It significantly improves the browsing experience for users—especially those with slower networks or devices.
As web developers, it's critical to sympathize how to optimize your pages for bfcache beyond all browsers, and then your users can reap the benefits.
Browser compatibility #
bfcache has been supported in both Firefox and Safari for many years, beyond desktop and mobile.
Starting in version 86, Chrome enabled bfcache for cross-site navigations on Android for a small percent of users. In subsequent releases, additional support slowly rolled out. Since version 96, bfcache is enabled for all Chrome users across desktop and mobile.
bfcache nuts #
bfcache is an in-retention cache that stores a complete snapshot of a page (including the JavaScript heap) as the user is navigating away. With the entire page in memory, the browser can rapidly and easily restore information technology if the user decides to return.
How many times have you lot visited a website and clicked a link to go to some other page, only to realize it'southward not what you wanted and click the dorsum push? In that moment, bfcache can make a big departure in how fast the previous folio loads:
| Without bfcache enabled | A new asking is initiated to load the previous folio, and, depending on how well that page has been optimized for repeat visits, the browser might take to re-download, re-parse, and re-execute some (or all) of resources information technology just downloaded. |
| With bfcache enabled | Loading the previous page is essentially instant, because the entire page tin be restored from memory, without having to go to the network at all |
Cheque out this video of bfcache in action to empathise the speed up it can bring to navigations:
In the video above, the example with bfcache is quite a bit faster than the example without information technology.
bfcache not only speeds up navigation, it besides reduces information usage, since resources do non take to be downloaded again.
Chrome usage data shows that one in ten navigations on desktop and 1 in five on mobile are either dorsum or forrard. With bfcache enabled, browsers could eliminate the data transfer and time spent loading for billions of web pages every single day!
How the "cache" works #
The "cache" used past bfcache is unlike from the HTTP enshroud (which is also useful in speeding upwards repeat navigations). The bfcache is a snapshot of the entire page in memory (including the JavaScript heap), whereas the HTTP cache contains only the responses for previously made requests. Since it's quite rare that all requests required to load a page can be fulfilled from the HTTP enshroud, repeat visits using bfcache restores are always faster than even the most well-optimized non-bfcache navigations.
Creating a snapshot of a page in memory, however, involves some complication in terms of how all-time to preserve in-progress lawmaking. For instance, how exercise y'all handle setTimeout() calls where the timeout is reached while the page is in the bfcache?
The answer is that browsers suspension running any awaiting timers or unresolved promises—essentially all pending tasks in the JavaScript task queues—and resume processing tasks when (or if) the folio is restored from the bfcache.
In some cases this is fairly low-risk (for example, timeouts or promises), but in other cases it might lead to very confusing or unexpected behavior. For example, if the browser pauses a task that's required equally role of an IndexedDB transaction, information technology tin affect other open tabs in the same origin (since the same IndexedDB databases can be accessed past multiple tabs simultaneously). As a effect, browsers volition by and large not attempt to enshroud pages in the middle of an IndexedDB transaction or using APIs that might touch on other pages.
For more details on how diverse API usage affects a page'southward bfcache eligibility, see Optimize your pages for bfcache below.
APIs to detect bfcache #
While bfcache is an optimization that browsers practice automatically, it's still important for developers to know when it'due south happening so they can optimize their pages for it and adjust whatsoever metrics or functioning measurement accordingly.
The principal events used to notice bfcache are the page transition events—pageshow and pagehide—which have been around every bit long every bit bfcache has and are supported in pretty much all browsers in employ today.
The newer Page Lifecycle events—freeze and resume—are also dispatched when pages go in or out of the bfcache, likewise as in another situations. For instance when a background tab gets frozen to minimize CPU usage. Note, the Page Lifecycle events are currently only supported in Chromium-based browsers.
Discover when a folio is restored from bfcache #
The pageshow event fires right after the load result when the page is initially loading and any time the page is restored from bfcache. The pageshow event has a persisted holding which volition be true if the page was restored from bfcache (and false if not). You lot can utilize the persisted property to distinguish regular page loads from bfcache restores. For example:
window. addEventListener ( 'pageshow' , ( outcome ) => {
if (event.persisted) {
panel. log ( 'This page was restored from the bfcache.' ) ;
} else {
console. log ( 'This page was loaded normally.' ) ;
}
} ) ; In browsers that support the Page Lifecycle API, the resume effect will besides burn down when pages are restored from bfcache (immediately before the pageshow outcome), though it will also fire when a user revisits a frozen groundwork tab. If you want to restore a page's state later on it'southward frozen (which includes pages in the bfcache), you lot can apply the resume event, but if y'all desire to measure your site's bfcache hitting rate, you'd need to use the pageshow event. In some cases, y'all might need to use both.
Observe when a page is entering bfcache #
The pagehide event is the counterpart to the pageshow event. The pageshow event fires when a page is either loaded normally or restored from the bfcache. The pagehide event fires when the page is either unloaded normally or when the browser attempts to put it into the bfcache.
The pagehide event also has a persisted property, and if it's false then you tin be confident a page is non about to enter the bfcache. Yet, if the persisted belongings is true, it doesn't guarantee that a page will be cached. It means that the browser intends to enshroud the page, only there may exist factors that make it impossible to enshroud.
window. addEventListener ( 'pagehide' , ( event ) => {
if (result.persisted === true ) {
console. log ( 'This page *might* be inbound the bfcache.' ) ;
} else {
console. log ( 'This page will unload unremarkably and be discarded.' ) ;
}
} ) ; Similarly, the freeze issue volition burn immediately after the pagehide consequence (if the event's persisted property is true), but once more that merely means the browser intends to enshroud the folio. Information technology may withal have to discard it for a number of reasons explained beneath.
Optimize your pages for bfcache #
Not all pages become stored in bfcache, and even when a page does get stored at that place, it won't stay there indefinitely. It'due south critical that developers understand what makes pages eligible (and ineligible) for bfcache to maximize their cache-hit rates.
The following sections outline the all-time practices to make it as likely as possible that the browser can cache your pages.
Never utilise the unload effect #
The near important way to optimize for bfcache in all browsers is to never use the unload event. Ever!
The unload issue is problematic for browsers considering it predates bfcache and many pages on the cyberspace operate under the (reasonable) assumption that a page volition non go along to exist after the unload event has fired. This presents a challenge because many of those pages were also built with the supposition that the unload event would fire whatever time a user is navigating away, which is no longer true (and hasn't been true for a long fourth dimension).
Then browsers are faced with a dilemma, they have to choose between something that can improve the user experience—simply might too risk breaking the page.
Chrome and Firefox have chosen to make pages ineligible for bfcache if they add an unload listener, which is less risky but also disqualifies a lot of pages. Safari volition attempt to cache some pages with an unload outcome listener, simply to reduce potential breakage information technology will not run the unload issue when a user is navigating away, which makes the upshot very unreliable.
Instead of using the unload issue, utilise the pagehide event. The pagehide event fires in all cases where the unload event currently fires, and it also fires when a folio is put in the bfcache.
In fact, Lighthouse v6.2.0 has added a no-unload-listeners audit, which will warn developers if any JavaScript on their pages (including that from third-political party libraries) adds an unload event listener.
Only add beforeunload listeners conditionally #
The beforeunload result volition not make your pages ineligible for bfcache in Chrome or Safari, but it will brand them ineligible in Firefox, so avoid using it unless admittedly necessary.
Dissimilar the unload effect, nevertheless, in that location are legitimate uses for beforeunload. For instance, when you desire to warn the user that they have unsaved changes they'll lose if they leave the page. In this case, it's recommended that you simply add beforeunload listeners when a user has unsaved changes so remove them immediately afterwards the unsaved changes are saved.
Don't
window. addEventListener ( 'beforeunload' , ( outcome ) => {
if ( pageHasUnsavedChanges ( ) ) {
result. preventDefault ( ) ;
return outcome.returnValue = 'Are yous sure y'all want to leave?' ;
}
} ) ; The code above adds a beforeunload listener unconditionally.
Do
part beforeUnloadListener ( event ) {
event. preventDefault ( ) ;
return effect.returnValue = 'Are yous sure you want to leave?' ;
} ; // A office that invokes a callback when the page has unsaved changes.
onPageHasUnsavedChanges ( ( ) => {
window. addEventListener ( 'beforeunload' , beforeUnloadListener) ;
} ) ;
// A function that invokes a callback when the page's unsaved changes are resolved.
onAllChangesSaved ( ( ) => {
window. removeEventListener ( 'beforeunload' , beforeUnloadListener) ;
} ) ;
The code above simply adds the beforeunload listener when it'due south needed (and removes information technology when information technology'due south non).
Avoid window.opener references #
In some browsers (including Chromium-based browsers) if a page was opened using window.open() or (in Chromium-based browsers prior to version 88) from a link with target=_blank—without specifying rel="noopener"—then the opening folio will take a reference to the window object of the opened page.
In addition to beingness a security hazard, a page with a non-null window.opener reference cannot safely exist put into the bfcache because that could suspension any pages attempting to access information technology.
As a result, information technology's best to avert creating window.opener references past using rel="noopener" whenever possible. If your site requires opening a window and controlling it through window.postMessage() or directly referencing the window object, neither the opened window nor the opener volition be eligible for bfcache.
Always close open up connections earlier the user navigates abroad #
As mentioned to a higher place, when a folio is put into the bfcache all scheduled JavaScript tasks are paused and then resumed when the page is taken out of the cache.
If these scheduled JavaScript tasks are merely accessing DOM APIs—or other APIs isolated to just the current page—then pausing these tasks while the page is non visible to the user is not going to cause whatsoever problems.
However, if these tasks are continued to APIs that are as well attainable from other pages in the aforementioned origin (for instance: IndexedDB, Spider web Locks, WebSockets, etc.) this can exist problematic because pausing these tasks may prevent code in other tabs from running.
Equally a result, some browsers will not attempt to put a folio in bfcache in the following scenarios:
- Pages with an open IndexedDB connection
- Pages with in-progress fetch() or XMLHttpRequest
- Pages with an open WebSocket or WebRTC connection
If your page is using whatever of these APIs, information technology's best to always close connections and remove or disconnect observers during the pagehide or freeze event. That volition allow the browser to safely enshroud the page without the risk of information technology affecting other open up tabs.
So, if the page is restored from the bfcache, you lot can re-open or re-connect to those APIs (in the pageshow or resume event).
The post-obit example shows how to ensure your pages are eligible for bfcache when using IndexedDB by endmost an open connection in the pagehide event listener:
let dbPromise;
office openDB ( ) {
if ( !dbPromise) {
dbPromise = new Promise ( ( resolve, reject ) => {
const req = indexedDB. open ( 'my-db' , one ) ;
req. onupgradeneeded = ( ) => req.issue. createObjectStore ( 'keyval' ) ;
req. onerror = ( ) => pass up (req.fault) ;
req. onsuccess = ( ) => resolve (req.result) ;
} ) ;
}
render dbPromise;
} // Shut the connection to the database when the user is leaving.
window. addEventListener ( 'pagehide' , ( ) => {
if (dbPromise) {
dbPromise. then ( db => db. shut ( ) ) ;
dbPromise = null ;
}
} ) ;
// Open the connection when the folio is loaded or restored from bfcache.
window. addEventListener ( 'pageshow' , ( ) => openDB ( ) ) ;
Update stale or sensitive data after bfcache restore #
If your site keeps user state—especially any sensitive user data—that data needs to be updated or cleared after a page is restored from bfcache.
For example, if a user navigates to a checkout page and then updates their shopping cart, a back navigation could potentially surface out-of-date information if a stale folio is restored from bfcache.
Another, more critical instance is if a user signs out of a site on a public computer and the next user clicks the back button. This could potentially expose individual data that the user assumed was cleared when they logged out.
To avoid situations similar this, information technology's good to always update the folio subsequently a pageshow event if issue.persisted is true.
The post-obit code checks for the presence of a site-specific cookie in the pageshow event and reloads if the cookie is non found:
window. addEventListener ( 'pageshow' , ( upshot ) => {
if (result.persisted && !certificate.cookie. lucifer ( / my-cookie / ) ) {
// Strength a reload if the user has logged out.
location. reload ( ) ;
}
} ) ; Test to ensure your pages are cacheable #
Chrome DevTools tin can help you test your pages to ensure they're optimized for bfcache, and place whatsoever problems that may exist preventing them from being eligible.
To test a particular page, navigate to it in Chrome and so in DevTools go to Application > Back-forrard Cache. Next click the Run Test button and DevTools will attempt to navigate away and back to make up one's mind whether the page could exist restored from bfcache.
If successful, the panel volition study "Restored from back-forwards cache":
If unsuccessful, the panel volition indicate the page was not restored and list the reason why. If the reason is something you every bit a developer can address, that volition also be indicated:
In the screenshot higher up, the utilize of an unload event listener is preventing the page from beingness eligible for bfcache. You tin can fix that by switching from unload to using pagehide instead:
Don't
window. addEventListener ( 'unload' , ... ) ; Do
window. addEventListener ( 'pagehide' , ... ) ; How bfcache affects analytics and operation measurement #
If you runway visits to your site with an analytics tool, y'all will probable notice a decrease in the total number of pageviews reported every bit Chrome continues to enable bfcache for more users.
In fact, you're likely already underreporting pageviews from other browsers that implement bfcache since most of the pop analytics libraries do not track bfcache restores as new pageviews.
If you don't desire your pageview counts to go downward due to Chrome enabling bfcache, yous tin can report bfcache restores every bit pageviews (recommended) by listening to the pageshow consequence and checking the persisted property.
The following case shows how to exercise this with Google Analytics; the logic should be like for other analytics tools:
// Send a pageview when the page is first loaded.
gtag ( 'upshot' , 'page_view' ) ; window. addEventListener ( 'pageshow' , ( outcome ) => {
if (event.persisted === true ) {
// Ship another pageview if the folio is restored from bfcache.
gtag ( 'upshot' , 'page_view' ) ;
}
} ) ;
Functioning measurement #
bfcache can also negatively affect functioning metrics collected in the field, specifically metrics that measure page load times.
Since bfcache navigations restore an existing folio rather than initiate a new page load, the total number of page loads collected will decrease when bfcache is enabled. What'southward critical, though, is that the page loads beingness replaced by bfcache restores would likely have been some of the fastest page loads in your dataset. This is because back and forrad navigations, by definition, are repeat visits, and repeat page loads are more often than not faster than page loads from get-go fourth dimension visitors (due to HTTP caching, as mentioned earlier).
The upshot is fewer fast page loads in your dataset, which will likely skew the distribution slower—despite the fact that the operation experienced by the user has probably improved!
There are a few means to deal with this event. I is to comment all page load metrics with their corresponding navigation type: navigate, reload, back_forward, or prerender. This will let y'all to go on to monitor your operation within these navigation types—even if the overall distribution skews negative. This arroyo is recommended for not-user-centric page load metrics similar Time to Showtime Byte (TTFB).
For user-centric metrics similar the Core Web Vitals, a better selection is to study a value that more accurately represents what the user experiences.
Bear upon on Core Spider web Vitals #
Cadre Web Vitals measure the user's feel of a web folio beyond a variety of dimensions (loading speed, interactivity, visual stability), and since users experience bfcache restores as faster navigations than traditional page loads, information technology's important that the Core Web Vitals metrics reflect this. After all, a user doesn't care whether or non bfcache was enabled, they but care that the navigation was fast!
Tools similar the Chrome User Experience Written report, that collect and report on the Cadre Spider web Vitals metrics treat bfcache restores every bit separate page visits in their dataset.
And while in that location aren't (all the same) defended web operation APIs for measuring these metrics after bfcache restores, their values tin be approximated using existing web APIs.
- For Largest Contentful Pigment (LCP), you tin can use the delta between the
pageshowconsequence's timestamp and the timestamp of the next painted frame (since all elements in the frame volition be painted at the aforementioned time). Notation that in the case of a bfcache restore, LCP and FCP will be the same. - For First Input Filibuster (FID), you lot can re-add the issue listeners (the same ones used by the FID polyfill) in the
pageshowevent, and report FID as the delay of the beginning input after the bfcache restore. - For Cumulative Layout Shift (CLS), you can continue to proceed using your existing Performance Observer; all you take to do is reset the current CLS value to 0.
For more details on how bfcache affects each metric, refer to the individual Cadre Web Vitals metric guides pages. And for a specific example of how to implement bfcache versions of these metrics in code, refer to the PR adding them to the web-vitals JS library.
Additional Resource #
- Firefox Caching (bfcache in Firefox)
- Page Enshroud (bfcache in Safari)
- Dorsum/forward cache: web exposed behavior (bfcache differences across browsers)
- bfcache tester (examination how dissimilar APIs and events bear upon bfcache in browsers)
Terminal updated: — Improve article
Return to all articles
kendricksooreaver.blogspot.com
Source: https://web.dev/bfcache/
0 Response to "How to Go Go Forward One Page Again Aftr Going Back a Page Android"
ارسال یک نظر