Thoroughly understand strong caching and negotiation caching

At work, the static resources generated after the front-end code is packaged will be published to the static server. At this time, some operation and maintenance configurations must be done for these static resources. Among them, gzip and cache settings are essential. These two are the most direct impact on website performance and user experience.

Advantages of caching:

  • Reduces unnecessary data transfers and saves bandwidth
  • Reduce server load and improve website performance
  • Speed ​​up the loading of web pages on the client side
  • user friendly

shortcoming:

  • If the resources are changed but the client is not updated in time, the user will lag behind in obtaining information. If the old version has bugs, the situation will be even worse.

Therefore, in order to avoid setting cache errors, mastering the principles of caching is very important for us to configure caching more reasonably in our work.

1. Strong cache

What exactly is a strong cache? Where is the strength? In fact, strong means coercive. When the browser requests a file, the server configures the file cache in the response header. The cache time and cache type are all controlled by the server. The specific performance is:
the cache-control of the respone header, and the common settings are max-age public private no-cache no-store, etc.

As shown in the figure below,
set cahe-control:max-age=31536000, public, immutable

 

max-age indicates that the cache time is 31536000 seconds (1 year), public indicates that it can be cached by browsers and proxy servers, and proxy servers can generally be used as nginx. Immutable means that the resource will never change, but in fact the resource is not forever. It is set so that the user does not request the server when refreshing the page! What do you mean? That is to say, if you only set cahe-control:max-age=31536000, public, this is a strong cache. Every time the user opens this page normally, the browser will judge whether the cache has expired, and read data from the cache if it has not expired; But some "smart" users will click the refresh button in the upper left corner of the browser to refresh the page. At this time, even if the resource has not expired (1 year has not passed so quickly), the browser will directly request the server, which is an additional request If it is consumed, it is equivalent to going through the process of negotiating the cache (described below). If cahe-control:max-age=315360000, public plus immutable, even if the user refreshes the page, the browser will not initiate a request to serve, the browser will directly read the cache from the local disk or memory and return a 200 status , look at the red box (from memory cache) above. This is the suggestion that the facebook team mentioned to the IETF working group that formulated the HTTP standard in 2015: they hope that the HTTP protocol can add an attribute field to the Cache-Control response header to indicate that the resource will never expire, and the browser does not need to provide these resources again. Conditional request sent.

Strong Caching Summary

  1. cache-control: max-age=xxxx, both public
    clients and proxy servers can cache this resource;
    within the validity period of xxx seconds, if the client needs to request this resource, it will directly read the cache, status code: 200, If the user performs a refresh operation, an http request is initiated to the server

  2. cache-control: max-age=xxxx, private
    only allows the client to cache the resource; the proxy server does not cache
    the client to directly read the cache within xxx seconds, status code: 200

  3. cache-control: max-age=xxxx, the immutable
    client will read the cache directly if there is a need to request the resource within the validity period of xxx seconds, status code: 200, even if the user performs a refresh operation, it will not send to the server Initiate http request

  4. cache-control: no-cache
    skips the setting of strong cache, but it does not hinder the setting of negotiation cache; generally, if you have made strong cache, the negotiation cache will only be used when the strong cache fails. If no-cache is set, the cache will not be strengthened Yes, every time a request is made, the server will be asked back.

  5. cache-control: no-store
    does not cache, this will prevent the client and server from caching, and there is no so-called strong caching or negotiation caching.

2. Negotiation caching

The strong cache mentioned above is to set an expiration time for resources. Every time the client requests a resource, it will check whether it has expired; only when it expires will it ask the server. Therefore, strong caching is for the self-sufficiency of the client. And when one day, when the client requests the resource and finds that it has expired, it will request the server, and the process of requesting the server at this time can set the negotiation cache. At this time, the negotiation cache requires interaction between the client and the server.

How to set the negotiation cache?

Settings in the response header

 

etag: '5c20abbd-e2e8'
last-modified: Mon, 24 Dec 2018 09:49:49 GMT

