1.1 introduction

  • 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, because cached files can be reused, reduce bandwidth and network load.
  • For a data request, it can be divided into three steps: initiating 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 and the request is not made, 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 next section, we’ll explore the browser caching mechanism by caching location, caching policies, and applying caching policies to real-world scenarios.

1.2 Cache Location

In terms of cache location, there are four types, and each has its own priority. When the cache is searched in turn and none of them hit, the network will be requested.

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

1.2.1 Service Worker

  • A Service Worker is a separate thread that runs behind the browser and is typically used to implement caching. To use a Service Worker, the transport protocol must be HTTPS. Because request interception is involved in the Service Worker, the HTTPS protocol must be used for security. The Service Worker’s caching is different from the browser’s other built-in caching mechanisms in that it gives us the freedom to control which files are cached, how the cache matches, how the cache is read, and that the caching is continuous.

  • Service workers generally implement caching in three steps: First of all, you need to register the Service Worker, and then after listening to the install event, you can cache the required files, so the next time the user visits, you can check whether there is a cache by intercepting the request. If there is a cache, you can directly read the cache file, otherwise you can request the data.

  • When the Service Worker does not hit the cache, we need to call the fetch function to fetch the data. In other words, if we do not hit the cache on the Service Worker, we will look for the data according to the cache lookup priority. But whether we get the data from the Memory Cache or from a network request, the browser will show that we got the data from the Service Worker.

  • Conclusion:

    • What files are cached freely, how do you match the cache, and how do you read the cache
    • The cache is persistent

1.2.2 the Memory Cache

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

  • ** So since memory caching is so efficient, can we keep all the data in memory? ** This is out of the question. Computers must have much less memory than hard disks, and operating systems need to be careful about how they use it, so there’s not much that we can use. After visiting the page and refreshing the page again, we can see that a lot of data comes from the memory cache:

  • An important cache resource in the memory cache is preloader-related instruction (e.g. ) downloads. As we all know, preloader has become one of the common means of page optimization. It can parse JS/CSS files while the network requests the next resource.

    The important thing to note is that memory Cache does not care about the value of the HTTP Cache header cache-control that returns the resource, and the matching of the resource is not only for the URL, but also for content-type, CORS and other characteristics.

  • Conclusion:

    • Read the efficient
    • Very short duration

1.2.3 Disk Cache

  • A Disk Cache is a Cache stored on a hard Disk. It is slower to read, but can store everything on a Disk, which is better than Memory Cache in terms of size and time.

  • The Disk Cache has the largest coverage of any browser Cache. It uses the fields in the HTTP Herder to determine which resources need to be cached, which resources can be used without a request, and which resources have expired and need to be rerequested. And even in the case of cross-site, resources at the same address, once cached by the hard disk, will not be asked for data again. The vast majority of caching comes from the Disk Cache. We will discuss the Cache fields in the HTTP header in more detail below.

  • ** What files does the browser throw into memory? Which ones go into the hard drive? ** There are different opinions on the Internet about this, but the following opinions are reliable:

    • For large files, a high probability is not stored in memory, and vice versa
    • If the current system memory usage is high, the files are stored on the hard disk first

1. Push the Cache

  • Push Cache is the content of HTTP/2 and is only used when none of the above three caches is hit. It exists only in sessions and is released once the Session is over. It is also cached for a very short time, around 5 minutes in Chrome, and it does not strictly implement the caching instructions in THE HTTP header.

  • Few data can be found in Push Cache in China, which is also because HTTP/2 is not widely used in China. I recommend reading this article by Jake Archibald in HTTP/2 Push is Faced than I Thought. A few conclusions in the article:

    • All resources can be pushed and cached, but Edge and Safari have relatively poor support
    • 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 the same Push Cache. For performance reasons, some browsers will use the same HTTP connection for different tabs with the same domain name.
    • The Cache in Push Cache can be used only once
    • The browser can refuse to accept an existing resource push
    • You can push resources to other domains
  • Conclusion:

    • Exists only in sessions
    • The session is released and the cache time is short
  • If none of the above four caches is hit, a request is made to obtain the resource.

  • For performance purposes, most interfaces should have a good caching policy. There are two types of caching policies: strong caching and negotiated caching. Caching policies are implemented by setting HTTP headers.

