构建应用程序后反应路由器不起作用

Posted

技术标签:

【中文标题】构建应用程序后反应路由器不起作用【英文标题】: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 页面。 【参考方案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.htmlindex.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】:

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

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

【讨论】:

【参考方案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 组件。

以上是关于构建应用程序后反应路由器不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为什么webpack构建后我的react-routing不起作用?

反应路由器导航不起作用

反应路由器 v4 重定向不起作用

react-router-dom BrowserRouter在构建后不起作用

反应路由器+ webpack,子路由不起作用

部署到 Springboot 应用程序后,角度路由不起作用