【问题标题】:Deploying react-redux app in AWS S3在 AWS S3 中部署 react-redux 应用程序
【发布时间】:2017-02-08 12:50:13
【问题描述】:

我在堆栈溢出中遇到了很多类似的问题,例如one。每个人对部署 react 应用都有不同的看法。

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

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

【问题讨论】:

    标签: amazon-web-services reactjs amazon-s3 react-router react-router-redux


    【解决方案1】:

    如果有人偶然发现这篇文章,并且由于 history.listen 函数中的无限循环而导致解决方案不起作用;对我来说,解决方案是为 history.replace(path) 调用添加一个小超时。所以它看起来像这样:

        history.listen(location => {
          const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
            if (path) {
              setTimeout(() => {
                history.replace(path);
              }, 100);
            }
          });
    

    【讨论】:

      【解决方案2】:

      您可以通过将第 8 步配置编辑为

      来忽略第 9 步
       <ReplaceKeyPrefixWith>/</ReplaceKeyPrefixWith>
      

      并在 react-router 中使用 browserHistory

      【讨论】:

      • 这对我不起作用,导致无限重定向(例如 hostname.com/////////////path/to/thing
      【解决方案3】:

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

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

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

      5. 确保您对 index.html 中的所有这些 public 文件具有相对引用。

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

      7. 最后,您的 react-redux 应用程序已部署完毕。您所有的反应路线都将正常工作。但是当您重新加载时,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 应用程序中进行的更改。我有我的 ma​​in.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 理解并相应地更改路由。这是我的 ma​​in.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 反应应用程序(app.js 文件)将满足所需的需求。由于我发现很难收集所有的东西,所以我将所有这些都汇总为步骤。

      【讨论】:

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