构建应用程序后,React路由器无法正常工作

时间:2017-04-10 13:33:19

标签: javascript reactjs npm build 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"
  }
}

8 个答案:

答案 0 :(得分:6)

在卡住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>

这已经解决了这个问题。希望它对面临类似问题的其他人有所帮助。

答案 1 :(得分:3)

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

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

最简单的答案是,如果您更改"homepage"的值并将其设置为"",或者将其实际部署到的站点主页的URL,它将直接起作用。

"homepage": "",

OR

"homepage: "mysite.com/",

这就是为什么我认为这很有效:

如果您现在使用react-scripts build,它将创建一个文件build/index.html,该文件将导入JS文件,例如<script src="./static/js/main.9ea6b007.chunk.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来源有何不同? src中的index.html尝试向./static/...请求,而.被解释为当前路由。

因此,假设您要访问localhost:3000/abcd,并希望显示所需的页面。让我们看看这里发生了什么。

  • 您会按预期获得index.html
  • index.html尝试请求./static/...,它转换为localhost:3000/abcd/static/...,而您希望它是localhost:3000/static/...。而且任何非/static的内容都将返回相同的index.html,因此,即使JS文件也返回相同的页面,从而导致控制台错误Uncaught SyntaxError: Unexpected token '<'
  • 如果您使用浏览器Devtools并查看源代码,则所有JS和CSS文件的内容都将与index.html相同。

因此,homepage中的package.jsonindex.html中用作所有静态文件的前缀,格式为<homepage>/static/...。因此,它必须为"",以便将请求发送到/static/..."mysite.com/",以便将请求发送到mysite.com/static/...

答案 2 :(得分:1)

这是一个与Apache有关的问题

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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

试试这个,以这种方式定义路由:

path="/"

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

答案 5 :(得分:0)

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

我发现问题实际上是与响应路由器无关,正如接受的答案的发布者所建议的。 HashRouter会将/#/附加在我们的URL之前,无论如何看起来都不是很漂亮。

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

发生这种情况是因为我们的托管服务提供商(可能是Amazon的S3 / Apache / Google Cloud Platform(GCP)的App Engine / Firebase托管等)不知道要呈现哪个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 Elements动态更新HTML DOM的树,

希望遇到类似问题的人能从中受益。

答案 6 :(得分:0)

最近遇到类似的问题,我的问题有点不同,有些事情无法处理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 />} />
}

答案 7 :(得分:-1)

我面临着同样的问题,阅读了多篇文章,但找不到完美的答案,但这些文章使我对问题有了清晰的了解。因此,我以这种方式解码了问题:

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