2

5 分钟内创建 AWS S3 网站 YT 视频在 Amazon S3 Pulumi 上托管静态网站教程中有很好的解释如何使用 Pulumi 在 S3 上创建网站托管。

在示例代码中使用了 Pulumi 的BucketBucketObject。第一个创建一个 S3 存储桶,后者创建对象,这些对象主要index.html用于公共访问,如下所示:

const aws = require("@pulumi/aws");
const pulumi = require("@pulumi/pulumi");
const mime = require("mime");

// Create an S3 bucket
let siteBucket = new aws.s3.Bucket("s3-website-bucket");

let siteDir = "www"; // directory for content files

// For each file in the directory, create an S3 object stored in `siteBucket`
for (let item of require("fs").readdirSync(siteDir)) {
    let filePath = require("path").join(siteDir, item);
    let object = new aws.s3.BucketObject(item, {
      bucket: siteBucket,
      source: new pulumi.asset.FileAsset(filePath),     // use FileAsset to point to a file
      contentType: mime.getType(filePath) || undefined, // set the MIME type of the file
    });
}

exports.bucketName = siteBucket.bucket; // create a stack export for bucket name

现在使用基于 Vue.js / Nuxt.js 的应用程序,我需要上传多个生成的文件,这些文件位于dist我的项目根目录中。它们由 a 生成npm run build并生成以下文件:

$ find dist
dist
dist/favicon.ico
dist/index.html
dist/.nojekyll
dist/200.html
dist/_nuxt
dist/_nuxt/LICENSES
dist/_nuxt/static
dist/_nuxt/static/1619685747
dist/_nuxt/static/1619685747/manifest.js
dist/_nuxt/static/1619685747/payload.js
dist/_nuxt/f3a11f3.js
dist/_nuxt/f179782.js
dist/_nuxt/fonts
dist/_nuxt/fonts/element-icons.4520188.ttf
dist/_nuxt/fonts/element-icons.313f7da.woff
dist/_nuxt/c25b1a7.js
dist/_nuxt/84fe6d0.js
dist/_nuxt/a93ae32.js
dist/_nuxt/7b77d06.js

我的问题是这些文件还包含嵌套在子目录中的文件,这些文件本身也可能是子目录 - 例如dist/_nuxt/fonts/element-icons.4520188.ttf. 教程中提供的方法不评估子目录,我不知道如何使用 Pulumi/TypeScript 做到这一点。

4

1 回答 1

4

我继续采用该方法并尝试构建一个递归 TypeScript 函数,该函数根据教程的建议基于 Pulumi 的BucketObject创建文件或目录。这让我陷入了一个复杂的境地!我需要使用创建目录,使用附加在参数BucketObject中可以实现什么(请参阅此答案)。只是为了记录,该功能看起来像这样:"/"key

function createS3BucketFolder(dirName: string) {
  new aws.s3.BucketObject(dirName, {
    bucket: nuxtBucket,
    acl: "public-read",
    key: dirName + "/", // an appended '/' will create a S3 Bucket prefix (see https://stackoverflow.com/a/57479653/4964553)
    contentType: "application/x-directory" // this content type is also needed for the S3 Bucket prefix
    // no source needed here!
  })
}

但这只是使用 TypeScript 递归遍历目录所需的大量代码中的一部分(另请参阅有关该主题的大量 so 答案,从同步版本到疯狂的 Node.js 11+ 异步解决方案)。我最终得到了大约 40-50 行代码,仅用于将静态站点生成的文件递归添加到 S3 - 感觉不好,没有对此进行测试(我真的不明白,为什么Pulumi 不支持类似 Terraform 的用例)。

最后,我偶然发现了关于使用 Amazon S3、CloudFront、Route53 和证书管理器保护静态网站的 Pulumi 教程,其中有一段关于部署速度的特殊段落,并附有一段有趣的引述:

此示例为网站提供的每个文件创建一个 aws.S3.BucketObject。在部署大型网站时,这可能会导致更新时间过长,因为会检查每个单独的文件是否有任何更改。不使用 Pulumi 管理单个文件而直接使用 AWS CLI 将本地文件与 S3 存储桶同步可能更有效。

TLDR:对于非 hello world 用例,Pulumi 文档告诉我们不要使用 Pulumi 将文件上传到 S3,而是使用 AWS CLI!所以我修改了我的代码,只使用 Pulumi 创建 S3 Bucket,如下所示:

import * as aws from "@pulumi/aws";

// Create an AWS resource (S3 Bucket)
const nuxtBucket = new aws.s3.Bucket("microservice-ui-nuxt-js-hosting-bucket", {
  acl: "public-read",
  website: {
    indexDocument: "index.html",
  }
});

// Export the name of the bucket
export const bucketName = nuxtBucket.id;

这将创建一个支持静态站点托管的 S3 存储桶,public-read可通过 Pulumi 访问。现在使用 AWS CLI,我们可以使用以下命令优雅地将文件复制/同步到存储桶:

aws s3 sync ../dist/ s3://$(pulumi stack output bucketName) --acl public-read

使用$(pulumi stack output bucketName)我们只需获取 Pulumi 创建的 S3 Bucket 名称。请注意最后的--acl public-read参数,因为您必须在 S3 中对每个静态 Web 文件启用公共读取访问权限,尽管存储桶本身已经具有公共读取访问权限!

于 2021-04-29T13:36:39.763 回答