【问题标题】:React router not working after building the app构建应用程序后反应路由器不起作用
【发布时间】:2017-09-05 14:01:58
【问题描述】:

我是 react 和 react-router 的新手。该应用程序是使用create-react-app 创建的。我需要在我的应用程序中使用两个主要页面实现路由。我尝试了很多选项,最后使它与以下代码一起工作。

此代码在开发过程中运行良好。但是在构建应用程序后,它无法正常工作。仅显示到 404 页面的路由。请帮我解决这个问题。

<Router history={browserHistory}>
  <Route component={Root}>
    <IndexRoute component={App} />
    <Route path="/" component={App} />
    <Route path="/sna/:country" component={SNA} />
    <Route path="*" component={FourOFour}/>
  </Route>
</Router>

我已使用browserHistory 启用导航以使用以下代码更改下拉菜单。

selectCountry(event){
    var value = event.target.value;
    browserHistory.push('/sna/' + value);
}

package.json

  {
  "name": "my-app",
  "version": "0.1.0",
  "homepage": "./",
  "private": true,
  "dependencies": {
    "bootstrap": "^3.3.7",
    "react": "^15.4.2",
    "react-addons-update": "^15.4.2",
    "react-bootstrap": "^0.30.8",
    "react-data-grid": "^2.0.24",
    "react-dom": "^15.4.2",
    "react-router": "^2.6.0"
  },
  "devDependencies": {
    "react-scripts": "0.9.5"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

【问题讨论】:

  • 在不知道您的构建+服务器设置的情况下,很难为您提供任何帮助。你的开发环境和生产环境一样吗?意思是,您是否使用相同的服务器(配置)来托管您的应用程序?
  • @SebastianSebald 我使用 create-react-app 创建了应用程序。 package.json 内容也被添加到问题中。如果您需要更多信息,请告诉我。
  • 这很有帮助。您使用什么服务器来托管构建结果?是否支持push
  • 我想与客户共享可以在本地打开的包。(类似于通常的 UI 代码:HTML + JS)。另外,我认为问题不是因为push 方法。因为在应用加载时会显示空白页面。理想情况下,它应该在App 组件中打开页面。相反,它被路由到我的自定义 404 页面。

标签: javascript reactjs npm build react-router


【解决方案1】:

如果未为 Apache 启用重写模块,也会出现此问题。 您可以通过执行来启用它:

sudo a2enmod rewrite

【讨论】:

    【解决方案2】:

    编辑:

    最好的方法是使用公共 URL,它将被部署为 Router 组件中的 basename 属性。它也可以是 PUBLIC_URL=myproject 之类的东西,并且假设应用程序在 https://&lt;domain-name&gt;/myproject/index.html 上提供服务,它将进行构建。

    <Router basename={process.env.PUBLIC_URL}>
    ...
    </Router>
    

    旧答案:

    首先,这不是 React Router 的问题。请注意,在您的 package.json 中,您有:

      "homepage": "./",
      "private": true,
    

    简短的回答是,如果您将"homepage" 的值更改为"",或者实际部署它的站点主页的URL,它将直接起作用。

    "homepage": "",
    

    "homepage": "mysite.com/",
    

    这就是我认为它有效的原因,详细说明:

    如果你现在使用react-scripts build,它会创建一个文件——build/index.html,它会导入像&lt;script src="./static/js/main.9ea6b007.chunk.js"&gt;这样的JS文件。

    现在,当您使用 react-router 时,您最好将所有请求路由到 build/index.html。因此,您可以构建一个代理服务器来为您的index.html 和静态文件提供服务,如下所示(使用 Express.js):

    const express = require('express');
    const path = require('path');
    const bodyParser = require('body-parser');
    
    const app = express();
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json());
    
    app.use(express.static(path.join(__dirname, 'build')));
    
    app.use('/', (req, res) => {
      res.sendFile(path.join(__dirname, 'build/index.html'));
    });
    
    app.listen(process.env.PORT || 3000, () => console.log(`Running on PORT ${process.env.PORT || 3000}`));
    

    现在您看到所有请求(静态文件除外)都返回了index.html 文件。因此,当您请求/static/js/main.9ea6b007.chunk.js 时,您的所有 JS 和 CSS 文件都将返回。请注意这与您的 index.html 源中的内容有何不同? index.html 中的src 尝试从./static/... 请求,. 被解释为当前路由。

    假设您访问localhost:3000/abcd 并期待您想要的页面出现。让我们看看这里发生了什么。

    • 如您所愿,您会收到index.html
    • index.html 尝试请求 ./static/...,它转换为 localhost:3000/abcd/static/...,而您希望它是 localhost:3000/static/...。任何不是/static 的东西都会返回相同的index.html,因此即使是JS 文件也会返回相同的页面,从而导致控制台错误Uncaught SyntaxError: Unexpected token '&lt;'
    • 如果您访问浏览器 Devtools 并查看源代码,您的所有 JS 和 CSS 文件的内容将与 index.html 相同。

    因此,package.json 中的homepageindex.html 中用作所有静态文件的前缀,格式为&lt;homepage&gt;/static/...。因此,它需要是"",以便请求发往/static/..."mysite.com/",因此请求发往mysite.com/static/...

    【讨论】:

    • 好人!添加带有 URL、&lt;Router basename={process.env.PUBLIC_URL}&gt;.htaccess 文件的 "homepage" 变量以强制对 index.html 文件的所有请求解决了我的问题。谢谢
    【解决方案3】:

    这是与服务器相关的问题

    对于 Apache 服务器:

    确保您的 Apache 服务器将每个请求重定向到 index.html 文件。确保 .htaccess 中存在以下代码

    Options -MultiViews
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.html [QSA,L]
    

    【讨论】:

      【解决方案4】:

      最近遇到类似的问题,我的问题有点不同,不能处理 HashRouter 或服务器配置...

      我最初是使用 render props 方法来渲染这样的路由组件

      <Route
         path={route.path}
         render={(props) => (
           <route.component {...props} routes={route.routes} />
         )}
      />
      

      当我转换为像这样渲染子方法时

      <Route path={route.path} key={route.path} children={<route.component />} />
      

      成功了

      因此我的最终路由器设置如下所示

      const routerConfig = [
        {
          path: '/billing',
          component: ComponentA,
          linkName: 'BILLING',
        },
        {
          path: '/update-price',
          component: ComponentB,
          linkName: 'PRICE UPDATE',
        },
      ]
      
      const MainPage = () => {
        return (
            <Switch>
              {routerConfig.map((route) => (
                <RouteWithSubRoutes key={route.path} {...route} />
              ))}
            </Switch>
        )
      }
      
      function RouteWithSubRoutes(route) {
        return <Route path={route.path} key={route.path} children={<route.component />} />
      }
      
      

      【讨论】:

        【解决方案5】:

        我遇到了同样的问题并阅读了多篇文章,但找不到完美的答案,但这些文章让我对这个问题有了清晰的了解。所以,我用这种方式解码了我的问题:

        1. React 是一个单页应用框架
        2. 加载网页时加载 index.html
        3. 从索引中,我们加载与 URL 匹配的 [router]react-router-dom。
        4. 在 localhost 中一切正常,但在我们构建应用程序时无法在生产环境中运行。
        5. 到这里为止没有任何问题,所以它是我们使用的完整托管服务。
        6. 就我而言,我使用了 firebase 托管,并且我已将所有内容重定向到 build/index.html
        7. 问题解决了!!

        【讨论】:

          【解决方案6】:

          对我来说,Lili Susan V 的解决方案适用于我的代码:

          import { HashRouter as Router } from 'react-router-dom';
          

          【讨论】:

          • 它确实有效。但是,如果您注意到您的 URL,您的 URL 将附加一个棋子“#”符号。如果你不介意链接的美感,你绝对可以使用这种方法。但是,它并没有解决问题的根源。我已经在上面的回答中解释了问题的根源。
          【解决方案7】:

          当我在 Firebase Hosting 上部署我的 React 应用程序时,我最初遇到了类似的问题。

          事实证明,问题实际上与已接受答案的发布者所建议的反应路由器无关。 HashRouter 会在我们的 URL 前面附加 /#/,无论如何,这看起来并不漂亮。

          我发现问题出在我们使用的网络托管服务上。我们需要指明我们想要呈现的默认 HTML 文件,即 index.html

          发生这种情况是因为我们的托管服务提供商(无论是 Amazon 的 S3 / Apache / Google Cloud Platform (GCP) 的 App Engine / Firebase Hosting 等) 不知道要呈现哪个 HTML 文件如果给出了默认 URL (https://www.link_to_your_website.com) 以外的 URL。例如,它将无法识别https://www.link_to_your_website.com/login

          在 Firebase 托管中,您需要执行以下操作:

          "rewrites": [ {
              "source": "**",
              "destination": "/index.html"
          }]
          

          在 Apache 的 .htaccess 中,您需要这样做:

          FallbackResource /index.html
          

          来源:How to redirect an error 404 to home page with .htaccess?

          这些命令将告诉他们无论如何渲染 index.html,因为 React-Route 将使用新的 React 元素动态更新 HTML DOM 树。

          希望那些遇到类似问题的人觉得这很有帮助。

          【讨论】:

            【解决方案8】:

            react-router 卡住了几天后,我阅读了React Training 中的文档。然后我按照快速入门步骤进行了修改以满足我的要求。

            import {
              HashRouter as Router,
              Route,
              } from 'react-router-dom';
            
              <Router>
                <div>
                  <Header />
                  <Route exact path="/" component={Content} />
                  <Route path="/:country" component={SnaContent} />
                  <Footer />
                </div>
              </Router>
            

            这暂时解决了这个问题。希望对遇到类似问题的其他人有所帮助。

            【讨论】:

            • 我在将 React 应用程序部署到 Firebase 托管时遇到了类似的问题。我发现问题实际上不在于反应路由器。问题在于我们使用的网络托管服务。我们需要指明我们想要呈现的默认 html 文件,即 index.html。
            • 修复我使用 HashRouter 而不是 BrowserRouter。
            【解决方案9】:

            试试这个,这样定义路由:

            <Router history={browserHistory}>
               <Route path="/" component={Root}>
                  <IndexRoute component={App} />
                  <Route path="/sna/:country" component={SNA} />
                  <Route path="*" component={FourOFour}/>
               </Route>
            </Router>
            

            原因:你需要通过path="/"定义主路由Root的路径,并且你不需要为App组件定义单独的路由,它已经是你的IndexRoute。每当您导航到/ 时,它都会呈现App 组件。

            【讨论】:

            • 感谢您的信息。但是一旦我们构建了应用程序,您的代码就不起作用了。我不明白为什么它会路由到 404 页面而不是 App 组件。
            猜你喜欢
            • 2020-09-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-02-04
            • 2021-09-08
            • 2015-11-25
            • 2017-02-24
            • 1970-01-01
            相关资源
            最近更新 更多