将 React 应用部署到 S3 和 Cloudfront

2025-06-09

将 React 应用部署到 S3 和 Cloudfront

在本文中,我们将研究如何将我们的 Web 应用部署到AWS S3,并使用AWS Cloudfront作为 CDN。我们还会介绍一种简单的自动化部署方法。

作为奖励,我们还将了解如何长期使用Terraform来管理我们的基础设施!

注意:所有代码都可以在这个存储库中找到

项目设置

我将使用已使用create react app (CRA)初始化的 React app ,但本指南几乎适用于任何框架!



yarn create react-app s3-cloudfront


Enter fullscreen mode Exit fullscreen mode


├── node_modules
├── public
│   ├── favicon.ico
│   ├── index.html
│   ├── manifest.json
│   └── robots.txt
├── src
│   ├── App.css
│   ├── App.js
│   ├── index.css
│   ├── index.js
│   └── logo.svg
├── package.json
└── yarn.lock


Enter fullscreen mode Exit fullscreen mode

设置 S3

创建存储桶
让我们创建一个新的 S3 存储桶

s3仪表板

现在,我们只需输入存储桶名称并将所有内容保留为默认设置即可

s3 创建

s3 创建

启用静态托管

Properties在这里,我们将启用选项卡下的托管

s3 属性
s3 启用托管
s3 托管完成

允许公共访问

现在,让我们转到Permissions选项卡并编辑存储桶设置以允许公共访问

s3 启用公共
s3 已启用公共

向下滚动,我们还将更新存储桶策略以允许s3:GetObject委托人*

s3 策略

这是存储桶策略 json



