Thor Correia
Thor Correia

Reputation: 1309

React, S3, and CloudFront Versioning for Deployment

First problem:

I have a static webpage hosted on S3, a CloudFront distribution pointing to this S3 bucket, and an A record on my domain pointing to this CloudFront distro. I also have some API Gateway and Lambda and DynamoDB stuff going on.

This webpage is a React app following the create-react-app template. As such, when I yarn build, all of the js and css fragments are cache-busted nicely with these random main.d74fc389.chunk.js names. However, importantly, the index.html (and other static files) are not.

When I aws s3 sync build/ s3://xxxx, everything gets uploaded nicely, but the cloudfront root is still pointing at the old cached index.html!

What can I do about this so that my automatic deployment script (basically just yarn build && aws s3 sync build/ s3://xxxxxx works properly?

I am pointing my domain to CloudFront rather than to the straight S3 website because I want a TLS certificate. I have therefore denied access in my policies to the S3 bucket to anyone except the CloudFront OAI.

Second problem:

I've solved this by setting up a default object in CloudFront.

For some reason I keep getting `access denied` errors on my `https://cloudfront.xxxxxx.xxx` (and therefore on my `https://mydomain.xxx`, but accessing `https://mydomain.xxx/index.html` and any other item (including the newly uploaded items, as evidenced by the updated javascript!) has absolutely no issue. Wtf? Here is my S3 policy:
{
    "Version": "2012-10-17",
    "Id": "Policy1631694343564",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXXXXXXX"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::xxxxxxx/*"
        }
    ]
}
This was literally autogenerated by CloudFront, so I have no idea how it could be incorrect.

I do have my bucket set to serve a static website, but have declined access to s3:GetObject to the general public, so this URL does nothing. The origin I have set up for my CloudFront is the S3's REST api (i.e. xxxxxx.s3.us-west-1.amazonaws.xxx) rather than the bucket's website URL (http://xxxxxxx.s3-website-us-west-1.amazonaws.xxx/).

The .com in URLs was replaced with .xxx because of StackOverflow rules

Upvotes: 0

Views: 730

Answers (1)

Nick
Nick

Reputation: 181

Wait for the TTL or invalidate your cache.

aws cloudfront create-invalidation --distribution-id E2FXXXXXX4N0MS --paths "/*"

This may not be suitable if you are doing lots of deployments as there are some limits and costs.

AWS Documentation

Upvotes: 1

Related Questions