我在堆栈溢出中遇到了很多类似的问题,如one。每个人都有不同的角度来部署反应应用程序。
但是这个问题适用于使用 redux , react-router 和 react-router-redux 的用户。我花了很多时间来确定托管单页面应用程序的正确方法。我正在汇总这里的所有步骤。
我写了以下答案,其中包含将react-redux app部署到S3的步骤。
答案 0 :(得分:20)
有一个video教程,用于将反应应用程序部署到s3。这将很容易在s3上部署应用程序,但我们需要在我们的反应应用程序中进行一些更改。由于很难遵循,我总结为步骤。在这里:
添加存储桶策略,以便每个人都可以访问react应用。点击创建的广告管理 - > 属性 - >的权限即可。在该单击编辑存储桶策略。以下是存储桶策略的示例。
{
"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 中的所有公开文件有相对引用。
现在,导航至属性 - &gt; 静态网站托管。启用网站托管选项。分别在字段中添加 index.html 和 error.html 。保存时,您将收到端点。
最后,部署了 react-redux 应用。您的所有反应路线都将正常运行。但是当您重新加载时,S3将重定向到该特定路线。由于尚未定义此类路线,因此会呈现 error.html
我们需要在静态网站托管下添加一些重定向规则。因此,当404发生时,S3需要重定向到 index.html ,但这只能通过添加一些前缀来完成,例如#!。现在,当您使用任何反应路线重新加载页面时,而不是转到 error.html ,将加载相同的网址,但前缀为#!。点击编辑重定向规则,然后添加以下代码:
<RoutingRules>
<RoutingRule>
<Condition>
<HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
</Condition>
<Redirect>
<HostName> [YOUR_ENDPOINT] </HostName>
<ReplaceKeyPrefixWith>#!/</ReplaceKeyPrefixWith>
</Redirect>
</RoutingRule>
</RoutingRules>
在做出反应时,我们需要删除该前缀并将路由推送到原始路由。以下是您在反应应用中需要做的更改。我有 main.js 文件,这是反应应用程序的起点。像这样添加一个 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);
}
});
因此,上传browserified或webpacked react应用程序(app.js文件)将满足所需的需求。由于我发现难以收集所有内容,因此我将所有这些内容汇总为步骤。
答案 1 :(得分:0)
如果有人偶然发现了此帖子,并且由于history.listen函数中的无限循环而导致解决方案不起作用;对我来说,解决方案是为history.replace(path)调用添加一个小的超时。所以看起来像这样:
history.listen(location => {
const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
if (path) {
setTimeout(() => {
history.replace(path);
}, 100);
}
});
答案 2 :(得分:-2)
您可以通过将第8个配置编辑为
来忽略第9步 <ReplaceKeyPrefixWith>/</ReplaceKeyPrefixWith>
并在react-router
中使用browserHistory