Hosting React App on S3 + CloudFront with React-Router (404 Fix)

React Application, by Antonio Batinić at Pexels

One of the advantages of building a static-front end application in React is the ability to cache and serve it using AWS S3 and CloudFront. This allows for some pretty awesome performance as well as some great cost savings. This works perfectly well for single page applications, but you may run into several small issues when routing on the front-end.

The Dreaded 404

If you split your application into multiple front-end routes, using libraries such as react-router or @reach/router, your application will appear to work perfectly at first. Unfortunately, if you refresh the page or copy/paste a url that includes a route, such as /about, you will get a 404 error. This is because there is no directory titled ‘about’ located within your S3 bucket to serve from. Because the route does not exist, the JavaScript bundle is not loaded, and the front-end static routing is never resolved.

When I was looking for a resolution to this, I noticed quite a few people suggesting to just change the Error Document field on your S3 Bucket’s Static Web Hosting settings to index.html. This tells S3 to serve the index.html file every time that there is a 404 error. The JavaScript bundle is loaded, and the front-end route is read by your static routing library. Everything is perfect…or is it?

Redirecting Error back to index.html – DON’T DO THIS!

The Fix That Broke Something Else

If you redirected your Error Document back to index.html, you will notice that your static routing works correctly, but you will still be dealing with a 404 error. In your console, you will still most likely be seeing something like Failed to load resource: the server responded with a status of 404 () whenever you try to load a route, such as /about, within your application. Receiving a 404 error, even when your application works, can cause search engines to avoid indexing the site. On top of that, if you try to audit in Google chrome, it will tell you that something is wrong very quickly.

Lighthouse receiving a 404 error

A Proper Fix

Now that we know what not to do, let’s talk about the proper way to fix this application. What we need to do first is login to AWS and open up your CloudFront distribution for our React App. In the top tabs, click on Error Pages.

On this page, you want to click Create Custom Error Response. This will allow us to specify handling for a 404 error. Here you will want to enter the following settings:

  • HTTP Error Code – 404: Not Found
  • TTL – 60s
  • Customize Error Response – Yes
  • Response Page Path – /index.html
  • HTTP Response Code – 200: OK
404 Redirect Settings in CloudFront

Click Yes, Edit to save your settings, and you should be good to go!

(Optional): If you are still getting a 404 error, you may need to create an invalidation for your CloudFront cache. By clicking the Invalidations tab, clicking Create Invalidation and entering the path to your React Application (I used /* to invalidate all paths).

A picture says a thousand words – CloudFront Invalidation

Once the cache has cleared and updated on your CloudFront distribution, your 404 errors should go away, and your static routing should work as expected!