React Router BrowserRouter在直接访问子页面时会导致“404 Not Found - nginx”错误,未经过首页点击。

60
我正在为多页面网站使用React Router进行路由。当直接访问子页面https://test0809.herokuapp.com/signin时,会出现"404 Not Found -nginx"错误(要查看此问题,您可能需要在无痕模式下访问此链接以避免缓存)。如果从主页test0809.herokuapp.com/进入,则所有链接均正常工作。我之前使用的是BrowserRouter,但通过将其更改为HashRouter,我能够消除"404未找到"错误,这样所有的URL都会带有"#"标记。但是,除了与URL中带有"#"有关的所有问题外,最大的问题是我需要在我的网站上实现LinkedIn Auth,而LinkedIn OAuth 2.0不允许重定向URL包含#。 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

有关解决方法的任何建议?

背景:我使用create-react-app开始了该项目。GitHub存储库:/debelopumento/test0809

5个回答

89
问题在于nginx不知道如何处理/signin。您需要更改nginx配置(通常在/etc/nginx/conf.d/中),以便无论路由如何,都可以提供index.html。以下是可能有帮助的示例nginx配置:
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;
  }
}

2
疯狂 / 相关的旁注,如果您在使用 envsubst 时忘记转义 $ 符号,则会出现错误,指出“try_files”指令中参数无效。在这种情况下不要忘记转义美元符号,然后就可以继续进行了。我花了30分钟才发现我使用有问题。 - kross
救命之恩,感谢您。 - Codedreamer
真是救命之恩啊!谢谢。 - xbmono
这对我有用,但我必须将 css|scss|js 添加到正则表达式中。谢谢! - Paul Tuckett

33

只需在NGINX配置文件的location /块中添加try_files $uri $uri/ /index.html;即可:

server {
   listen       80;
   server_name  localhost;

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

嗨 @Chhaileng,你能看一下这个问题吗?https://stackoverflow.com/questions/77093374/problem-with-react-browserrouter-inside-drupal-site,这是一个没有index.html的情况。提前感谢你。 - undefined

6

在现场添加此内容

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

0

如果我使用的是Cloud Foundry而不是Heroku怎么办?此外,这是否假定您在根目录下有一个index.html文件?我的顶级index.html位于root/public/index.html中,但它不包含任何路由信息。我的路由由react-router-dom在root/src/app/routeConfig.js中处理。 - E. Oregel

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接