Ultimate Caching Guide 3: Browser/Chrome
Tags: webdev, javascript, programming
Published: 2023-03-07 13:25:44


This article is focused on caching in Chrome Browser. 

* Most of the concepts in this article are applicable to other browsers. 
* Chrome is most used and documented so it is a good place to start.

Caching in Chrome is important for performance and reducing latency, bandwidth and memory. It's also useful for offline functionality.

* Asset/page caching is a major part of Chrome's capabilities, but there are many others you may not know about.
* There are surprising number of obscure ways to cache in Chrome ranging from IndexDB to cookies to Service Workers.
* PWAs (Progressive Web Apps) are a good example of using Service Workers in Chrome for offline functionality. 
* Even other specialized applications like Google AMP (Accelerated Mobile Pages) utilize Chrome's caching capabilities.



Before getting into implementation in Chrome, let's look at the basics of HTTP caching and how you can monitor it in Chrome browser.

#### Ultimate Caching Guide Series

[Ultimate Caching Guide 1: Overview and Strategies](https://dev.to/csjcode/ultimate-caching-guide-1-overview-and-strategies-222h)

[Ultimate Caching Guide 2: Javascript/React](https://dev.to/csjcode/ultimate-caching-guide-2-javascriptreact-2lie)

This is an ongoing series. I have at least 7 planned.


## HTTP Caching and Monitoring Caches in Chrome

### HTTP Caching
* [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)

Some general background about the HTTP caching model, which is the foundation of the browser cache:

* **Heuristic caching**: responses are reused if conditions are met. 
  * Although conditions may be made in the Cache-Control http response header, they are not always enforced. Included are directives like "max-age", "no-cache", "no-store", "must-revalidate", "public", "private" and more.
* **Common header heuristics**:
  * **max-age:** Specifies the maximum age of the resource in seconds. After this time, the resource should be considered stale and a new copy should be fetched from the server.
  * **no-cache:** Instructs the cache to revalidate the resource with the server before using a cached copy.
  * **no-store:** Instructs the cache to not store any copies of the resource at all.
  * **public:** Specifies that the resource can be cached by any cache, including intermediate proxies. 
  * **private:** Specifies that the resource can only be cached by the user's browser and not by any intermediate proxies. 
* Other headers are used to control caching.
    * Vary (properties of the request that can change the response).
    * Validation based other factors such as last modified, ETags, forced revalidation.
* **Private cache**: 
  * Private cache is a cache tied to a specific client, such as the browser. 
* **Shared cache**:  
  * **Proxy (gateway) cache**: a shared cache between clients and servers.
  * **Managed cache**: CDNs, services deployed by developers to offload the origin server and to deliver content efficiently.
* HTTP can use HTTP caching though is complicated by TLS/SSL extra security measures, which may prevent proper caching..

### View Cache Data in Chrome
https://developer.chrome.com/docs/devtools/storage/cache/

* Test if you optimized your page for instant loads when using the browser's back and forward buttons.
* Identify issues that may prevent your page from being eligible for this type of caching
* [Back-Forward Cache](https://developer.chrome.com/docs/devtools/application/back-forward-cache/)
* Also you can use Chrome console commands which you can dig around on to see what's going on with your cache and other settings: https://www.webnots.com/useful-chrome-url-commands/

**Chrome DevTools**
* You can use the DevTools Network tab to monitor requests and responses and see caching information such as cache hits and misses.

Open Chrome Dev Tools with "Ctrl+Shift+I" (Windows, Linux) or "Cmd+Opt+I" (Mac), on the Application tab of you can see the Cache Storage.

![Dev Tools Storage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iqanu0476pdviqo88y2u.png)

**Network Tab**

* Here you can see the cache status of each request.

![Dev Tools Network](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h3d78v0i1q3is3tat38t.png)

* You can also disable the cache, if you want to be sure you are not getting cached data.

![DevTools Disable Cache](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/asycgw9n2p85cs7yzqp4.png)

* You can open dev tools and right click the browser's reload button and select "Empty Cache and Hard Reload"

![Empty Cache and Hard Reload](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g7lkm8t4kyltt0z2o9qr.png)

**Lighthouse**

Open Chrome Dev Tools with "Ctrl+Shift+I" (Windows, Linux) or "Cmd+Opt+I" (Mac) , on the Lighthouse tab of you can analyze your app and get cache -related feedback among other metrics. 

* Lighthouse is an open-source tool that can audit a website's performance, including caching. It provides suggestions for improving caching behavior.
* Serve static assets with an efficient cache policy
* [Long Cache TTL](https://developer.chrome.com/docs/lighthouse/performance/uses-long-cache-ttl/)

![Lighthouse Cache](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/haeceiybw9lqcrd9rmlu.png)

![Lighthouse Service Worker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f2wv8i9hqstjczsosclb.png)


**In Chrome browser url input: chrome://serviceworker-internals**
* This page provides information about registered service workers and their cache storage.


![ServiceWorker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgpkt52jwd7jih47prbf.png)

Other possible ways to checking Caching from the browser:

* **Google Analytics** 
  * Google Analytics can be used to track cache hits and misses by setting up custom events and tracking them in the Analytics dashboard.
* **Chrome extensions:**
  * There are several Chrome extensions available that can provide more detailed information about caching, such as "Cache Killer" and "Clear Cache."
* **Command Line:** 
  * You can use the Chrome command line to view detailed caching information, such as cache size and usage, by running the command "chrome://net-internals/#httpCache" or chrome://net-internals/#dns in the Chrome address bar. [List of shortcuts](https://www.minitool.com/news/chrome-urls.html)


## Types of Caching in Chrome

### Memory Caching /  HTTP (browser) Cache

* Caching that temporarily stores and retrieves web page resources, such as HTML, CSS, JavaScript, and images, in memory for faster access. 
* The Page (browser) Cache may store in memory and/or disk depending on the assets.
* Managed by the browser's networking layer 
* "Ctrl+Shift+I" (Windows, Linux) or "Cmd+Opt+I" (Mac) + NETWORK tab. Click on the "Network" tab.
* Used along with other types of caches like disk and service worker caches.
* When a user visits a website, the browser initiates a request to fetch the web page and its resources. 
* If the resource is not in the memory cache, the browser fetches the resource from the network and stores it in the cache for faster access in the future. 
* The cache uses a Least Recently Used (LRU) algorithm to determine which resources to evict from memory when the cache becomes full.
* Faster than disk-based caches because it doesn't require the time to read and write data to disk.
* Limited size (can be modified by the user) and can quickly fill up with frequently used resources.
* Checks HTTP headers to control cache behavior. For example, the Cache-Control header can be used to set the maximum age of a resource in the cache.

### Disk Caching / HTTP (browser) Cache 

* Website assets, such as HTML files, CSS stylesheets, JavaScript files, images, and other resources, and stores them in the disk cache. 
* When users revisit the site, the browser checks the disk cache to see if the assets are already stored there, and if so, it retrieves them from the cache instead of downloading them again.
* Chrome Disk Cache works in conjunction with the Memory Cache.
* The Chrome Disk Cache uses Least Recently Used (LRU) algorithm to determine which resources to evict from the cache when it becomes full.
* HTTP headers are also used on this like the memory cache.
* Devs could use [LocalStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) for caching as well, and Session Storage may be either in memory or disk.
* [SessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) uses disk caching.
* IndexDB and WebSQL are also disk based.

### Page Cache

The difference of the Page cache and Browser cache is a bit confusing. 

There are 2 different methods in the Chrome API under "chrome.browsingData" to clear each (remove and removeCache). Although the examples given don't specify much of the difference (in the code itself). Some I'm going to leave this section general for now, just noting the difference.

* The Page Cache caches the entire rendered content of a web page, including its HTML, CSS, and JavaScript, as well as any data fetched by the page through APIs or other means. 
* The Page Cache is stored separately from the regular browser cache.
* It's only used for pages that have been visited recently or frequently.

### Back/forward cache 
Back/forward cache differs from browser cache and HTTP cache.

[Back-Forward Cache](https://developer.chrome.com/docs/devtools/application/back-forward-cache/)
  * The Back-Forward Cache is different from the regular browser cache in that it only stores pages that the user has visited during the current browsing session, and it is optimized for quick access to those pages. 
  * It is also different from the Page Cache, which is used to cache pages that are opened from links in new tabs.
* https://developer.mozilla.org/en-US/docs/Web/API/Cache

### Cookies

* Cookies can be used to store data in the browser cache.
* Cookies can be set to expire after a certain time, or  when the browser is closed (session cookie).
* The topic of cookies is covered in more detail here: [Cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) article.

### Service Worker Cache

* Service workers intercept network requests and cache responses in the browser (see code below in Cache Storage API section).
* They can be used offline or on a slow internet connection.
* Steps to implementation:
  * Register a Service Worker using the navigator.serviceWorker.register() method.
  * Implement the caching logic in the fetch event listener of the Service Worker. With an event listener, you can intercept requests made by the browser and cache the responses.
  * Use the Cache API provided by the Service Worker. The Cache API provides methods like cache.addAll() and cache.match() to add and retrieve responses from the cache.
  * You can see Service Workers as listed aboe in the article in Chrome DevTools in the Application panel.
  * Cache versioning and expiration should also be implemented to ensure that the cache is updated when the service worker is updated.

### Web Workers
* Web Workers operate independently of the main thread of the web page
* They use a similar mechanism of caching as the page cache, however this can be customized by the developer.
* Stored in memory cache or disk cache, depending on the size and type of data being cached.
  
### Cache Storage API

[The Cache Storage API](https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage) is a newer API that allows developers to cache network resources programmatically. It provides more control over caching behavior and allows for more advanced caching strategies.

* Caching of HTTP responses: Developers cache HTTP responses.
* Support for different cache strategies.
* Separation of caches: You can create multiple caches with different names, to keep different types of resources separate. For example, create a cache for images and another for scripts.
* Management of cache entries: The API provides methods for adding, retrieving, and deleting cache entries. Developers can also set expiration times for entries or update them if the original resource has changed.
* Programmatic caching: The API allows developers to cache resources programmatically, which can be useful for pre-caching resources that are likely to be needed in the future or for updating the cache in the background.

Example:

```js
// Define the name of the cache
const CACHE_NAME = 'my-static-cache';

// Define the URLs of the files to cache
const urlsToCache = [
  '/',
  '/styles.css',
  '/script.js',
  '/images/logo.png'
];

// Install the service worker and cache the static assets
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => cache.addAll(urlsToCache))
  );
});

// Serve cached files if available, otherwise fetch them from the network
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        if (response) {
          return response;
        }
        return fetch(event.request);
      })
  );
});

```

### Push Cache

* Used for push notifications in Chrome. When a user receives a push notification, Chrome stores the resource in the push cache so that it can be quickly accessed if the user wants to view it.
* Separate from the browser's regular cache and is only available for the lifetime of a single session.
* The server sends the resources along with a PUSH_PROMISE frame to the client, which tells the browser to cache the resources in the Push Cache. 
* The browser then stores the resources in the Push Cache and can retrieve them without making a request to the server.
*  HTTP/2 Push is required to use the Push Cache. 
* Monitor the Push Cache using the Chrome DevTools in the Application tab and select Push Cache. You can also use the Performance panel to see the requests.


### DNS Cache
Chrome stores recently resolved DNS queries in a cache to reduce the time it takes to resolve domain names.

* **DNS prefetching**: 
  * By including the [dns-prefetch ](https://developer.mozilla.org/en-US/docs/Web/HTTP/Link_prefetching_FAQ) link relation in your HTML code, you can instruct the browser to resolve DNS records for a domain in advance, before the user clicks on a link to that domain. This can help reduce latency and improve page load times.

```
<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
  <link rel="dns-prefetch" href="//example.com">
</head>
<body>
  <h1>Welcome to My Website</h1>
  <p>This is an example of how to use the dns-prefetch link tag.</p>
</body>
</html>
```

* Add a dns-prefetch link tag to the head section of the HTML document. 
* The href attribute specifies the domain name we want to pre-resolve, in this case, example.com.
* **preconnect: **This option allows the browser to set up an early connection to a domain before the user requests any resources from it. This can reduce the latency of establishing a new connection and improve page loading speed.
```
<link rel="preconnect" href="https://example.com">
```
* **prefetch:** This option allows the browser to fetch and cache a resource in advance, before the user requests it. This can improve page loading speed by reducing the time it takes to fetch the resource when the user requests it.
* 
```
<link rel="prefetch" href="https://example.com/styles.css">
```
* **prerender:** This option allows the browser to pre-render a web page in the background, before the user requests it. This can improve page loading speed by pre-rendering the page's HTML, CSS, and JavaScript, and making it available immediately when the user requests it. 
```
<link rel="prerender" href="https://example.com/page.html">
```
See more on preconnect, prefetch, and prerender in the [Link prefetching](https://web.dev/preconnect-and-dns-prefetch/).

* **HTTPS and SSL/TLS certificates**: When a user visits a website with a valid SSL/TLS certificate, Chrome will cache the certificate for a certain period of time. This helps to speed up subsequent visits to the same site, as the browser does not need to download the certificate again. However, if the certificate is invalid or has expired, Chrome will not cache it and will require a new certificate to be downloaded.

### Font Cache

The Font Cache is a specialized cache used to store font data. It caches font files downloaded so that they can be reused across different web pages on the same site. This helps improve performance by reducing the number of requests needed to download font files.

### Form Data Cache
* Form data can be saved in local storage and autofilled.

### Plugin caching 
Chrome caches plugin content like Flash and Java to speed up the loading of multimedia content on web pages.

### AMP

AMP (Accelerated Mobile Pages) is not specifically designed for caching, but it does use caching as a key component of its optimization strategy at several levels to speed up the delivery of content on mobile devices. Some of the caching is done by the browser, while other parts are done by the AMP Cache a global Google CDN. 

* AMP uses a service worker to cache the content on the user's device. 
* When a user visits an AMP page, the Chrome browser may display a lightning bolt icon in the address bar, indicating that the page is an AMP page and has been cached by the AMP Cache. 

Other useful pages:
* [Web caching](https://www.mnot.net/cache_docs/)
* [HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)
* [HTTP Caching more, examples](https://web.dev/http-cache/)
* [PWA Caching](https://web.dev/learn/pwa/caching/)
* [Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Cache)
* [Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)
* [Using Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers)
* [Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API)