在 AWS S3 中部署 react-redux 应用程序

IT技术 amazon-web-services reactjs amazon-s3 react-router react-router-redux
2021-03-29 05:12:13

我已经通过很多的这样的堆栈溢出类似的问题了一个每个人对部署 React 应用程序都有不同的看法。

但这个问题是针对那些使用reduxreact-routerreact-router-redux 的人的我花了很多时间来找出托管单页应用程序的正确方法。我在这里汇总了所有步骤。

我写了下面的答案,其中包含将 react-redux 应用程序部署到 S3 的步骤。

3个回答

有一个用于将 react 应用程序部署到 s3视频教程。这将很容易在 s3 上部署应用程序,但我们需要在我们的 React 应用程序中做一些更改。由于很难遵循,我总结为步骤。它是这样的:

  1. 亚马逊 AWS -> s3 ->创建存储桶
  2. 添加存储桶策略,以便每个人都可以访问 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>/*"
            }
        ]
    }
    
  3. 如果需要日志,请创建另一个存储桶并属性的日志部分下设置存储桶名称

  4. 你需要在一个文件夹中有一个index.html(这是你的应用程序的起点)和error.html以及所有公共资产(浏览过的 reactJS 应用程序和其他 CSS、JS、img 文件)。

  5. 确保您对index.html 中的所有这些公共文件相对引用

  6. 现在,导航到属性->静态网站托管启用网站托管选项。分别index.htmlerror.html添加到字段中。保存后,您将收到Endpoint

  7. 最后,您的react-redux应用程序已部署。您所有的react路线都将正常工作。但是当您重新加载时,S3 将重定向到该特定路线。由于尚未定义此类路由,因此它会呈现error.html

  8. 我们需要在静态虚拟主机下添加一些重定向规则因此,当 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>
    
  9. 在react中,我们需要删除该前缀并将路由推送到原始路由。这是您需要在 React 应用程序中进行的更改。我有我的main.js文件,它是 react 应用程序的起点。像这样browserHistory添加一个监听器

    browserHistory.listen(location => {
      const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
      if (path) {
          history.replace(path);
       }
     });
    
  10. 上面的代码将删除前缀并将历史推送到正确的路由(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 文件)将满足所需的需求。由于我发现很难收集所有内容,因此我将所有这些汇总为步骤。

@lakshmandiwaakar 实际上又在为此苦苦挣扎,散列路由不太适用。你能帮我解决这个问题吗?如果我按照您的指示操作,history.replace 函数将被无限调用,并且从 #!/ 中删除 / 会阻止事情发生。
2021-05-23 05:12:13
嗨,我只是按照这些步骤操作,其他一切都可以正常工作,除了现在当我重新加载页面时,#! 前缀不会被 / 替换,页面开始执行 infine history.replace() 调用。您能否提供任何见解,为什么会发生这种情况?我正在使用历史库中的 createBrowserHistory 函数,因为 recat-router 4 不再具有 browserHistory 函数。
2021-05-25 05:12:13
您能否为 React 4 / Router 4.1 版本库的 browserHistory.listen 部分提供帮助?
2021-05-30 05:12:13
实际上是通过删除 #! 之后的 / 部分来实现的。来自重定向规则中的 ReplaceKeyPrefixWith 标记。不过会赞成答案,因为没有其他 SO aswer 能很好地指出这个问题。
2021-05-31 05:12:13
我只是在这方面经历了一些挫折。现在是 2020 年,S3 允许自定义索引和错误解析为 index.html,无需 RoutingRules(第 8 步)和 React 16.12+ 和 React-Router 5.x。剩下的一个问题是请求的文档收到 404 或其他 4xx,即使应用程序在其他方面正常工作。如果您设置了 CloudFront,并且您的 CloudFront 域上只有您的 React SPA,您可以设置错误页面以使用 200 HTTP 响应代码进行响应。
2021-06-13 05:12:13

如果有人偶然发现这篇文章,并且由于 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

这对我不起作用,导致无限重定向(例如 hostname.com//////////////path/to/thing
2021-05-27 05:12:13