Cache Management
Cache management plays an important role in ensuring that Cache Experience is giving your shoppers the best possible performance improvement, while also keeping the caching and cache refreshing processes efficient.
When you are using Cache Experience, the easy part is putting objects into cache. The hard part is knowing when to revalidate resources in cache. With default configurations of Cache Experience (only caching HTML), you will generally only want to manage cache when a user interaction dictates it. User interactions that warrant a cache management action include:
Add to cart
Log in or log out
Price manipulation (loyalty, promo code, size/color change)
Cart manipulation (removing contents, changing contents, price changes)
Selecting physical store location
Geo specific languages
Other shopper actions that change the contents of a page
All of these actions cause previously cached HTML to change. In the following examples, the contents of each pop-up is stored directly in the HTML of the page.
Manipulating anything related to the cart contents can impact the mini-cart.
Changing a log-in state will adjust the header.
Selecting a preferred store will change one or more pages.
If we did not update cache when the above actions occurred, then pages in cache would have the wrong information. For example, a page could show the wrong store, incorrect log-in state, or incorrect cart contents.
Lastly, it is possible that resources are invalid because they have been cached for too long. For example, an image is updated, however a link to an older image is still in the HTML in cache.
Caching Strategies
By default, for time based expirations (outdated image example above), Cache Experience utilizes a stale while revalidate policy. To summarize, stale while revalidate means that Cache Experience will serve a stale object once while simultaneously fetching a new version of the resource from the originating server. The response from the originating server is then placed in cache and thus updated.
It’s worth noting, stale while revalidate is widely used in the industry.
Refresh vs. Remove
When Cache Experience updates cache there are two main methods to do this. These methods are invoked via an API when an action on the page occurs, or specific pages are navigated to.
Refresh: Cache Experience will take a snapshot of all resource URLs in cache and then delete all the resources in cache. Once the resources are deleted, Cache Experience will then, singularly, request each object that was previously in cache.
This is the most performant approach and therefore the recommended approach. This approach ensures latest content is in cache, and most iportantly updated.
Remove: Cache Experience will remove all resources from cache effectively dumping the entire cache.
This approach will effectively remove all resources that were in cache. There is no possibility of a cache hit on any page previously visited.
Revalidate On
Stale while revalidates has obvious advantages, and obvious disadvantages. A major disadvantage is that a resource can be served stale once. To work around this disadvantage, a flag can be set utilizing the Journey Caching dropdown Revalidate On.
Revalidate On means when do we revalidate a request. There are two potential options:
Configured TTL: When the resource in cache exceeds the configured maximum cache duration
Request: Each time that resource is requested AND when the resource in cache exceeds the configured maximum cache duration.
User Interaction Cache Management Methods
Navigation Interaction
When needed, Cache Experience can refresh, or remove, all resources in a given cache when a shopper browses to a particular page.
Sequencing Interaction
A number of the examples stated above discuss user interactions changing the contents of stored pages. If you recall, add to cart will impact the minicart and logging in will impact the header. In these cases, Cache Experience needs to listen for specific requests. When these specific requests occur, a refresh/remove action needs to be taken on the resources in cache to ensure they’re updated.
To listen for specific requests Cache Experience leverages Application Sequencing rules that are normally reserved for performance configurations. These Application Sequencing rules are already listening for requests so it’s easier to piggyback.
Click Interaction
HTML form submissions or anchor tag href clicks can be used to manage the cache. Click interactions are helpful in situations where a particular request, via sequencing interaction, would be the preferred method for cache management however that request is a redirect (HTTP response code 301/302).
In this case, you will need to add custom JavaScript (portal functionality forthcoming), to manage the caches.
Utilizing Chrome Dev Tool’s inspector, you should locate the HTML tag, which is clickable, that will be used for the click interaction. In the below example, the button labeled Sign In is within a form tag.
Custom JavaScript Leveraging Cache Experience APIs
The custom JavaScript that needs to be inserted is below. This script needs to be executed after the tag (form or href), are inserted into the DOM. Generally this happens by core/load. However, in some situations it’s possible the tag is inserted after this event. In those cases, you will need to adjust the pubsub topic to when the tag is created.
The below scripts create an array of all forms or anchor tags that are defined. querySelectorAll is leveraged for simplicity sake. For example, if I wanted to add a new anchor tag click I would change the var aHrefs = document.querySelectorAll('a[href*="LogOut"') line to var aHrefs = document.querySelectorAll('a[href*="LogOut", a[href*="GregClick"]'). Similarly for formsvar forms = document.querySelectorAll('#loginform')would become var forms = document.querySelectorAll('#loginform, .newFormClassName')
Yo.pubsub.subscribe({topic: 'core/load', callback: function(){
// <a href='/foo'>Click Me</a>
// a tag links require click events
var aHrefs = document.querySelectorAll('a[href*="LogOut"')
aHrefs.forEach(function(element){
element.addEventListener("click", function(event){
Yo.utils.log('Removing cache via a click on event: ', event);
Yo.tec.removeResources();
})
})
// <form id='login></form>
// forms require submit event
var forms = document.querySelectorAll('#loginform')
forms.forEach(function(element){
element.addEventListener("submit", function(event){
Yo.utils.log('Removing cache via a click on event: ', event);
Yo.tec.removeResources();
})
})
}})
Verifying Cache Management Rules
Similar to other verification steps, we will utilize Chrome dev tools to verify that the cache management was successful. Go to dev tools → Application → Cache storage.
Refreshing Resources
Browse to a page that should be put into cache according to Journey Caching or Prefetch rules.
Ensure a page is in cache.
Trigger an event that should revalidate the cache in a refresh manner.
Once at cache storage, you will need to look at the column Time Cached. This column should have close to (within seconds) the same time for all resources EXCEPT rapid-worker-cache (this is internal to YOTTAA’s service worker and does not need to be updated). If the Time Cached column is within seconds then the refresh was successful.
Remove Resources
Browse to a page that should be put into cache according to Journey Caching or Prefetch rules.
Ensure a page is in cache.
Trigger an event that should revalidate the cache in a remove manner.
Within the Cache Storage area, ensure only the rapid-worker-cache-configuration exists. All other entries should be removed.
Delete All Caches and Cached Resources
Deleting all the caches, resources in cache, is straightforward. The following JavaScript API can be used to destroy all caches. This API leverages the Rapid Client Library. If a standard deployment, this should be put in the Rapid CTRL configuration, not the service worker.
Note: Yo.serviceWorker.cache.destroyAll();
is the actual API to destroy the cache. In the below JavaScript, it is loading after the page has loaded (via Yottaa’s pubsub mechanism). This is the preferred method to ensure that the service worker is available.
Yo.pubsub.subscribe({ topic: "core/load" , callback: function() {
Yo.serviceWorker.cache.destroyAll();
}});