The resources that work best with caching are static immutable files whose contents never change. And for resources that do change, it is a common best practice to change the URL each time the content changes, so that the URL unit can be cached for a longer period.
As an example, consider the following HTML:
<script src="bundle.js"></script>
<link rel="stylesheet" href="build.css" />
<body>
hello
</body>
In modern web development, JavaScript and CSS resources are frequently updated as development progresses. Also, if the versions of JavaScript and CSS resources that a client uses are out of sync, the display will break.
So the HTML above makes it difficult to cache bundle.js
and build.css
with max-age
.
Therefore, you can serve the JavaScript and CSS with URLs that include a changing part based on a version number or hash value. Some of the ways to do that are shown below.
# version in filename
bundle.v123.js
# version in query
bundle.js?v=123
# hash in filename
bundle.YsAIAAAA-QG4G6kCMAMBAAAAAAAoK.js
# hash in query
bundle.js?v=YsAIAAAA-QG4G6kCMAMBAAAAAAAoK
Since the cache distinguishes resources from one another based on their URLs, the cache will not be reused again if the URL changes when a resource is updated.
<script src="bundle.v123.js"></script>
<link rel="stylesheet" href="build.v123.css" />
<body>
hello
</body>
With that design, both JavaScript and CSS resources can be cached for a long time. So how long should max-age
be set to? The QPACK specification provides an answer to that question.
QPACK is a standard for compressing HTTP header fields, with tables of commonly-used field values defined.
Some commonly-used cache-header values are shown below.
36 cache-control max-age=0
37 cache-control max-age=604800
38 cache-control max-age=2592000
39 cache-control no-cache
40 cache-control no-store
41 cache-control public, max-age=31536000
If you select one of those numbered options, you can compress values in 1 byte when transferred via HTTP3.
Numbers 37
, 38
, and 41
are for periods of one week, one month, and one year.
Because the cache removes old entries when new entries are saved, the probability that a stored response still exists after one week is not that high — even if max-age
is set to 1 week. Therefore, in practice, it does not make much difference which one you choose.
Note that number 41
has the longest max-age
(1 year), but with public
.
The public
value has the effect of making the response storable even if the Authorization
header is present.
Note: The public
directive should only be used if there is a need to store the response when the Authorization
header is set. It is not required otherwise, because a response will be stored in the shared cache as long as max-age
is given.
So if the response is personalized with basic authentication, the presence of public
may cause problems. If you are concerned about that, you can choose the second-longest value, 38
(1 month).
# response for bundle.v123.js
# If you never personalize responses via Authorization
# If you can't be certain