React Router v4部署Heroku后直接访问路由/history.push出现404问题求助
Hey there, let's get that routing issue sorted out!
The Root Cause
When you use BrowserRouter in your React app, all routing happens on the client side—meaning React handles navigating between pages without asking the server for new files. But here's the problem: when you type /login directly into the address bar, Heroku's web server tries to find a physical file at that path (which doesn't exist, since your app is a single-page app with only one index.html). That's why you get a 404. When you click the Login button, history.push() handles the navigation entirely in the browser, so it skips the server and works perfectly.
Solution 1: Configure Heroku to Support Client-Side Routing (Recommended)
This method keeps your clean URLs (no extra # characters) and is the standard fix for Create React App deployments on Heroku.
- Create a
static.jsonfile in your project's root directory with this content:
{ "root": "build/", "clean_urls": false, "routes": { "/**": "index.html" } }
This tells Heroku's server to redirect every request to your app's index.html, letting React handle the routing from there.
- Commit the file to Git and redeploy to Heroku:
git add static.json git commit -m "Configure server to redirect all requests to index.html for client-side routing" git push heroku main
Solution 2: Switch to HashRouter (Quick Fix)
If you want a faster workaround without configuring the server, you can replace BrowserRouter with HashRouter. This adds a # to your URLs (like placemate.herokuapp.com/#/login), which tells the server to only care about the path before the #—the rest is handled by React.
Update your index.js file:
import React from 'react'; import ReactDOM from 'react-dom'; import { HashRouter } from 'react-router-dom'; import App from './App'; import registerServiceWorker from './registerServiceWorker'; ReactDOM.render( <HashRouter> <App /> </HashRouter>, document.getElementById('root') ); registerServiceWorker();
Then redeploy your app to Heroku, and direct URL access should work.
Which Should You Choose?
Go with Solution 1 if you want clean, user-friendly URLs. Solution 2 is great for testing or if you don't want to mess with server configs, but the # in the URL can feel clunky for production apps.
内容的提问来源于stack exchange,提问作者J Dorrian

