React Router BrowserRouter leads to "404 Not Found - nginx " error when going to subpage directly without through a home-page click

31,317

Solution 1

The problem is that nginx doesn't know what to do with /signin. You need to change your nginx config (usually in /etc/nginx/conf.d/) to serve your index.html regardless of the route. Here is a sample nginx config that might help:

server {
  listen 80 default_server;
  server_name /var/www/example.com;

  root /var/www/example.com;
  index index.html index.htm;      

  location ~* \.(?:manifest|appcache|html?|xml|json)$ {
    expires -1;
    # access_log logs/static.log; # I don't usually include a static log
  }

  location ~* \.(?:css|js)$ {
    try_files $uri =404;
    expires 1y;
    access_log off;
    add_header Cache-Control "public";
  }

  # Any route containing a file extension (e.g. /devicesfile.js)
  location ~ ^.+\..+$ {
    try_files $uri =404;
  }

  # Any route that doesn't have a file extension (e.g. /devices)
  location / {
    try_files $uri $uri/ /index.html;
  }
}

Solution 2

Just simply add try_files $uri $uri/ /index.html; to location / block in NGINX configuration file like this:

server {
   listen       80;
   server_name  localhost;

   location / {
       root   /build;
       index  index.html;
       try_files $uri $uri/ /index.html;
   }
}

Solution 3

On location add this

location / {
try_files $uri /index.html;
}
Share:
31,317
Di Ye
Author by

Di Ye

Updated on July 09, 2022

Comments

  • Di Ye
    Di Ye almost 2 years

    I am using React Router for routing for a multi-page website. When trying to go to a sub page directly https://test0809.herokuapp.com/signin you'd get a "404 Not Found -nginx" error (To be able to see this problem you might need to go to this link in Incognito mode so there's no cache). All the links work fine if you go from the home page: test0809.herokuapp.com/. I was using BrowserRouter and was able to eliminate the "404 not found" error by changing BrowserRouter to HashRouter, which gives all my urls a "#" sign. Besides all the problems with having a "#" in your urls, the biggest issue with it is that I need to implement LinkedIn Auth in my website, and LinkedIn OAuth 2.0 does not allow redirect URLs to contain #. LinedIn OAuth 2.0 error screen grab

    import React, { Component } from 'react'
    import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
    import LinkedIn from 'react-linkedin-login'
    const Home = () => <div><h2>Home</h2></div>
    const About = () => <div><h2>About</h2></div>
    class Signin extends Component {
      callbackLinkedIn = code => {
        console.log(1, code)
      }
      render() {
          return (
              <div>
                  <h2>Signin</h2>
                  <LinkedIn
                      clientId="clientID"
                      callback={this.callbackLinkedIn}
                  >
              </div>
          )
      }
    }
    const BasicExample = () =>
      <Router>
        <div>
          <ul>
             <li>
               <Link to="/">Home</Link>
             </li>
             <li>
               <Link to="/about">About</Link>
             </li>
             <li>
               <Link to="/signin">Signin</Link>
             </li>
          </ul>
      <hr />
    
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
          <Route path="/signin" component={Signin} />
        </div>
      </Router>
    export default BasicExample
    

    Any suggestions on the workarounds?

    Background: I started the project with create-react-app. GitHub repo: /debelopumento/test0809

  • kross
    kross almost 6 years
    Crazy/related side-note, if you use this with envsubst and forget to escape the $ signs, you get an error stating [emerg] invalid number of arguments in "try_files" directive. Don't forget to escape the dollars in this case and you are good to go. It took me 30 minutes to spot the issue with my usage.
  • E. Oregel
    E. Oregel about 4 years
    What if i'm using cloud foundry not heroku? Also, is this assuming you have an index.html at your root? I have my top level index.html in root/public/index.html, but it doesn't contain any routing information. My routes are handled by react-router-dom in root/src/app/routeConfig.js
  • Codedreamer
    Codedreamer over 2 years
    Life-saving. Thank Man.
  • xbmono
    xbmono almost 2 years
    Life saving indeed! Thanks