我已经通过很多的这样的堆栈溢出类似的问题了一个。每个人对部署 React 应用程序都有不同的看法。
但这个问题是针对那些使用redux、react-router和react-router-redux 的人的。我花了很多时间来找出托管单页应用程序的正确方法。我在这里汇总了所有步骤。
我写了下面的答案,其中包含将 react-redux 应用程序部署到 S3 的步骤。
我已经通过很多的这样的堆栈溢出类似的问题了一个。每个人对部署 React 应用程序都有不同的看法。
但这个问题是针对那些使用redux、react-router和react-router-redux 的人的。我花了很多时间来找出托管单页应用程序的正确方法。我在这里汇总了所有步骤。
我写了下面的答案,其中包含将 react-redux 应用程序部署到 S3 的步骤。
有一个用于将 react 应用程序部署到 s3的视频教程。这将很容易在 s3 上部署应用程序,但我们需要在我们的 React 应用程序中做一些更改。由于很难遵循,我总结为步骤。它是这样的:
添加存储桶策略,以便每个人都可以访问 react 应用程序。单击创建的存储桶->属性->权限。在该点击Edit bucket policy。以下是存储桶策略的示例。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Allow Public Access to All Objects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/*"
}
]
}
如果需要日志,请创建另一个存储桶并在属性的日志部分下设置存储桶名称。
你需要在一个文件夹中有一个index.html(这是你的应用程序的起点)和error.html以及所有公共资产(浏览过的 reactJS 应用程序和其他 CSS、JS、img 文件)。
确保您对index.html 中的所有这些公共文件有相对引用。
现在,导航到属性->静态网站托管。启用网站托管选项。分别将index.html和error.html添加到字段中。保存后,您将收到Endpoint。
最后,您的react-redux应用程序已部署。您所有的react路线都将正常工作。但是当您重新加载时,S3 将重定向到该特定路线。由于尚未定义此类路由,因此它会呈现error.html
我们需要在静态虚拟主机下添加一些重定向规则。因此,当 404 发生时,S3 需要重定向到index.html,但这只能通过添加一些前缀来完成,例如#! . 现在,当您使用任何 react 路由重新加载页面时,不会转到error.html,而是会加载相同的 url 但带有前缀#! . 单击编辑重定向规则并添加以下代码:
<RoutingRules>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<HostName> [YOUR_ENDPOINT] </HostName>
<ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
</RoutingRules>
在react中,我们需要删除该前缀并将路由推送到原始路由。这是您需要在 React 应用程序中进行的更改。我有我的main.js文件,它是 react 应用程序的起点。像这样向browserHistory添加一个监听器:
browserHistory.listen(location => {
const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
if (path) {
history.replace(path);
}
});
上面的代码将删除前缀并将历史推送到正确的路由(HTML 5 浏览器历史)。例如:像这样http://s3.hosting/#!/event将更改为http://s3.hosting/event。这样做会使react-router理解并相应地更改路由。这是我的main.js文件,以便更好地理解:
import React from 'react';
import ReactDOM from 'react-dom';
import {createStore, compose, applyMiddleware} from 'redux';
import {Provider} from 'react-redux'
import {Router, Route, IndexRoute, browserHistory, useRouterHistory} from 'react-router';
import {syncHistoryWithStore} from 'react-router-redux';
import createLogger from 'redux-logger';
import thunk from 'redux-thunk';
const logger = createLogger();
const createStoreWithMiddleware = applyMiddleware(thunk, logger)(createStore);
const store = createStoreWithMiddleware(reducers);
const history = syncHistoryWithStore(browserHistory, store);
browserHistory.listen(location => {
const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
if (path) {
history.replace(path);
}
});
因此,上传浏览器化或 webpacked react 应用程序(app.js 文件)将满足所需的需求。由于我发现很难收集所有内容,因此我将所有这些汇总为步骤。
如果有人偶然发现这篇文章,并且由于 history.listen 函数中的无限循环而导致解决方案不起作用;对我来说,解决方案是为 history.replace(path) 调用添加一个小的超时时间。所以它看起来像这样:
history.listen(location => {
const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
if (path) {
setTimeout(() => {
history.replace(path);
}, 100);
}
});
您可以通过编辑第 8 个配置来忽略第 9 个步骤
<ReplaceKeyPrefixWith>/</ReplaceKeyPrefixWith>
并在 react-router 中使用 browserHistory