From: sailing in the waves jianshu.com/p/54cc04190…

One, foreword

Caching is a simple and efficient way to optimize performance. A good caching strategy can shorten the distance of web page request resources, reduce latency, and reduce bandwidth and network load because cached files can be reused.

For a data request, it can be divided into three steps: initiating a network request, back-end processing and browser response. Browser caching helps us optimize performance in the first and third steps. For example, if the cache is used directly without making a request, or if the request is made but the back-end stores the same data as the front-end, there is no need to send the data back, thus reducing the response data.

In the following sections, we’ll explore the browser caching mechanism through cache locations, cache policies, and the application of cache policies in real-world scenarios.

To get a mind map or read more great articles, please click on the GitHub blog

2. Cache location

From the point of view of the cache position, there are four kinds, and each has its priority. When the cache is searched in sequence and none is hit, the network will be requested.

  • Service Worker
  • Memory Cache
  • Disk Cache
  • Push Cache

1.Service Worker

A Service Worker is a separate thread that runs behind the browser and is typically used for caching. To use the Service Worker, the transport protocol must be HTTPS. Since request interception is involved in Service workers, the HTTPS protocol must be used for security. The Service Worker’s cache differs from other built-in caching mechanisms in that it gives us control over which files are cached, how the cache is matched, and how the cache is read, and the cache is persistent.

There are three steps to realize the caching function of Service Worker: The Service Worker needs to be registered first, and the required files can be cached after the install event is monitored. Then the next time the user accesses the server, it can intercept the request to check whether there is cache. If there is cache, it can directly read the cache file, otherwise it will request data.

When the Service Worker does not hit the cache, we need to call the fetch function to fetch data. That is, if we do not hit the cache in the Service Worker, we will look up the data based on the cache lookup priority. But whether we fetch data from the Memory Cache or from a network request, the browser displays what we fetch from the Service Worker.

2.Memory Cache

The Memory Cache is the Cache in Memory that contains the resources captured in the current page, such as styles, scripts, and images that have been downloaded on the page. It is definitely faster to read data from memory than from disk. Although memory cache reads data efficiently, it has a short cache duration and will be released as the process is released. Once we close the Tab page, the cache in memory is freed.

So since in-memory caching is so efficient, can we keep all our data in memory? It’s impossible. The amount of memory in a computer is bound to be much smaller than a hard disk, and operating systems need to be very careful about how much memory they use, so there won’t be much for us to use.

When we visit the page and refresh the page again, we can see that much of the data comes from memory cache.

One important cached resource in the memory cache is the resource downloaded by preloader-related instructions (e.g. ). It is well known that the preloader directive is one of the most common methods of page optimization, which can parse JS/CSS files while requesting the next resource online.

Note that memory caching does not care about the value of the HTTP Cache header cache-Control that returns the resource, and the matching of the resource does not only match the URL, but may also check the content-Type, CORS, and other characteristics.

3.Disk Cache

A Disk Cache is a Cache stored on a hard Disk. It is slower to read, but everything can be stored on Disk, which is better than a Memory Cache in terms of capacity and storage timeliness.

Disk Cache coverage is by far the largest of all browser caches. Based on the fields in the HTTP Herder, it determines which resources need to be cached, which resources can be used without being requested, and which resources have expired and need to be re-requested. And even in the case of cross-site, resources with the same address once cached by the hard disk will not be requested again. Most of the Cache comes from Disk Cache, which we’ll discuss in more detail in HTTP protocol headers.

What files does the browser throw into memory? What goes into the hard drive? Opinions vary on the Internet, but here’s a good one:

  • For large files, most likely not stored in memory, and vice versa is preferred
  • If the current system has high memory usage, files are preferentially saved to hard disks

4.Push Cache

Push Cache is HTTP/2 and is used when all three caches fail. It only exists in the Session, is released once the Session ends, has a short cache time (about 5 minutes in Chrome), and does not strictly implement the cache instructions in the HTTP header.

Push Cache in China can find very little information, also because HTTP/2 is not popular in China. “I recommend reading Jake Archibald’s HTTP/2 Push is Demands than I thought”

  • All resources can be pushed and cached, but Edge and Safari support is relatively poor
  • You can push no-cache and no-store resources
  • Once the connection is closed, the Push Cache is released
  • Multiple pages can use the same HTTP/2 connection and thus use the same Push Cache. This depends on the browser implementation. For performance reasons, some browsers may use the same HTTP connection for different tabs with the same domain name.
  • The Cache in a Push Cache can only be used once
  • The browser can refuse to accept an existing resource push
  • You can push resources to other domains

If none of the above caches is hit, then you have to make a request to fetch the resource.

Therefore, for the sake of performance, most interfaces should choose a good cache policy. Generally, browser cache policy is divided into two types: strong cache and negotiated cache, and the cache policy is implemented by setting HTTP headers.

