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

Deploying react-redux app in AWS S3

我在堆栈溢出中遇到过很多类似的问题 one。每个人对部署 React 应用程序都有不同的看法。

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

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

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

  1. Amazon AWS -> s3 -> 创建存储桶.
  2. 添加bucket policy,让所有人都能访问react app。单击 创建的存储桶 -> 属性 -> 权限。在其中单击 编辑存储桶策略 。这是存储桶策略的示例。

    {
        "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 和文件夹中的所有 public 资产(浏览器化的 reactJS 应用程序和其他 CSS、JS、img 文件)。

  5. 确保你有相对引用所有这些public文件在index.html.

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

  7. 最后,您的 react-redux 应用已部署。你所有的反应路线都会正常工作。但是当您 reload 时,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 文件,这是反应应用程序的起点。像这样向 browserHistory 添加监听器:

    browserHistory.listen(location => {
      const path = (/#!(\/.*)$/.exec(location.hash) || [])[1];
      if (path) {
          history.replace(path);
       }
     });
    
  10. 以上代码会去掉前缀并将历史推送到正确的路由(HTML 5 浏览器历史)。例如:像这样的 http://s3.hosting/#!/event will change to 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);
       }
     });
    

因此上传浏览器化或网络打包的 React 应用程序(app.js 文件)将满足要求。由于我发现很难收集所有的东西,所以我将所有这些汇总为步骤。

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

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

并在 react-router 中使用浏览器历史记录

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

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