So you finally deploy your React app to Vercel. It works. You click around, everything's smooth. Then you navigate to another page, hit refresh and…
Boom. 404 Page Not Found.
You're sitting there like "It literally worked two seconds ago. I didn't change anything. What is happening?"
Let me explain what's going on, and more importantly, how to fix it without losing your mind.
What's Actually Happening Here
Your React app uses React Router to handle navigation. When you click a link to /about
or /profile
, React quietly swaps the content on your screen without actually loading a new page from the server. It's smooth, it's fast, it's great.
But here's the problem.
When you hit refresh on /about
, your browser asks Vercel's server: "Hey, give me the /about
page."
And Vercel's like: "About? I don't have a file or folder called 'about.' Here's a 404 instead."
See, Vercel is looking for actual files and folders. But /about
doesn't exist as a file. It only exists in your React Router configuration, which lives in JavaScript that hasn't run yet because... well, you got a 404 before React could even load.
Classic catch-22.
The Fix (Seriously, Takes 2 Minutes)
You need to tell Vercel: "Listen, no matter what URL someone visits, just serve them the main React app. Let React figure out the routing."
Here's how:
Step 1: In your project folder (where package.json
lives), create a file called vercel.json
Step 2: Paste this in:
{
"rewrites": [
{ "source": "/(.*)", "destination": "/" }
]
}
Step 3: Save it. Push to GitHub (or wherever your code lives).
Step 4: Redeploy on Vercel.
That's it. Go test it. Navigate to any page, hit refresh. It works now.
What this config does is tell Vercel "For every route someone tries to access, serve them the main index.html file." Then React Router takes over and shows the right page.
The Quick-and-Dirty Alternative
If you're in a rush and don't want to mess with config files, there's another option.
Change this in your code:
import { BrowserRouter } from "react-router-dom";
To this:
import { HashRouter } from "react-router-dom";
This makes your URLs look like /#/about
instead of /about
. The refresh issue goes away, but your URLs are uglier and search engines don't love them.
It's like fixing a broken chair by just sitting on the floor. Technically works, but not ideal.
Use this only if you're desperate or don't have access to deploy config files.
Why This Happens to Everyone
You didn't mess up. This trips up tons of developers, even experienced ones.
It's just one of those things where your local development environment and production hosting don't work the same way. On your local machine with npm start
, the dev server handles this automatically. But when you deploy? Different story.
Now you know. And next time someone in your Discord or Slack freaks out about this exact issue, you can swoop in with the answer and look like a genius.
The Takeaway
Single Page Apps (SPAs) like React are amazing, but they need a little help when it comes to server-side routing. One tiny config file fixes it permanently.
Bookmark this post. You'll probably need it again, or someone you know will.
Got other React deployment headaches? Drop them in the comments. I've probably run into them too, and misery loves company.
Now go refresh that page with confidence.
Originally published on My Blog
Top comments (0)