preface

HTTP caching as a front-end engineer is one of the knowledge points, I believe you have mastered. This article will take a look at HTTP caching, starting with a few questions:

  1. When you want to cache a file, is the caching set up by the client or the server, or both?
  2. When cache-control is set on both the client and the server, which Cache will be used?
  3. Do two values of cache-control max-age=0 have the same effect as no-cache?

If you’re confused about the use of cache-Control in request headers, this article will take you through some of the gaps in HTTP caching.

Practice is the proof of wisdom. I believe that many people have only written about HTTP caching and have not practiced it. Therefore, this article will use KOA to build services for verification.

HTTP cache knowledge review

Using HTTP caching can reduce bandwidth, relieve server stress, and improve web site performance. Three header fields are associated with it: Cache-Control, Expires, and Pragma.

Pragma

Pragma is a legacy field from prior HTTP/1.1 and is defined only as backward compatibility with HTTP/1.0. Pragma has only one property value, no-cache, which is used only in requests sent by clients and has the same effect as cache-control’s no-cache.

Pragma has a higher priority than cache-control.

Figure 1: Just set cache-control: max-age=15

Figure 2: Setting cache-control: max-age=15 and Pragma: no-cache

It can be seen from the results of Figures 1 and 2 that no Cache is used when both attributes are present, so Pragma takes precedence over cache-Control.

Expires

The header Expires field tells the client when the resource Expires. Its value is an HTTP date, such as Wed, 04 Jul 2012 08:26:05 GMT. If the request time does not exceed this value, the browser directly uses the cache. Its priority is lower than that of cache-control, which is verified by the following two graphs.

Figure 3: Setting Expires only

Figure 4: Setting Both Expires and Cache-Control

As you can see from Figures 3 and 4, when both Expires and cache-control are set, the request is not cached, so Expires has a lower priority than cache-control.

The priorities of the three fields come out here: Pragma > Cache-Control > Expires

Cache-Control

Cache-control: cache-control: cache-control: cache-control: cache-control: cache-control: cache-control: cache-control

Figure 5: Request instructions (image from Illustration HTTP)

Figure 6: Response instructions (image source: Diagram HTTP)

In the request header, pay attention to the following items: no-cache and max-age. Normally we disable caching with no-cache or max-age=0.

The response header includes public, private, no-cache, no-store, max-age, and s-maxage. No-store indicates that cache is disabled, max-age indicates that cache is strong, and no-cache indicates that cache is negotiated. Others are described in the following figure.

Strong and negotiated caching

When max-age appears in the response header and the value is greater than 0, the browser will enable strong caching, meaning that from now on, the browser will not make a request to the server for max-age seconds and will use the local cache directly. The browser will re-request the server only after max-age seconds.

Figure 7: Strong cache

Let’s look at Figure 7:

  1. The browser initiates the request for the first time.
  2. The server returns 200 and cache-control: max-age=3600, meaning that the browser can use the local Cache for the next 3600 seconds without making a request to the server.
  3. The browser makes the request again.
  4. Read cache directly.

Figure 8: Negotiated cache

Then look at the negotiated cache from Figure 8:

  1. The browser initiates the request for the first time
  2. The server returns 200 and sets cache-control: no-cache and etag
  3. The next time the browser makes a request, it takes the etag value returned earlier and sets if-none-match =etag
  4. At this point, the server determines whether the latest etag value is the same as the etag value of the request header, and returns 304 if they are the same, 200 if they are different and the latest content.
  5. 304 status code received, read from cache
  6. Cache return content

In addition to Etag and if-none-match, there are also last-modified and if-Modified-since caches, one based on whether the contents of the file have been Modified or not, and the other based on when the file was updated.

Overall process of caching

With the above knowledge as a foundation, we can know the overall flow of HTTP caching, as shown in the following figure:

Figure 9: The overall flow of HTTP caching

HTTP caching practices

Cache setup

We’ll set caching separately on the request and response headers to see when caching works.

Figure 10: Caching is set in the response header and the request is initiated for the second time

Figure 11: Caching is set in the request header for the second time

As you can see from Figures 10 and 11, caching only takes effect on the server side.

Cache-control is set in both request and response headers

In the first case, max-age is set.

Figure 12: Max-age =10 on the request header and 60 on the response header

Figure 13: Max-age =0 on the request header and 60 on the response header

It can be seen from Figure 12 that more than 50 seconds have passed and the browser is still reading the cache, so the response s-head is in effect when max-age is set at the same time.

One exception, as you can see from Figure 13, is when max-age=0 is set on the request header, and negotiation cache is used instead of strong cache.

In the second case, max-age is set in the response header and no-cache is set in the request header

Figure 14: Max-age on the response header and no-cache on the request header

In the case of multiple requests, the result is the same as figure 14. It can be seen that the cache is not enabled at this time. At the same time, note that the negotiation cache is not used for multiple requests.

The Disable Cache feature in Chrome DevTool allows no-cache at the beginning of a request

In the third case, max-age is set in the request header and no-cache is set in the response header

Figure 15: Max-age on the request header and no-cache on the response header

Obviously, this is a negotiated cache, i.e. the max-age of the request header is only effective if it is equal to 0.

Do two values of cache-control max-age=0 have the same effect as no-cache

This is split between the request header and the response header. From the above example, we can see that the two effects are different when asking the first subordinate. No-cache disables the cache. Max-age =0 disables the negotiation cache. Now let’s look at the response head case.

Figure 16: Setting no-cache on the response header

Figure 17: Max-age =0 on the response header

Max-age =0 has the same effect on the response header as no-cache.

If the request header is set to no-cache, the request header’s no-store is disabled

Figure 18: No-store for the request header

You can see that most browsers do not support this property.

conclusion

To sum up the first three questions:

  1. The server has to set the cache to work.
  2. Caching is usually done on the server, but setting cache-control to no-cache or max-age=0 on the client changes the decision of the caching mechanism.
  3. The effect is different on the client. No-cache disables cache, and max-age=0 negotiates cache. The effect is the same on the server, which is negotiation cache.

You have a better understanding of HTTP caching.

Finally practice is the truth, the practice of the source code, interested students can try their own.

The practice is based on Koa and Chrome. If there are any errors, please correct them.