skip to Main Content

I have an S3 bucket for my single page application, and all assets stored in the assets folder should be cached for one year, since they have unique filenames based on their hashed contents.

However, I want the remaining items in the S3 bucket to never be cached, and always be requested every time.

Is there a way to do this? Basically, I want two opposing caching strategies in my bucket. For one subfolder in my bucket (/assets) I want the most aggressive caching possible, and for everything else, I want the least aggressive caching possible.

2

Answers


  1. Chosen as BEST ANSWER

    I asked an AI for help and it gave me this, which seems to work, so using it tentatively for now unless someone else has a better idea..!

    aws s3 sync C:\Users\Admin\mysite\frontend\dist\assets s3://mysite/assets --cache-control "max-age=31536000"
    aws s3 sync C:\Users\Admin\mysite\frontend\dist s3://mysite/ --exclude "assets/*" --cache-control "no-store, no-cache, must-revalidate, max-age=0"
    aws cloudfront create-invalidation --distribution-id SITE_ID --paths "/*"
    

    The basic idea seems to be to do two sync calls, where the first one only uploads the assets folder (the one that should be cached forever) with extremely aggressive caching settings.

    Then the second call syncs everything except that folder, with the least aggressive caching headers.

    Then to do a CloudFront invalidation so all the changes are propagated.


  2. You may be able to set cache headers in cloudfront itself. For cases where this is insufficient you can provide a lambda edge function and take finer control over origin response headers, similar to this code of mine:

    function getCacheControlResponseHeader(event: any): string {
    
        const request = event.Records[0].cf.request;
        const path = request.uri.toLowerCase();
    
        const extensions = [
            '.js',
            '.css',
            '.ico',
        ];
    
        const cacheableExtension = extensions.find((ext) => {
            return path.endsWith(`${ext}`);
        });
    
        if (cacheableExtension) {
            return 'public, max-age=31536000, immutable';
        } else {
            return 'no-cache, must-revalidate';
        }
    }
    

    It is typical to not use cache headers for HTNL files, and also to use cache busting timestamps for each resource cached in user browsers. Doing so ensures that upgrades work reliably. In the above code I am caching other assets. Further related info in my blog post.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search