Alright the solutions given are all valid, I just want to re-iterate everything you can try to get this setup to work (at least what worked for me):
Have cloudfront take the lead in the caching policy
You don this by making sure the content in your S3 bucket doesn't have the max-age
header set to anything besides 0. So for example when using aws s3 sync
, you can use:
aws s3 sync ./build/ $S3_BUCKET --delete --cache-control max-age=0
Or when you you use the aws 3 cp
command, then please see @chadhamre's solution above.
Please do make sure you check this in your CI pipelines, as I accidentally had this set to a large number and couldn't figure out why any solution like cache invalidation did not work.
What this does: As far as I understand it, the content from the S3 buckets now won't be cached on themselves. But we have cloudfront taking the lead in deciding which caching policy to use ,as cloudfront is responsible for serving the content to the enduser. So based cloudfront's own caching policy, it decides when it needs to make a roundtrip to s3 to get the latest content, where we now know that S3 will always be serving the latest content because of the max-age=0
header.
Cloudfront invalidation
Now you also want the all of your cloudfront cache to be invalidated on each release in your deployment pipeline. Simply invalidate the distribution's cache to do this like this for example:
aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths '/*'
Why isn't this enough: Because this invalidates the cached files in cloudfront's edge locations. As @Uğur Dinç
also pointed out: When visiting a page the index.html
is first requested and has a no cache control header, then the browser itself will not even call the server for a newer version. Meaning even though there is a new file at cloudfront, your browser's cache will then not even make the call. And the main issue here is that the index.html refers to older bundle files which don't exist anymore, so having the old index.html being loaded is exactly what triggers this white screen.
What will this be used for?
This invalidation is perfect for when you do have caching policy for all your other files besides the index.html
. As on new release you also want to make sure that any other files like assets their cache will be invalidated. So for example when the index.html
loads your new favicon, with the same filename, the newer version will be shown.
Custom caching behavior for index.html
As cloudfront is now fully in charge of the caching policy and the index.html
referring to older bundle files is the main issue, we will want to implement a custom caching behaviour for this:
- In the aws dashboard click on the distribution at hand
- Click on the behaviours tab to see the table with behaviours
- Create a new behaviour with the following settings:
- path pattern: index.html
- Under "Cache key and origin requests" and as "Cache Policy" select the "CachingDisabled"
- Click on create and make sure that in the the table with behaviours, the
index.html
is at position 0, as this the first behaviour we want cloudfront run.
Final words
I am no expert in this field and perhaps you won't need all 3 of them, but these were the settings that worked for me. Hope this helps someone who has been struggling with this for a while like myself:)