首页 > 解决方案 > Gatsby 公用文件夹结构不能很好地与 S3 静态网站托管配合使用

问题描述

所以,假设我有一个没有后端的简单 Gatsby 网站,只有两页的纯文本,index并且about-us

现在当我运行时gatsby build,公用文件夹结构是这样的:

├── index.html
├── about-us
│   ├── index.html

问题是,这种结构不能很好地与 S3 配合使用,如果我向 发出请求mywebsite.com/about-us,它实际上会返回 404。启用静态托管的 S3 不会自动路由到mywebsite.com/about-us/index.html,尽管如果我手动浏览到该页面它会工作,但是有这样的路线是一场噩梦。

问题是,Gatsby 中是否有一些配置使其不会生成这样的子文件夹?而只是about-us.html在根文件夹中创建一个?

所以,我想实现以下目标:

├── index.html
├── about-us.html

我的 src/pages 结构如下:

├── index.tsx
├── about-us.tsx

标签: amazon-s3gatsby

解决方案


有一个gatsby 插件可以满足您的要求,但请确保您设置了规范 url 以防止搜索引擎记录重复的内容。

这在 gatsby 和 next js 中很常见(启用了斜杠和静态导出)。它们会按照您的描述静态构建站点,/path/index.html并通过路径路由到路径/path/(注意尾部斜杠)。

最简单的完整且非插件的解决方案是将您的 S3 站点放在CloudFront 分配后面,并添加一个 lambda 函数以将所有流量重定向到正确的路由。我已经在一些小型网站上运行了这个,我的账单每月不到 1 美元。

这是Gatsby文档,但他们使用 CLI,该页面底部还有其他参考资料。

这是有关如何使用 CloudFront 分发创建静态站点的AWS 文档。

安装 CloudFront 后,您需要创建一个 lambda 函数以在后台重定向/route//route/index.html但显示/route/在 URL 中并设置适当的权限。

  1. 转到 lambda 并使用节点 14.xx 从头开始​​创建一个新函数
  2. 单击 index.js 旁边的图标
  3. 剪切并粘贴下面的代码并保存

Lambda 函数 - 该函数将非尾斜杠 ( /route) 重定向到尾斜杠 ( /route/),这与/route/index.html. 此外,重定向/route/index.html/route用户友好的网址。最后,以 301 响应,告诉搜索引擎只有/route/有效。

"use strict";

exports.handler = (event, _, callback) => {
  // Extract the request from the CloudFront event that is sent to Lambda@Edge
  let request = event.Records[0].cf.request;
  // Extract the URI from the request
  let oldUri = request.uri;
  // If URI is a file
  const isFile = /\/[^/]+\.[^/]+$/.test(oldUri);
  // If not a file request and does not end with / redirect to /
  if (!isFile && !oldUri.endsWith("/")) {
    return callback(null, {
      body: "",
      status: "301",
      statusDescription: "Moved Permanently",
      querystring: request.querystring,
      headers: {
        location: [
          {
            key: "Location",
            value: `${oldUri}/`,
          },
        ],
      },
    });
  }
  // Match any '/' that occurs at the end of a URI. Replace it with a default index
  request.uri = oldUri.replace(/\/$/, "/index.html");
  // Return to CloudFront
  return callback(null, request);
};

注意 - lambda 函数是从某个地方获取的,我为这种情况修改了一段时间,我不记得它来自哪里 - 我只是从我的 lambda 中剪切了一个粘贴的 if。

完成上述操作后,您需要编辑 CloudFront 分配以接受 lambda 函数。

  1. 转到 CloudFront 并选择您的分配
  2. 选择 Behaviors 选项卡,选择默认行为,然后单击编辑按钮
  3. Lambda 函数关联集 - CloudFront 事件到源请求 - 然后将 Lambda 函数 ARN 设置为您刚刚创建的函数。

最后,您需要设置 IAM 权限,以便您的分配可以访问您的 lambda 函数。


推荐阅读