{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::YOUR_S3_NAME/*"
            ]
        }
    ]
}


Enter fullscreen mode Exit fullscreen mode

s3 策略更新

完美,现在让我们构建我们的 React 应用



yarn build


Enter fullscreen mode Exit fullscreen mode

构建并上传

build并与我们的myapp.comS3 bucket同步



aws s3 sync build s3://myapp.com


Enter fullscreen mode Exit fullscreen mode

如果您是 AWS CLI 新手,欢迎阅读我的另一篇关于从头开始设置 CLI 的文章_

太棒了!看来我们的构建已经与 S3 bucket 同步了

s3 完成

太好了!现在我们应该能够通过存储桶端点访问我们的网站了。

存储桶端点

注意:您可以通过重新访问Properties选项卡下的静态部署部分来查看存储桶端点

云端

让我们将 Cloudfront 与 S3 端点连接起来。如果您不熟悉 Cloudfront,它是一个内容分发网络 (CDN),它以低延迟、高传输速度在全球范围内(基于客户的地理位置)分发我们的数据(图像、视频、API 等)。

让我们创建一个 Cloudfront 发行版
CF 仪表板

您应该能够直接从下拉菜单中选择您的 S3 端点。

我们还将创建一个新的源访问身份 (OAI),并允许 CloudFront 更新存储桶策略

cf 创建

Cloudfront 应该通过添加额外的主体来自动更新您的存储桶策略,如下所示。



{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        },
        {
            "Sid": "2",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity DISTRIBUTION_ID"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
        }
    ]
}


Enter fullscreen mode Exit fullscreen mode

现在,我将保留大多数字段为默认设置,但您可以在此处配置、、ssl更多内容。logginghttps redirection

cf 创建成功

cf完成

几分钟后,您的分发将被部署,您应该能够在分发 DNS 上访问您的内容!

无效

当我们重新部署或同步更新的构建时,我们还需要创建一个失效规则,该规则的作用是在对象缓存过期之前将其移除。这在为 Web 应用提供更新时非常重要。

无效
无效创建

注意:这里,我们只是*为了简单起见使所有对象无效,但您可能需要根据您的用例进行自定义

自动化部署

现在让我们自动化我们的部署过程,以便我们可以在诸如拉取请求合并等事件中从我们的 CI(例如 Github 操作)中使用它。

这是一个简单的部署脚本,它安装依赖项、构建应用程序、将其与我们的 S3 存储桶同步,然后使 CloudFront 分发缓存无效。



touch scripts/deploy.sh


Enter fullscreen mode Exit fullscreen mode


BUCKET_NAME=$1
DISTRIBUTION_ID=$2

echo "-- Install --"
# Install dependencies
yarn --production

echo "-- Build --"
# Build
yarn build

echo "-- Deploy --"
# Sync build with our S3 bucket
aws s3 sync build s3://$BUCKET_NAME
# Invalidate cache
aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths "/*" --no-cli-pager


Enter fullscreen mode Exit fullscreen mode


chmod +x ./scripts/deploy.sh


Enter fullscreen mode Exit fullscreen mode

现在,我们可以从 CI 中简单地执行脚本来创建部署



./scripts/deploy.sh "YOUR_BUCKET_NAME" "YOUR_DISTRIBUTION_ID"


Enter fullscreen mode Exit fullscreen mode

地形改造(奖励!)

太麻烦了?那就用Terraform来搭建基础设施吧。如果你不熟悉 Terraform,可以看看我的另一篇文章

这是一个示例地形



provider "aws" {
  region = "us-east-1"
}

variable "bucket_name" {
  default = "myapp.com-sample"
}

resource "aws_s3_bucket_policy" "bucket_policy" {
  bucket = aws_s3_bucket.deploy_bucket.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid       = "PublicReadGetObject"
        Effect    = "Allow"
        Principal = "*"
        Action    = "s3:GetObject"
        Resource  = "${aws_s3_bucket.deploy_bucket.arn}/*"
      },
    ]
  })
}

resource "aws_s3_bucket" "deploy_bucket" {
  bucket = var.bucket_name
  acl    = "public-read"

  website {
    index_document = "index.html"
    error_document = "index.html"
  }
}

resource "aws_cloudfront_origin_access_identity" "cloudfront_oia" {
  comment = "example origin access identify"
}

resource "aws_cloudfront_distribution" "website_cdn" {
  enabled = true

  origin {
    origin_id   = "origin-bucket-${aws_s3_bucket.deploy_bucket.id}"
    domain_name = aws_s3_bucket.deploy_bucket.website_endpoint

    custom_origin_config {
      http_port              = "80"
      https_port             = "443"
      origin_protocol_policy = "http-only"
      origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"]
    }
  }

  default_root_object = "index.html"

  default_cache_behavior {
    allowed_methods        = ["GET", "HEAD", "DELETE", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods         = ["GET", "HEAD"]
    min_ttl                = "0"
    default_ttl            = "300"
    max_ttl                = "1200"
    target_origin_id       = "origin-bucket-${aws_s3_bucket.deploy_bucket.id}"
    viewer_protocol_policy = "redirect-to-https"
    compress               = true

    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

output "website_cdn_id" {
  value = aws_cloudfront_distribution.website_cdn.id
}

output "website_endpoint" {
  value = aws_cloudfront_distribution.website_cdn.domain_name
}


Enter fullscreen mode Exit fullscreen mode

让我们tf apply看看魔术吧!



$ tf apply

...

Outputs:

website_cdn_id = "ABCDXYZ"
website_endpoint = "abcdxyz.cloudfront.net"

Enter fullscreen mode Exit fullscreen mode




下一步?

现在我们已经将静态资源部署到 S3 并使用 Cloudfront 作为 CDN。我们可以连接我们的分发 DNS,Route 53通过我们自己的域名提供服务。

希望以上信息对您有所帮助,如果您遇到任何问题,请随时通过Twitter联系我。祝您拥有美好的一天!

鏂囩珷鏉ユ簮锛�https://dev.to/karanpratapsingh/deploy-react-app-to-s3-cloudfront-1cao
PREV
使用 C# 简单介绍通用存储库模式
NEXT
使用 Go 构建 REST API - 适合初学者 gorilla/mux