将你的 Astro 网站部署到 AWS

AWS 是一个功能齐全的 Web 应用托管平台,可以用来部署 Astro 网站。

将你的项目部署到 AWS 需要使用 AWS 控制台(大部分操作也可以使用 AWS CLI 进行)。本指南将指导你按照最基本的方法将网站部署到 AWS 上,然后演示如何添加额外的服务以降本增效。

AWS Amplify 是一套专为前端 Web 和移动开发人员设计的工具和功能,可以让你在 AWS 上快速轻松地构建全栈应用程序。

  1. 创建一个新的 Amplify Hosting 项目。

  2. 将你的仓库连接到 Amplify。

  3. 修改构建输出目录 baseDirectory/dist

    version: 1
    frontend:
    phases:
    preBuild:
    # 如果不使用 npm,请将 `npm ci` 修改为 `yarn install` 或 `pnpm i`
    commands:
    - npm ci
    build:
    commands:
    - npm run build
    artifacts:
    baseDirectory: /dist
    files:
    - '**/*'
    cache:
    paths:
    - node_modules/**/*

如果使用 pnpm,则需要稍微不同的配置来缓存 pnpm 存储目录而不是 node_modules。以下是建议的构建配置:

version: 1
frontend:
phases:
preBuild:
commands:
- npm i -g pnpm
- pnpm config set store-dir .pnpm-store
- pnpm i
build:
commands:
- pnpm run build
artifacts:
baseDirectory: /dist
files:
- '**/*'
cache:
paths:
- .pnpm-store/**/*

之后 Amplify 将自动部署你的网站,并在你向仓库推送提交时进行更新。

