preface

Recently met a problem, our team developed a js library, to provide various business introduction, relevant business data, gradually found that each update js library code, redistribution, and clear the DNS cache, or some business party at the request of the old js library code, how to make the business side pick up the latest SDK code? Do I get stuck changing the filename of the JS library every time I republish it? It doesn’t seem reasonable to notify so many business parties to change their incoming file names one after another every time they publish? I am afraid it will be thrown eggs by the business side, and the business side will not re-issue the version because of this small change, which is obviously not reliable. So I looked into the browser’s static resource caching policy, thinking that the Nginx configuration would change the Etag field in the corresponding header to tell the browser that THE resource had been updated, and the browser would download the new resource file from the server. However, after a lot of work, I found that Nginx can only ensure that the ETag is turned on and off, that is, whether the field is included in the detail header, but it cannot guarantee that the ETag field will be updated after the resource is updated. My problem is not solved, but I have carefully studied Expires, last-Modified. Caching mechanism for Etag. In this post, I share some of my thoughts on the browser’s static resource caching strategy, hoping to help those who have similar problems

Cache-control

Before I get to the highlights, I’d like to share a little bit about the cache-control field in the request and response headers. This field acts as a Cache Control in HTTP requests. It is a Cache Control switch that identifies whether or not caching is enabled in a request or access, and what type of caching is being used.

Cache-control generic header fields are used to implement caching mechanisms through directives in HTTP requests and responses. Cache directives are one-way, meaning that directives set in the request do not necessarily contain the same directives in the response. The cache-control response directive allows the source server to override a response’s default caching capabilities.

Cache-control fields

Cache-control is used in the request, which has the following optional values:

The field names instructions
no-cache Tell the (proxy) server not to use the cache directly and ask to make a request to the original server (this does not mean you can fetch the latest resource every time).
no-store None of the content is saved to cache or temporary Internet files
max-age=delta-seconds Tell the server that it wants to receive a resource whose Age is no longer than delta-seconds
min-fresh=delta-seconds Tell the (proxy) server that the client wants to receive a resource that has been updated in less than delta-seconds
no-transform Inform the (proxy) server that the client wants to obtain a resource whose entity data has not been transformed (such as compressed)
only-if-cached Inform the (proxy) server that the client wants to retrieve the cached content without sending a request to the original server
cache-extension Custom extension value. If the server does not recognize this value, it will be ignored

When cache-control is used in the response, its optional values are:

The field names instructions
public Indicates that the resource should be cached in any case (even if it requires HTTP authentication)
Private[=”field-name”] All or part of the field data (field-name if field-name is specified) in the returned packets can only be cached by certain users (share-users specified by the server, for example, a proxy server). Other users cannot cache the data
no-cache Instead of using caching directly, request a (freshness check) request to the server (this is where Etag and Last-Modified come into play)
no-store None of the content is saved to cache or temporary Internet files
no-transform Tell the client to cache the file without making any changes to the entity data
only-if-cached Inform the (proxy) server that the client wants to retrieve the cached contents (if any) without sending a request to the original server
must-revalidate The current resource must have sent an authentication request to the original server. If the request fails, 504 will be returned (not cached on the proxy server).
proxy-revalidate Similar to must-revalidate, but skills apply to shared caches (such as proxies)
max-age=delta-seconds Tell the client that the resource is fresh for delta-seconds and does not require a request to the server
s-maxage=delta-seconds Same as max-age, but only for shared caches (such as proxies)
cache-extension Custom extended value. If the client does not recognize this value, it will be ignored

It is important to note that in cache-control, these values can be combined freely. When multiple values conflict, they have priority, and no-store has the highest priority.

Cache validation: In caching, we need a mechanism to verify that the cache is valid. For example, when the server resources are updated, the client needs to refresh the cache in time, or the client resources expire, but the resources on the server are still old. In this case, the client does not need to request resources again. Cache validation is used to solve these problems.

Expires(Cache validation)

Server Settings Expires fields for a date, when client requests the resources, to compare the the client and the date the current date, if the current time is less than this date, said resources has not expired, use the cache, if time is greater than the current date, said resources has expired, the client will request the resource again. However, this strategy suffers from client and server time inconsistency issues. If the time of the client is later than that of the server, the client will re-request the resource before it expires. Otherwise, the client will still use the expired resource.

Last-modified/if-modified-since (cache check)

When the browser first requests a resource, the server returns a status code of 200, and the HTTP response header returns the requested resource with a last-Modified mark indicating when the file was Last Modified on the server.

When the browser makes a second request for the resource it requested last time, it adds an if-modified-since flag to the HTTP request header to ask the server If the file has been Modified Since then

If the resources on the server do not change, the system automatically returns to status 304 and uses the browser cache to ensure that the browser does not repeatedly obtain resources from the server and that the client can obtain the latest resources in a timely manner when the server changes.

Etag/if-none-match (cache check)

When the browser first requests a resource, the server returns a status code of 200, and the HTTP header contains an Etag field containing a sequence of values generated by the server.

When the browser makes a second request for the same URL, it adds an if-none-match flag to the HTTP request header to ask the server If the file has been modified.

If the server resource has not changed and the Etag field has not been modified and is consistent with if-none-match, the request automatically returns status 304, using the browser cache. If they are inconsistent, the resource is changed and you need to download a new resource.

Etag addresses a number of issues that Last-Modified could not:

(1) Some files may change periodically, but their contents do not change (only the modification time is changed). At this time, we do not want the client to think that the file has been modified, and get resources again.

(2) Some files are Modified very frequently, such as in less than a second (such as N changes in 1s), if-modified-since the granularity can be detected in seconds, such changes are not detectable (or UNIX records MTIME is only accurate to seconds);

(3) Some servers cannot accurately get the last modification time of files;

The ETag option is enabled by default in the nginx configuration, so any changes to the requested resource file will generate a new ETag value in the response header. This allows the client to find that the if-none-match value does not Match the value of the Etag field and request the latest resource file.

My confusion

After static resources are modified. The time when the file was last changed and the ETag field sometimes don’t seem to change, and the browser caches the static resource file, causing it to fail to update when the file changes. Does the cache of static resources rely only on the policy of changing the file name to get the latest resource? So Expires, Last-Modified, and Etag fields can only be changed in background code? Do the heroes have a better solution? Hope each hero not stingy give advice ~

The articles

Use SockJS to achieve webSocket communication in VUE

PostMessage is so useful

Table header-fixed (table header-fixed)