1.3 Cache process analysis

  • The mode of communication between the browser and the server is reply mode, that is: the browser makes an HTTP request – the server responds to the request, so 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 into the browser cache. The browser’s processing of the cache is determined according to the response header returned when the browser first requests the resource. The specific process is as follows:

  • From the picture above, we can know:

    • Each time the browser gets a returned request result, it stores the result and the cache identifier in the browser cache
    • Each time the browser initiates a request, it first looks in the browser cache for the result of the request and the cache identifier
  • These two conclusions are the key to the browser caching mechanism, which ensures that every request is cached and read. Once we understand how the browser cache is used, all problems will be solved. This article will focus on this in detail. For the sake of understanding, the caching process is divided into two parts, the strong cache and the negotiated cache, depending on whether the HTTP request needs to be re-sent to the server.

1.4 strong cache

Strong cache: Instead of sending a request to the server, the resource is read directly from the cache. You can see in the Chrome console’s Network option that the request returns a status code of 200, and the Size is displayed as from Disk cache or from Memory cache. Strong caching can be achieved by setting two HTTP headers: Expires and cache-control.

1.4.1 Expires

The cache expiration time, which specifies the expiration time of the resource, is a specific point in time on the server. In other words, Expires=max-age + request time, which 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 data can be cached directly from the browser until the expiration date, without having to request it again.

Expires is an artifact of HTTP/1 and is limited to local time, which can invalidate the cache if changed. 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.

1.4.2 Cache-Control

In HTTP/1.1, cache-Control is the most important rule and is primarily used to Control the caching of web pages. For example, when cache-control :max-age=300, the resource is reloaded within 5 minutes of the correct return time of the request (which is also recorded by the browser), and the strong Cache is hit.

Cache-control can be set in either the request header or the response header, and can be used in combination 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 intermediate proxy can cache the resource, For example, the next time proxy1 requests the same resource, it will directly give Browser its cache instead of proxy2.

Private: All contents can be cached only by the client. Default value of cache-control. If Browser <– proxy1 <– proxy2 <– Server, proxy sends the data returned by Server to proxy1 without caching any data itself. The next time the Browser requests again, the proxy will do a good job of forwarding the request instead of giving the cached data to itself.

No-cache: Indicates the content cached by the client. Whether to use the cache is verified through cache negotiation. Indicates that you do not use cache-control for pre-validation, but instead use the Etag or last-Modified field to Control the Cache. Note that the name no-cache is a little misleading. After no-cache is set, it does not mean that the browser does not cache the data, but the browser needs to make sure that the data is consistent with the server before using the cached data.

No-store: Nothing will be cached, either by force or negotiation

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

S-maxage (unit: s) : Same as max-age, only takes effect on the proxy server (such as CDN cache). For example, when s-maxage=60, in the 60 seconds, even if the content of the CDN is updated, the browser will not make the request. Max-age is used for normal caching, while S-maxAge is used for proxy caching. The priority of S-maxage is higher than that of max-age. If s-maxage is present, the max-age and Expires headers are overwritten.

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

Min-fresh: The minimum freshness that can be tolerated. Min-fresh indicates that the client is not willing to accept a response whose freshness is no more than the current age plus the time set by Min-fresh.

cache-control

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, and both the client and the proxy can be cached, and we can set the cache expiration time and so on.

1.4.3 Comparison between Expires and cache-control

The difference is that Expires is created by Http1.0, and cache-control is created by Http1.1. If both are present, cache-control takes precedence over Expires. Expires is useful in situations where HTTP1.1 is not supported. So Expires is actually obsolete, and for now it exists only as a compatible expression. Strong caching is based on whether the cache is cached after a certain time or a certain period of time, regardless of whether the server side file has been updated. This may cause the loaded file not to be the latest content on the server side, so how do we know if the server side content has been updated? This is where we need to negotiate the cache policy.

1.5 Negotiation Cache