S3 是任何应用程序的起点,因为它是一个可以存储你项目文件和其他资源的地方。S3 按照文件存储和请求数量收费。你可以在 AWS 文档 中找到有关 S3 的更多信息。

  1. 创建一个与你的项目名称相对应的 S3 存储桶。

  2. 禁用 “Block all public access”。默认情况下,AWS 将所有存储桶设置为私有。要使其公开访问,你需要在存储桶的属性中取消选中“Block public access”复选框。

  3. 将你构建后的文件(位于 dist 目录)上传到 S3。你可以在控制台手动执行此操作,也可以使用 AWS CLI。如果使用 AWS CLI,请在 使用 AWS 凭证进行身份验证 后,使用以下命令:

    aws s3 cp dist/ s3://<BUCKET_NAME>/ --recursive
  4. 更新你的存储桶策略以允许公共访问。你可以在存储桶的权限 > 存储桶策略中找到此设置。

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "PublicReadGetObject",
    "Effect": "Allow",
    "Principal": "*",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::<BUCKET_NAME>/*"
    }
    ]
    }
  5. 为你的存储桶启用网站托管。你可以在存储桶的 Settings > Static website hosting 中找到此设置。将你的索引文档设置为 index.html,错误文档设置为 404.html。最后,在存储桶的 Settings > Static website hosting 中找到你的新网站 URL。

CloudFront 是一个提供内容分发网络 (CDN) 功能的 Web 服务。它用于缓存 Web 服务器的内容并将其分发给用户。CloudFront 按照传输的数据量收费。将 CloudFront 添加到你的 S3 存储桶中可以更为经济的同时也提供更快的分发速度。

我们将使用 CloudFront 来包装我们的 S3 存储桶,以使用亚马逊全球 CDN 网络为项目的文件提供服务。这样可以降低提供项目文件的成本,并提高站点的性能。

  1. 使用你的项目名称创建一个 S3 存储桶。

  2. 将位于 dist 目录中的构建文件上传到 S3。你可以在控制台手动执行此操作,也可以使用 AWS CLI。如果使用 AWS CLI,可以在 使用 AWS 凭证进行身份验证 后使用以下命令:

    aws s3 cp dist/ s3://<BUCKET_NAME>/ --recursive
  3. 更新存储桶策略以允许 CloudFront 访问。你可以在存储桶的 Permissions > Bucket policy 中找到此设置。

    {
    "Version": "2012-10-17",
    "Statement": [{
    "Effect": "Allow",
    "Principal": {
    "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <CLOUDFRONT_OAI_ID>"
    },
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::astro-aws/*"
    }]
    }
  1. 创建一个 CloudFront 分发,并按如下值配置:
    • 源域名:你的 S3 存储桶
    • S3 存储桶访问:“Yes use OAI (bucket can restrict access to only CloudFront)”
    • 源访问标识:创建一个新的源访问标识
    • 查看者 - 存储桶策略:“No, I will update the bucket policy”
    • 查看者协议策略:“Redirect to HTTPS”
    • 默认根对象index.html

这样的配置将阻止公共互联网访问你的 S3 存储桶,并通过全球 CDN 网络提供你的网站。你可以在存储桶的 Distributions > Domain name 中找到你的 CloudFront 分发 URL。

不幸的是,默认情况下,CloudFront 不支持多页的 sub-folder/index 路由。为了配置它,我们将使用 CloudFront 函数将请求定向到 S3 中所需的对象上。

  1. 使用以下代码片段创建一个新的 CloudFront 函数。你可以在 CloudFront > Functions 中找到 CloudFront 函数。

    function handler(event) {
    var request = event.request;
    var uri = request.uri;
    // 检查 URI 是否缺少文件名。
    if (uri.endsWith('/')) {
    request.uri += 'index.html';
    }
    // 检查 URI 是否缺少文件扩展名。
    else if (!uri.includes('.')) {
    request.uri += '/index.html';
    }
    return request;
    }
  2. 将函数附加到 CloudFront 分发中。你可以在 CloudFront 分发的 Settings > Behaviors > Edit > Function 关联中找到此选项。

    • 查看者请求 - 函数类型: CloudFront 函数。
    • 查看者请求 - 函数 ARN: 选择在前面创建的函数。

使用 GitHub Actions 实现持续部署

标题部分 使用 GitHub Actions 实现持续部署

有许多方法可以为 AWS 设置持续部署。对于托管在 GitHub 上的代码,一种可能的方法是使用 GitHub Actions 在每次提交时部署你的网站。

  1. 创建一个新的策略在你的 AWS 账户中使用 IAM 并拥有以下权限。这个策略将允许你在提交时上传构建好的文件到你的 S3 存储桶,并且在提交时使 CloudFront 分布的文件失效。

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Sid": "VisualEditor0",
    "Effect": "Allow",
    "Action": [
    "s3:PutObject",
    "s3:ListBucket",
    "s3:DeleteObject",
    "cloudfront:CreateInvalidation"
    ],
    "Resource": [
    "<DISTRIBUTION_ARN>",
    "arn:aws:s3:::<BUCKET_NAME>/*",
    "arn:aws:s3:::<BUCKET_NAME>"
    ]
    }
    ]
    }
  2. 创建一个新的 IAM 用户并将该策略附加到用户上。这将需要你提供 AWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_ID

  3. 将以下示例工作流添加到你的代码库中的 .github/workflows/deploy.yml 文件中,并将其推送到 GitHub。你需要将 AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYBUCKET_IDDISTRIBUTION_ID 作为“secrets”添加到 GitHub 代码库中的 Settings > Secrets > Actions 中。使用 New repository secret 按钮来添加每个秘钥。

    name: Deploy Website
    on:
    push:
    branches:
    - main
    jobs:
    deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout
    uses: actions/checkout@v3
    - name: Configure AWS Credentials
    uses: aws-actions/configure-aws-credentials@v1
    with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: us-east-1
    - name: Install modules
    run: npm ci
    - name: Build application
    run: npm run build
    - name: Deploy to S3
    run: aws s3 sync --delete ./dist/ s3://${{ secrets.BUCKET_ID }}
    - name: Create CloudFront invalidation
    run: aws cloudfront create-invalidation --distribution-id ${{ secrets.DISTRIBUTION_ID }} --paths "/*"

更多部署指南

根据类型筛选