september 16, 2023

{ react router and netlify deployment }


tags: netlify, servers and deployment

Timing can be funny, but it this case, it was perfect. I discovered I was having a problem with 404s on Netlify last night. Before I got the time to look into it, the lecture we had today was on deploying a React site on Netlify and the steps to make React Router work in production.

If only all my bugs could be solved that way.

Why Netlify Returns a 404 on React Router URLs

This is a React site and I'm using React Router to define the URLs for individual pages, such as /blog and each of the blog posts. It works great for navigating around the site using links and the nav bar.

But I was forgetting one key thing.

With React Router links, we stay in the context of the BrowserRouter and the URLs React Router provides. We are never making a request to the server for a particular URL.

This is not the case when we enter something in the URL bar. Or, in my case last night, refresh /blog page to see if I could get the API call to work. In these instances, the browser is saying, "Send me whatever resource you have at /blog." To which Netlify answers, "I don't have anything there. Here's a 404." There is nothing there because I have an SPA. There are no individual pages.

This isn't just a Netlify problem, but the solution depends on which deployment method you're using. Since I'm on Netlify, that's what I'll go over here.

Accessing URLs on an SPA on Netlify

Admittedly I sat through the lecture on deployment several months ago, but apparently I forgot this key piece. How great it was to then get a second chance reminder today. To fix my issue, I:

  • Added a file called _redirects to the root of my project
  • Added the line /* /index.html 200 to the file
  • In Netlify, I went to my site > Site Configuration > Build & Deploy, and then updated the Build Command to be npm run build && cp _redirects build
  • Pushed all changes to GitHub

My site redeploys after any pushes, so that had it fixed in a couple minutes. What is happening here is this:

  • /* is a wildcard to listen for all subdirectories on my domain
  • We then tell Netlify to return /index.html (the entirety of our SPA) and a 200 status code for those URLs
  • At this point, React Router can take over and render the correct components

I did Google this issue shortly after and it does seem to be an easy to miss one. Hopefully writing this out means I will not forget it on my next deploy!