3. Cache process analysis

The communication between the browser and the server is in reply mode. That is, the browser initiates an HTTP request and the server responds to the request. How does the browser determine whether a resource should be cached and how to cache it? After the browser sends the request to the server for the first time and gets the request result, it stores the request result and the cache identifier in the browser cache. The browser’s processing of the cache is determined by the response header returned during the first request for the resource. The specific process is shown below:

From the figure above, we can know:

  • Each time the browser initiates a request, it first looks up the result of the request and the cache identifier in the browser cache

  • Each time the browser receives the result of the returned request, it stores the result and the cache id in the browser cache

The above two conclusions are the key to the browser cache mechanism, which ensures that each request is cached and read. Once we understand the browser cache rules, all problems will be solved, and this article will analyze them in detail. For your convenience, we divide the caching process into two parts, strong caching and negotiated caching, depending on whether the HTTP request needs to be re-sent to the server.

4. Strong cache

Strong cache: Does not send a request to the server, but reads resources directly from the cache. In the Network option of the Chrome console, the request returns a status code of 200, and Size displays from Disk cache or from Memory cache. Strong caching can be implemented by setting two HTTP headers: Expires and cache-Control.

1.Expires

Cache expiration time, used to specify the expiration time of resources, is a specific point in time on the server. That is, Expires=max-age + request time needs to be used in combination with last-Modified. Expires is a Web server response header field that tells the browser in response to an HTTP request that the browser can cache data directly from the browser before the expiration date without having to request it again.

Expires is a product of HTTP/1 and is limited to local time, which can invalidate a cache if you change it. Expires: Wed, 22 Oct 2018 08:41:00 GMT Indicates that the resource will expire after Wed, 22 Oct 2018 08:41:00 GMT and needs to be requested again.

2.Cache-Control

In HTTP/1.1, cache-control is the most important rule and is used to Control web page caching. For example, cache-control :max-age=300 means that the strong Cache will be hit if the resource is reloaded within 5 minutes of the correct return time of the request (which the browser records).

Cache-control can be set in either the request header or the response header, and can be combined with multiple instructions:

Public: All content will be cached (both client and proxy servers can be cached). Specifically, the response can be cached by any intermediate node, such as Browser <– proxy1 <– proxy2 <– Server, the proxy in the middle can cache resources, For example, the next time proxy1 requests the same resource, it directly gives Browser its cache instead of asking Proxy2 for it.

Private: All content can be cached only by the client. The default value of cache-control. For Browser <– proxy1 <– proxy2 <– Server, proxy will send data returned by Server to Proxy1 without caching any data. The next time Browser requests it again, the proxy forwards the request instead of giving cached data to itself.

No-cache: indicates the content of the client cache. Whether to use the cache requires negotiation cache. Does not use cache-control Cache Control for pre-validation, but uses the Etag or Last-Modified field to Control the Cache. Note that the name no-cache is a bit misleading. This does not mean that the browser will no longer cache data, but that the browser needs to make sure that the data is consistent with the server before using the cache.

No-store: All content is not cached, that is, neither mandatory cache nor negotiated cache is used

Max-age: max-age= XXX (XXX is numeric) indicates that the cache contents will expire after XXX seconds

S-maxage (unit: s) : the same as max-age, only in the proxy server (such as CDN cache). For example, when s-maxage=60, during this 60 seconds, even if the content of the CDN is updated, the browser will not request it. Max-age is used for normal caching, while s-maxage is used for proxy caching. S-maxage has a higher priority than max-age. Max-age and Expires headers are overwritten if s-maxage is present.

Max-stale: indicates the maximum expiration time that can be tolerated. The max-stale directive indicates that the client is willing to accept a response that has expired. If a max-stale value is specified, the maximum tolerance time is the corresponding number of seconds. If not specified, the browser is willing to receive any response from age (age represents the difference between the time the response was generated or validated by the source site and the current time).

Min-fresh: Minimum level of freshness that can be tolerated. Min-fresh indicates that the client is unwilling to accept a response whose freshness is less than the sum of the current age plus the time set by Min-Fresh.

As we can see from the figure, we can use multiple instructions together to achieve multiple purposes. For example, we want resources to be cached, cached by both client and proxy servers, cached by expiration times, and so on.

3. Compare Expires and Cache-control

The difference is that Expires is a product of HTTP1.0 and cache-Control is a product of HTTP1.1. If both exist, cache-Control takes precedence over Expires. In some environments where HTTP1.1 is not supported, Expires can be useful. So Expires is an outmoded object that currently exists as a way to write compatibility. Strong caches Determine whether or not the cache is cached based on whether or not the server side file has been updated after a certain time or period, which may result in the loading file is not the latest content on the server side, so how do we know whether the server side content has been updated? Here we need to use a negotiated cache strategy.

