preface
Accessing the server for data is common in any front-end project, but if the same data is requested repeatedly, the extra number of requests can waste network bandwidth and delay the browser rendering process, thus affecting the user experience. If the user uses a pay-per-view approach to access the network, then the extra requests will implicitly increase the user’s network traffic charges. Therefore, it is an effective strategy to consider using caching technology to reuse the acquired resources to improve website performance and user experience.
How caching works
After the first request, a response copy of the resource request is saved. When the user initiates the same request again, if the cache matches the request, the request is intercepted and the response copy stored before is returned to the user, so as to avoid re-initiating resource requests to the server.
There are many types of caching technologies, such as proxy caches, browser caches, gateway caches, load balancers, and content delivery networks, which can be broadly divided into two categories:
Shared cache
– Cached content can be used by multiple users, such as Web proxies within a company.Private cache
– A cache that can only be used by the user alone, such as the browser cache.
HTTP cache A front-end development in one of the most often contact caching mechanism, it can be divided into mandatory buffer cache and negotiation, the two biggest difference is that a judge a cache hit, the browser will need to ask the server to negotiate the cached information, and then determine whether need to the content of the response to the request. Let’s take a look at the specific mechanism of HTTP caching and the decision strategy of caching.
Mandatory cache
In the case of the forced cache, if the browser determines that the requested target resource is a valid hit (it has not expired), the request response can be returned directly from the forced cache without any communication to the server.
Simply put, the resource is read directly from the cache without sending a request to the server.
Force caching principle
Forced caching is a process of looking up the request result from the browser cache and deciding whether to use the cached result according to the caching rules of the result. There are three cases of forced caching, as follows:
-
Case 1: The first request, with no cache result or cache identity, sends the request directly to the server.
-
Second case: The cache identity and the cache result exist, but have expired, force the cache to expire, then use the negotiated cache (described later)
-
The third case: the cache result and the cache identifier exist, and the result is not invalid, the cache is forced to take effect and the result is directly returned.
Caching rules that force caching
When a browser sends a request to the server, the server sends the request back to the browser in the HTTP header of the response packet along with the result of the request. The fields that Control the mandatory Cache are Expires and cache-control, respectively. Cache-control has a higher priority than Expires.
Before we talk about forcing the cache to determine a hit, let’s first look at part of a response header:
access-control-allow-origin: *
age: 734978
content-length: 40830
content-type: image/jpeg
cache-control: max-age=31536000
expires: Web, 14 Fed 2021 12:23:42 GMT
Copy the code
The two fields associated with mandatory caching are Expires and cache-control.
Expires
expires
Is in theHTTP1.0 agreement
Field that controls the cache expiration date timestamp declared in It tells the browser through the response header when set on the server, and the browser caches when it receives a response body with that field.- Valid value: GMT format
Expires = max-age + Request time
If the browser makes the same resource request again, Expires will be compared with the current local timestamp. If the local timestamp of the current request is less than Expires, the cached response has not expired and can be used directly without making a request to the server again. A new request to the server is allowed only if the local timestamp is greater than the Expires value.
resp.setHeader("Expires", new Date("2021-08-13 22:50:24").toUTCString());
Copy the code
Expires’s flaws:
The above mechanism for determining whether the cache is expired has a big vulnerability, that is, excessive reliance on the local timestamp. If the local time of the client is not synchronized with the server time, or the client time is actively changed, the judgment of the cache expiration may not be as expected.
Cache-control
To address the limitations of Expires, the cache-control field was added to the HTTP1.1 protocol to extend and improve the Expires function.
max-age
From the above code, you can see that cache-control sets the max-age=31536000 attribute value to control the duration of the response resource, which is a length of time in seconds, indicating that the resource is valid for 31536000 seconds after the request. This avoids the problem of server-side and client-side timestamps being out of sync. In addition, cache-control can be configured with a number of other properties to control the Cache more accurately.
No – the cache and no – the store
Setting no-cache is not the literal meaning of not using the cache. It means to force a negotiated cache (as we’ll see later), that is, no longer to determine whether the enforced cache is expired on the requested request, but to negotiate directly with the server to verify the validity of the cache. If the cache is not expired, the local cache will be used.
Setting no-store disables any caching policy and requires a new response from the server every time the client requests it.
No-cache and no-store are mutually exclusive and cannot be set at the same time.
Private and public
Private and public are also a set of mutually exclusive values for cache-control that specify whether the response resource can be cached by the proxy server.
private
– Indicates that the response resource can be cached by either the browser or the proxy server.public
– The default value of cache-control. Indicates that the response resource can only be cached by the browser.
For files that do not change in the application, it is usually possible to add active caching (public) before sending the response header. For example, static files in the application, such as images, CSS files, and JS files.
Cache-control: public, max-age=600
Copy the code
Max – age and s – maxage
The value of max-age is more commonly used than that of s-maxage. It indicates the expiration time of the response resource that the server tells the client browser. It is sufficient in common project scenarios. However, in cases where large architecture projects typically involve the use of various proxy servers, the validity of caching on the proxy server needs to be considered. That’s what S-MaxAge is for. It represents the expiration time cached in the proxy server and is valid only if the value of the public property is set.
conclusion
So cache-control can be a complete expires alternative, and it has some Cache control features that it doesn’t, so it’s enough to use in your project practice. The only reason expires exists at the moment is to allow for backward compatibility in terms of usability.
Negotiate the cache
Before using the local cache, you need to send a GET request to the server to negotiate whether the local cache saved by the browser has expired.
Last-Modified
This is usually based on the last modification timestamp of the requested resource (the mtime when the file was obtained). To understand this, let’s look at an example: Suppose the client browser requests a js file resource from the server. In order for the resource to be requested again using the local cache, the response header that returns the image resource for the first time should contain a last-modified field. The value of this field is the timestamp of the last modification of the JS file resource. Brief interception of the key information of the request header and response header:
/ / the first Request of the head of the Request URL: http://localhost:3000/image.jpg the Request Method: GET / / first Request response headers last-modified: Thu, 29 Apr 2021 03:09:28 GMT cache-control: no-cacheCopy the code
When we refresh the web page, because the JS file uses no-cache, the client browser cannot determine whether the local cache is expired, so we need to send a GET request to the server to negotiate the validity of the cache. The request header for this GET request needs to include an IF-Modified-since field with the last-modified field value of the Last response header.
When the server receives the request, it compares the current Modified timestamp of the requested resource with the value of the IF-Modified-Since field. If they are the same, the cache has not expired, and the browser is told to continue to use the local cache. Otherwise, the server returns a new file resource, and intercepts the key information of the request header and response header.
/ / Request of the head again Request URL: http://localhost:3000/image.jpg the Request Method: GET the if-modified-since: Thu, 29 Apr 2021 03:09:28 GMT // Negotiation cache valid response header Status Code: 304 Not ModifiedCopy the code
*! Note: * The response status code for the negotiation cache to determine whether the cache is valid is 304, meaning that the cache is still valid and is redirected to the local cache. This is different from forced caching, which, if valid, returns a request with a response status code of 200.
The defects of last-modified
The last-modified negotiated cache works for most usage scenarios, but has two obvious drawbacks:
- First it’s just based on resourcesTimestamp of last modification[a.jpg -> B.jpg -> a.jpg]). The time stamp is updated, causing the validity judgment to be invalid when the cache is negotiated. The complete resource request needs to be remade. This will undoubtedly cause a waste of network bandwidth resources, and prolong the user to obtain the target resource time.
- Secondly, the time stamp unit of the file resource modification is identified as second. If the file modification speed is very fast, assuming that it is completed within several hundred milliseconds, then the validity of the cache verified by the time stamp mentioned above cannot be recognized. (For example, multiple changes within 1 second cannot be captured)
In both cases, the server was unable to identify the actual update based on the timestamp of the resource modification, resulting in a re-request that used a cached Bug scenario.
ETag
To make up for the lack of time stamp judgment, an ETag header is added from HTTP 1.1, that is, an Entity Tag.
The content is a string generated by the server based on the hash operation of different resources. The string is similar to the file fingerprint. As long as the content encoding of the file is different, the corresponding ETag value will be different. Therefore, you can use ETAGS for more accurate awareness of changes in file resources.
The following is an example of using ETag to negotiate and cache image resources. The key information of part of the response header after the first request:
Content-Type: image/jpeg
ETag: "xxx"
Last-Modified: Fri, 12 Jul 2021 18:30:00 GMT
Content-Length: 9887
Copy the code
The response header contains both the last-Modified timestamp and the ETag entity tag to verify the validity of the negotiated cache. Since ETag is more accurate than last-Modified, it has a higher priority. If the ETag and ETag exist simultaneously, the ETag prevails.
When a request is made for the image resource again, the ETag field of the response header of the first request is used as the if-none-match field in the current request header and provided to the server for cache validation.
Request header key field information:
If-modified-since: Fri, 12 Jul 2021 18:30:00 GMT if-none-match: "XXX"Copy the code
If the cache is validated, a 304 status code is returned in response to redirect to the local cache.
ETag defects:
Unlike cache-control, a mandatory replacement for Expires, in negotiated caches, ETag is not a last-modified alternative but a complement, because it still has some drawbacks.
-
On the one hand, the server needs to pay extra computing costs for generating ETAGS of file resources. If the size of resources is large, the number of resources is large, and they are frequently modified, the process of generating ETAGS affects the performance of the server.
-
On the other hand, the generation of ETag field value can be divided into strong authentication and weak authentication:
- Strong authentication: Generated according to the resource content, to ensure that each byte is the same;
- Weak authentication: Is generated according to the value of some attributes of the resource. The generation speed is fast, but each byte cannot be the same. In the server cluster scenario, the accuracy is insufficient, and the success rate of the negotiated cache validity verification is reduced.
Links to sites
- Segmentfault.com/a/119000001…
- www.yuque.com/docs/share/…