An SPA (Single-page application) is a web app implementation that loads only a single web document, and then updates the body content of that single document via JavaScript APIs such as XMLHttpRequest and Fetch when different content is to be shown. Read more about it here.
For the purpose of this post, I will be using a simple react app.
Setting up S3 bucket to hold our react build.
Create a bucket
- Keep the bucket name same as the domain (Helps).
- Let the Object Ownership be 'ACLs Disabled'
- Block All Public Access.
Deploy the React Application Build Folder to the S3 bucket
- Make sure the
index.html
file is in the root of the directory.
Setting up CloudFront
Create a new CloudFront Distribution
- Select the Origin as the S3 bucket we just created.
- S3 Bucket Access: If you do not already have an Object Access Identity, create a new one.
- We can let CloudFront update the policy for us. (Select
Yes, update the bucket policy
) - Price Class: You can select the regions as per your needs.
- Since we will be using this CloudFront in our Domain Name, Provide the CNAME Domain Name. My Domain name is
roshan-raj.com
. - You can choose to add a custom SSL certificate. You can choose to request one from AWS. This will be free of cost if used in CloudFront. If you are creating a new SSL Certificate, it needs to be in the N.Virginia Region.
- Specify the Default Root Object as
index.html
. - You can turn on Standard Logging. (Recommended)
Going Back to S3.
- CloudFront should have added a policy for our bucket.
- We need to add another statement in the Policy, which is s3:ListBucket.
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <CLOUDFRONT>"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::roshan-raj/*"
},
{
"Sid": "2",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <CLOUDFRONT>"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::roshan-raj"
}
]
}
We are done. The React App will be available at the CloudFront URL.
Now, If you have any further routes in the React SPA, going to that routes will throw an Error "NoSuchKey".
We can fix this using a CloudFront Function, to re-write the url and attaching an index.html to the URL.
- Create a CloudFront function and use the below code. https://github.com/aws-samples/amazon-cloudfront-functions/blob/main/url-rewrite-single-page-apps/index.js
- Publish the function and attach it to the CloudFront > Behaviour > Edit > Viewer Request.
The "NoSuchKey" error is now fixed.
To connect it to a domain on Route53, simple point your domain to the CloudFront Domain Name.
Top comments (2)
Good easy to follow setup guide ๐
Thank for the instructions. There is one thing I would like to add here for case how to setup redirect from non-www to www Static website on Amazon S3 and Cloudfront. This can help us further configuration for website use only one domain. Hope that can help!