I host a static website on S3 + Cloudfront. To redeploy, I upload static files with
aws s3 sync static
and invalidate the cloudfront cache with
aws cloudfront create-invalidation
What is the recommended way to force browsers to get these new assets after I update them? The problem is that browsers are caching these assets and users are getting old (invalid) versions of scripts, images, and styles.
Generally, there are multiple steps you can do to make sure your AWS CloudFront and S3 setup to cache bust upon new deployments.
Using New File Names
<!doctype html>
<html lang="en">
<head>
<link href="styles.h2d1f722.css" rel="stylesheet" />
</head>
<body>
<script type="text/javascript" src="scripts.cbe3c974.js"></script>
</body>
</html>
You can generate new file names using your frontend build tool (e.g Webpack, Gulp & etc.)
Using Query Parameters
<!doctype html>
<html lang="en">
<head>
<link href="styles.css?hash=h2d1f722" rel="stylesheet" />
</head>
<body>
<script type="text/javascript" src="scripts.js?hash=cbe3c974"></script>
</body>
</html>
When setting up Query Parameters, make sure you have enabled it in CloudFront (Otherwise the cached response of the file will be returned).
Note: Comparing these two approaches there are pros and cons of each of them. Having same file name, you are able to version the files using S3 native versioning while having new names, it doesn't make much sense to do it since new deployments add new names for the files. Also having new file names, makes the S3 bucket cluttered unless you remove or move the old file to another bucket.
Using Meta Tags
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
<link href="styles.css?hash=h2d1f722" rel="stylesheet" />
</head>
<body>
<script type="text/javascript" src="scripts.js?hash=cbe3c974"></script>
</body>
</html>
In this example, it instructs not to cache at browser. However, you can setup appropreate values for these.
You cannot force browsers remote if they already hold the cache values, unless manually intervened.
You need to append
script.something.js?buildid=someuniquereference
and make cloudfront not to cache on query string parameters.
You can also include filename.hash.js or filename.hash.html and with index.html / default document, reduce the time of caching with cache control headers.
This way if you make any changes, you can change that number, cache will be busted on the client as well.
But once you sent the cache headers, there is no way you can clean up the client cache on the browsers remotely.
Hope it helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With