构建应用程序后反应路由器不起作用
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://<domain-name>/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
,它会导入像<script src="./static/js/main.9ea6b007.chunk.js">
这样的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 '<'
。
如果您访问浏览器 Devtools 并查看源代码,您的所有 JS 和 CSS 文件的内容将与 index.html
相同。
因此,package.json
中的homepage
在index.html
中用作所有静态文件的前缀,格式为<homepage>/static/...
。因此,它需要是""
,以便请求发往/static/...
或"mysite.com/"
,因此请求发往mysite.com/static/...
。
【讨论】:
好人!添加带有 URL、<Router basename=process.env.PUBLIC_URL>
和 .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不起作用?