etag: There is one for each file, and it will change when the file is changed. It is a file hash, and each file is unique, just like when packaging with webpack, each resource will have this thing, such as: app.js becomes packaged app.c20abbde.js, adding a unique hash is also to solve the cache problem.

last-modified: The modification time of the file, accurate to seconds

That is to say, each time a request returns etag and last-modified in the response header, these two will be included in the request header in the next request, and the server will compare the identifiers you brought over, and then judge whether the resource has changed If it is changed, the new resource will be returned directly, and the corresponding response header's etag and last-modified will be updated. If the resource has not changed, then etag and last-modified will remain unchanged. At this time, for the client, each request needs to be negotiated and cached, that is:

Send a request --> see if the resource is expired --> expired --> request the server --> the server compares whether the resource is really expired --> not expired --> return a 304 status code --> the client uses the cached old resource .

This is a complete negotiation cache process.

Of course, when the server finds that the resource is really expired, it will go through the following process:

Send a request --> see if the resource is expired --> expired --> request the server --> compare whether the server is really expired --> expired --> return a 200 status code --> if the client receives the resource for the first time Like resources, write down the max-age, etag, last-modified, etc. in its cache-control.

So a summary of the negotiation caching steps:

When requesting a resource, the user's local etag of the resource is brought to the server at the same time, and the server compares it with the latest resource.
If the resource has not changed, return 304, and the browser reads the local cache.
If the resource has changed, return 200 and return the latest resource.

One more point, when the etag and last-modified in the response header are re-initiated by the client to the server, the key name will be changed in the request header:

 

// response header
etag: '5c20abbd-e2e8'
last-modified: Mon, 24 Dec 2018 09:49:49 GMT

// request header 变为
if-none-matched: '5c20abbd-e2e8'
if-modified-since: Mon, 24 Dec 2018 09:49:49 GMT

Why is there an etag?
You may think that using last-modified is enough to let the browser know whether the local cached copy is new enough, why do you need etag? The emergence of etag in HTTP1.1 (that is, etag is newly added, in order to solve the shortcomings of only If-Modified before) is mainly to solve several last-modified problems that are difficult to solve:

  1. Some files may be changed periodically, but their content does not change (only the modified modification time). At this time, we don't want the client to think that the file has been modified and get it again;

  2. Some files are modified very frequently, such as modification within seconds (for example, N times within 1 second), the granularity that can be checked by if-modified-since is second-level, and this modification cannot be judged (or Say that UNIX records MTIME can only be accurate to seconds);

  1. Some servers cannot accurately get the last modification time of the file.

How to set strong cache and negotiation cache

  1. Backend server such as nodejs:
    res.setHeader('max-age': '3600 public')
    res.setHeader(etag: '5c20abbd-e2e8')
    res.setHeader('last-modified': Mon, 24 Dec 2018 09: 49:49 GMT)
  2. nginx configuration

     

Occasionally, when you are tossing about non-front-end things by yourself, if you know what you are doing, you will naturally not be in a hurry.

How to use it?

For example, the current single-page file generated after packaging with vue-cli has an html, and a bunch of js css img resources, how to set these files, the core requirement is

 

My approach is:
the index.html file adopts negotiation caching, the reason is that the user requests the index.html every time without taking the browser cache, and directly requests the server, so as to ensure that the resource is updated, and the user can immediately access the new resource. If the service The terminal returns 304, then take the index.html cached by the browser, remember not to set a strong cache! ! !

Other resources use strong cache + negotiation cache, so I won’t say much about the reasons.

  1. There must be a cache, no doubt
  2. When sending new packages, avoid loading old cache resources

     

    Packaged static files

My approach is:
the index.html file adopts negotiation caching, the reason is that the user requests the index.html every time without taking the browser cache, and directly requests the server, so as to ensure that the resource is updated, and the user can immediately access the new resource. If the service The terminal returns 304, then take the index.html cached by the browser, remember not to set a strong cache! ! !

Other resources use strong cache + negotiation cache, so I won’t say much about the reasons.

Guess you like

Origin blog.csdn.net/hanruo7532/article/details/112631071
Recommended