Deploy React SPA to CloudFront and S3
Tags: aws, cloudfront, s3, react
Published: 2022-08-06 09:10:10

---
title: Deploy React SPA to CloudFront and S3
published: true
description: Deploying a react single page application on CloudFront, S3 and direct a Route53 domain to the CloudFront Distribution. 
tags: #aws #cloudfront #s3 #react
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
---

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](https://developer.mozilla.org/en-US/docs/Glossary/SPA).

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.![Origin Domain](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9i8uavxav77wjt2eamft.png)
- 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`. ![Alternate CNAME](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lji9juydki2mufnelbas.png)
- 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`. ![Default Root Object](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/01dvmic4xplabt4s875l.png)
- 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.

```json
{
	"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".
![NoSuchKey Error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0iyj26q59harhp9vhrlj.png) 

### 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.
![CloudFront Behaviour](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tglz6zlv3e9rg7qlqnjc.png)

The "NoSuchKey" error is now fixed.
To connect it to a domain on Route53, simple point your domain to the CloudFront Domain Name.