Negotiation cache

Negotiation cache is a process in which the browser sends a request to the server with the cache ID after the cache is invalid, and the server decides whether to use the cache based on the cache ID. There are two main situations:

  • The negotiated cache takes effect, returning 304 and Not Modified

  • Negotiation cache invalid, return 200 and request result

Negotiated caching can be implemented by setting two HTTP headers: Last-Modified and ETag.

1. The last-modified and If – Modified – Since

When the browser accesses the resource for the first time and the server returns the resource, the last-Modified header is added to the response header, whose value is the Last modification time of the resource on the server. The browser caches the file and header after receiving it.

Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
Copy the code

The next time the browser requests the resource, the browser detects a last-Modified header and adds if-modified-since, which is the last-modified value; When the server receives the resource request again, it compares the value in if-modified-since with the last modification time of the resource in the server. If there is no change, it returns 304 and an empty response body, reading directly from the cache. If the time of if-modified-since is less than the time of the last modification of the resource on the server, the file has been updated, and the new resource file and 200 are returned

But last-Modified has some drawbacks:

  • If the cache file is opened locally, last-Modified is Modified even if the file is not Modified. The server cannot match the cache and sends the same resource
  • Because last-Modified can only be measured in seconds, if the file is Modified in an imperceptible amount of time, the server will assume that the resource is still a hit and will not return the correct resource

Since the cache is not sufficient based on the file modification time, can the cache policy be determined directly based on the file content modification? ETag and if-none-match were introduced in HTTP / 1.1

2. The ETag and If – None – Match

An Etag is a unique identifier (generated by the server) that is returned to the current resource file when the server responds to a request. The Etag is regenerated whenever the resource changes. When the browser sends a request to the server next time it loads a resource, it will add the Etag value returned last time to if-none-match in the request header. The server only needs to compare the if-none-match value sent by the client with the Etag of the resource on the server. It is a good idea to determine whether the resource has been modified relative to the client. If the server finds that the ETag does not match, it sends the new resource (including the new ETag) to the client in a regular GET 200 packet return. If the ETag is consistent, 304 is returned to inform the client to use the local cache directly.

3. Comparison between the two:

  • First, Etag is superior to Last-Modified in accuracy.

    • Last-modified time is in seconds. If a file changes several times within a second, their last-Modified time is not actually Modified, but Etag changes each time to ensure accuracy. If the server is load-balanced, the last-Modified generated by each server may also be inconsistent.
  • Second, in terms of performance, Etag is inferior to Last-Modified, because last-Modified only takes time to record, whereas Etag requires the server to compute a hash value through an algorithm.

  • Third, server verification takes Etag as the priority

6. Caching mechanism

The mandatory-cache takes precedence over the negotiated Cache. If mandatory-cache (Expires and cache-control) is valid, the Cache is used directly, and If not, the negotiated Cache (last-modified/if-modified-since and Etag/if-none-match) is used. The server decides whether to use the negotiated cache. If the negotiated cache is invalid, the cache of the request is invalid. 200 is returned, and the resource and cache id are returned again, and then stored in the browser cache. If it takes effect, return to 304 and continue to use the cache. The specific flow chart is as follows:

If you have a question: what will the browser do if no caching policy is set?

In this case, the browser uses a heuristic algorithm that typically takes 10% of the Date minus last-Modified value in the response header as the cache time.

7. Apply caching policies in actual scenarios

1. Frequently changing resources

Cache-Control: no-cache
Copy the code

For resources that change frequently, cache-control: no-cache is used to make the browser request the server each time, and then ETag or Last-Modified is used to verify that the resource is valid. This does not save the number of requests, but it can significantly reduce the size of the response data.

2. Resources that are not constantly changing

Cache-Control: max-age=31536000
Copy the code

Such resources are typically processed by setting their cache-control to a large max-age=31536000 (a year) so that subsequent browser requests for the same URL will hit the forced Cache. In order to solve the update problem, dynamic characters such as hash and version number need to be added to the file name (or path), and then dynamic characters need to be changed to change the reference URL, so that the previous mandatory cache is invalidated (it is not immediately invalidated, but is no longer used). Libraries that are available online (jQUERy-3.3.1.min.js, lodash.min.js, etc.) use this pattern.

The impact of user behavior on browser cache

The effect of user behavior on the browser cache refers to the cache policies that are triggered when the user acts on the browser. There are three main types:

  • Open the web page and enter the address in the address bar to check whether there is a match in the disk cache. Use if available; If no network request is sent.
  • Plain flush (F5) : Since TAB is not closed, memory cache is available and will be used preferentially (if a match is made). Disk cache comes next.
  • Forced refresh (Ctrl + F5) : The browser does not use caching, so requests are sent with a headerCache-control: no-cache(And for compatibilityPragma: no-cache), the server returns 200 and the latest content.