如何S3 + Cloudfrond + 2 SPA对子文件夹中的应用程序做出反应?

stp*_*poa 7 amazon-s3 amazon-cloudfront single-page-application reactjs react-router

我想使用 S3 + Cloudfront 在子文件夹中提供 2 个不同的 React 应用程序

myapp.com/app-one/<-- 这是index.html
myapp.com/app-two/<-- 这是另一个index.html

我知道如何配置 create-react-app 和 React router 来处理这个问题。
https://create-react-app.dev/docs/deployment/#building-for-relative-paths

问题在于配置 S3 + Cloudfront 来处理重定向。

当您在浏览器中输入 url 时:
myapp.com/app-one/some-route- 它应该重定向到index.html of app-one
myapp.com/app-two/some-route- 它应该重定向到index.html ofapp-two

不幸的是,S3 只允许您定义一个后备file.html( 404)Static website hosting

我也不想使用 hashrouter:https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/api/HashRouter.md

reo*_*sed 4

我在一个角度应用程序中遇到了同样的问题,并找到了一些解决方案,但我发现最有用的一个是使用 Lambda@Edge 函数,这允许您将静态文件保存在 S3 存储桶中,而无需打开静态文件托管。

唯一对我有用的 Lambda@Edge 配置是此答案中的配置。这是代码:

var path = require('path');

exports.handler = (event, context, callback) => {
  // Extract the request from the CloudFront event that is sent to Lambda@Edge
  var request = event.Records[0].cf.request;

  const parsedPath = path.parse(request.uri);

  // If there is no extension present, attempt to rewrite url
  if (parsedPath.ext === '') {
    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/second-app.*/, 'second-app/index.html');

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;
  }
  // If an extension was not present, we are trying to load static access, so allow the request to proceed
  // Return to CloudFront
  return callback(null, request);
};
Run Code Online (Sandbox Code Playgroud)

它的基本作用是匹配子文件夹的 uri 并将所有请求重定向到正确的index.html文件。如果您有多个子文件夹,您可以简单地添加一些条件:

var path = require('path');

exports.handler = (event, context, callback) => {
  // Extract the request from the CloudFront event that is sent to Lambda@Edge
  var request = event.Records[0].cf.request;

  const parsedPath = path.parse(request.uri);

  // If there is no extension present, attempt to rewrite url
  if (parsedPath.ext === '') {
    // Extract the URI from the request
    var olduri = request.uri;
    var newuri = olduri
    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    if(olduri.match(/first-sub-app.*/)){
        newuri = olduri.replace(/first-sub-app.*/, 'first-sub-app/index.html');
    } else if(olduri.match(/second-sub-app.*/)){
        newuri = olduri.replace(/second-sub-app.*/, 'second-sub-app/index.html');
    }

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;
  }
  // If an extension was not present, we are trying to load static access, so allow the request to proceed
  // Return to CloudFront
  return callback(null, request);
};
Run Code Online (Sandbox Code Playgroud)

检查原始答案以获取有关设置的进一步说明以及有关其工作原理的更多详细信息,但它基本上会忽略任何带有扩展名的请求,并且仅在与特定子目录匹配时才进行重定向。