Negotiated cache refers to the process in which the browser sends a request to the server with the cache identifier after the mandatory cache is invalid, and the server decides whether to use the cache according to the cache identifier. There are mainly two cases:

  • Negotiation cache takes effect, return 304 and Not Modified

  • Negotiation cache invalid, return 200 and request result

Negotiation caching can be achieved by setting two HTTP headers: last-Modified and ETag.

1.5.1 last-modified and If – Modified – Since

When the browser accesses the resource for the first time, the server returns the resource, and adds the last-modified header to the response Header. The value is the Last time that the resource was Modified on the server. After the browser receives the resource, the file and header are cached.

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

The next time the browser requests the resource, the browser detects the last-Modified header and adds the if-modified-since header, which is the last-modified value. When the server receives the resource request again, it will compare the value in if-Modified-since to the last time the resource was Modified in the server. If there is no change, it will return 304 and an empty response body and read it directly from the cache. If the if-modified-since time is less than the last time the resource was Modified 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 cached file is opened locally, the last-modified file will still be Modified, and the server will not be able to hit the cache and send the same resource
  • Since last-modified files can only be counted 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 it is not sufficient to determine whether the cache is modified based on the time of file modification, can we directly determine the cache policy based on whether the file content is modified? So ETag and if-none-match appear in HTTP / 1.1

1.5.2 the ETag and If – None – Match

An Etag is a unique identifier (generated by the server) that the server returns to the current resource file in response to a request and is regenerated whenever the resource changes. When the browser loads a resource and sends a request to the server next time, it puts the Etag value returned last time into the if-none-match in the request header. The server only needs to compare whether the if-None-match sent by the client is consistent with the Etag of the resource on its server. It’s a good idea to determine if the resource has been modified relative to the client. If the server finds that the ETag does not match, it directly sends the new resource (including the new ETag) to the client in the form of the regular GET 200 return package. If the ETAGS are consistent, return 304 and tell the client to use the local cache.

The ETag and If – None – Match

1.5.3 Comparison between the two:

  • First, Etag is better than last-Modified in terms of accuracy.

The last-modified time unit is seconds. If a file is Modified multiple times in a second, their last-modified time does not actually reflect the modification, 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, Etag is inferior to last-Modified in terms of performance. After all, last-Modified only records time, whereas Etag requires the server to compute a hash value through an algorithm.
  • Third, server verification takes precedence over Etag

1.6 Caching Mechanism

Mandatory caches take precedence over negotiated caches. If mandatory caches (Expires and cache-control) are valid, caches are used directly. If not, negotiated caches are used (last-modified/if-modified-since and Etag/if-none-match). The server decides whether to use the negotiation cache. If the negotiation cache is invalid, the request cache is invalid and 200 is returned. Resources and cache identifier are returned and stored in the browser cache. If effective, return 304 and continue using cache. The specific flow chart is as follows:

If no caching policy is set, what will the browser do?

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

1.7 Applying caching Policies in actual scenarios

1.7.1 Frequently Changing Resources

Cache-Control: no-cache

For frequently changing resources, you first need to use cache-control: no-cache to make the browser request the server each time, and then use ETag or last-Modified 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.

1.7.3 Infrequently Changing Resources

Cache-Control: max-age=31536000

Usually when dealing with such resources, you configure their cache-control with a large max-age=31536000 (a year), so that the browser will hit the mandatory Cache when it requests the same URL later. To solve the update problem, you need to add dynamic characters such as hashes and version numbers to the file name (or path), and then change the dynamic characters to change the reference URL and invalidate the previous forced cache (which is not immediately invalidated, just no longer used). The class libraries available online (e.g., jquery-3.3.1.min.js, lodash.min.js, etc.) all adopt this pattern.

1.8 Impact of User Behavior on Browser Cache

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

  • Open the web page, enter the address in the address box, and check whether there is a match in the disk cache. Use if available; If not, send a network request.
  • Normal refresh (F5) : Since TAB is not turned off, memory cache is available and will be used preferentially (if a match is found). Second is disk cache.
  • Force refresh (Ctrl + F5) : The browser does not use caching, so requests are sent withCache-control: no-cache(For compatibility, I brought itPragma: no-cache), the server directly returns 200 and the latest content.