In the current state of the web, performance plays a quintessential role in a user’s experience. Having a fast and fluid web application has a direct effect on the success of a website’s conversions and traffic.
After all, good performance is all about maintaining users, so keeping them engaged will only lead to positive results in any business venture.
This is where the process of caching yields benefits. If the user’s browser has access to resources that were already retrieved, they are going to have a quicker experience as a result.
This is applicable when a user navigates to a URL that has previously been visited.
However, a more passive approach might be more effective here as even though changes can be made to improve caching, the logistics behind browsers caching process is subject to change in its version updates.
This can result in creating caching improvements that are no longer valid after a few months, essentially nullifying the work that went into it.
Let’s explore this further.
What is the function of the cache in HTTP?
The goal of caching in HTTP is to reduce the need to send requests and responses. Reducing both of these will result in fewer network round-trips as well as reduced network bandwidth requirements
These directives control how the browser interacts with the resources it requests.
Let examine the main directives related to caching.
This setting tells the browser how long it should keep cached data after its initial retrieval.
Typically this is defined in seconds like so:
When specifying a custom amount of seconds in this header, we must be wary of potential updates to those files.
This can cause the user to be interacting with an earlier version of the website.
This is a frequently encountered scenario in tech companies, where the developers push a change to the product and the business side is unable to see the updates.
This results in some confusion between both areas of the company but is easily remedied by clearing the cache of the browser.
And while this situation might seem trivial, I have experienced it many times in different jobs, especially during times of urgency and feature crunch. It can cause a small amount of temporary friction between business and development teams.
These custom headers enable quite a lot of flexibility when it comes to configuring browser cache.
The no-cache directive indicates to the browser that cached versions of the requested resource can not be utilized without checking to see if there has been an updated version of the resource since the initial caching occurred.
Typically, this check is done by using an additional header called an ETag. This is a unique token that helps to differentiate versions of the same resource.
The token will change on the server whenever the resource is updated. If the ETag in the browser is identical to the server then the cached version will be served to the user.
If these tokens don’t match, a fresh version of the resource is downloaded. This process enables the user to get the most up to date version of the assets they are requesting.
The configuration header directive, no-store, acts in a more simplified manner when compared to no-cache. It essentially disallows browsers from storing any versions of resources from returned responses.
The process of downloading the assets every time is undoubtedly inefficient. However this is not without good reason, the use of no-store can help to disallow the storing of personal data/private information.
Some other Cache-Control request options include:
Cache-Control: max-age=<seconds> Cache-Control: max-stale[=<seconds>] Cache-Control: min-fresh=<seconds> Cache-Control: no-cache Cache-Control: no-store Cache-Control: no-transform Cache-Control: only-if-cached
Some other Cache-Control response options include:
Cache-Control: must-revalidate Cache-Control: no-cache Cache-Control: no-store Cache-Control: no-transform Cache-Control: public Cache-Control: private Cache-Control: proxy-revalidate Cache-Control: max-age=<seconds> Cache-Control: s-maxage=<seconds>
The full list of cache headers and their functionality can be found at the MDN docs.
Essentially, Memoization is caching for functions.
This technique is only effective when the function is expected to return the same result. This is also called a pure function.
The Memoization process might look something like this:
- Create references to a function as an input
- Create a cache to hold the result of previous function calls
- Future invocations of that function will return the cached results
- If no cached value exists, call the function and store the returned result in cache
If there is memory available to be used for memoization, then it can be worth implementing in order to eliminate some repeated code execution. It may not worth the extra effort in programs where memory is already sparse.
While it is unlikely that you will use memoization wherever possible in your codebase, there are plenty of 3rd party libraries that can do a much better job for us.
Take, for example, Reselect, which provides redux selector utilities that are not recomputed unless one of its arguments changes.
This is very handy in a Redux based application, as these selectors are constantly used to call upon subsections of data in the applications state.
Having the results of the selectors already computed provides efficiency for more performant web applications.
If you don’t want to use 3rd party libraries and you are optimizing your functions for memoization, just ensure that the functions to be memoized are pure functions.
How long does a website stay cached?
But, surely it can’t store endless amounts of cached data, right? How long does a website actually stay cached?
Well, this very much depends on the browser, settings, and configuration of the HTTP requests and responses.
Typically, browsers reserve a finite amount of disk space to complete a task. If a user stops using the browser completely, the cache can persist indefinitely.
However, if the browser is used occasionally by the user, the stored data will last until the expiration date that was set either by the internal policy of the browser or the configuration of the HTTP headers.
If the user is very active using the browser, the length of time that the cache is stored can be extended to 10 minutes or less.
The process of caching such a small file is too heavy of an operation relative to the value it provides.
The majority of the logic for the user to interact is contained within these assets, so the ability to have them cached will allow the user to interact much faster on subsequent visits to the same page.