将 React 应用部署到 S3 和 Cloudfront
在本文中,我们将研究如何将我们的 Web 应用部署到AWS S3,并使用AWS Cloudfront作为 CDN。我们还会介绍一种简单的自动化部署方法。
作为奖励,我们还将了解如何长期使用Terraform来管理我们的基础设施!
注意:所有代码都可以在这个存储库中找到
项目设置
我将使用已使用create react app (CRA)初始化的 React app ,但本指南几乎适用于任何框架!
yarn create react-app s3-cloudfront
├── 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
设置 S3
创建存储桶
让我们创建一个新的 S3 存储桶
现在,我们只需输入存储桶名称并将所有内容保留为默认设置即可
启用静态托管
Properties
在这里,我们将启用选项卡下的托管
允许公共访问
现在,让我们转到Permissions
选项卡并编辑存储桶设置以允许公共访问
向下滚动,我们还将更新存储桶策略以允许s3:GetObject
委托人*
这是存储桶策略 json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::YOUR_S3_NAME/*"
]
}
]
}
完美,现在让我们构建我们的 React 应用
yarn build
build
并与我们的myapp.com
S3 bucket同步
aws s3 sync build s3://myapp.com
如果您是 AWS CLI 新手,欢迎阅读我的另一篇关于从头开始设置 CLI 的文章_
太棒了!看来我们的构建已经与 S3 bucket 同步了
太好了!现在我们应该能够通过存储桶端点访问我们的网站了。
注意:您可以通过重新访问Properties
选项卡下的静态部署部分来查看存储桶端点
云端
让我们将 Cloudfront 与 S3 端点连接起来。如果您不熟悉 Cloudfront,它是一个内容分发网络 (CDN),它以低延迟、高传输速度在全球范围内(基于客户的地理位置)分发我们的数据(图像、视频、API 等)。
您应该能够直接从下拉菜单中选择您的 S3 端点。
我们还将创建一个新的源访问身份 (OAI),并允许 CloudFront 更新存储桶策略
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/*"
}
]
}
现在,我将保留大多数字段为默认设置,但您可以在此处配置、、ssl
等更多内容。logging
https redirection
几分钟后,您的分发将被部署,您应该能够在分发 DNS 上访问您的内容!
无效
当我们重新部署或同步更新的构建时,我们还需要创建一个失效规则,该规则的作用是在对象缓存过期之前将其移除。这在为 Web 应用提供更新时非常重要。
注意:这里,我们只是*
为了简单起见使所有对象无效,但您可能需要根据您的用例进行自定义
自动化部署
现在让我们自动化我们的部署过程,以便我们可以在诸如拉取请求合并等事件中从我们的 CI(例如 Github 操作)中使用它。
这是一个简单的部署脚本,它安装依赖项、构建应用程序、将其与我们的 S3 存储桶同步,然后使 CloudFront 分发缓存无效。
touch scripts/deploy.sh
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
chmod +x ./scripts/deploy.sh
现在,我们可以从 CI 中简单地执行脚本来创建部署
./scripts/deploy.sh "YOUR_BUCKET_NAME" "YOUR_DISTRIBUTION_ID"
地形改造(奖励!)
太麻烦了?那就用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
}
让我们tf apply
看看魔术吧!
$ tf apply
...
Outputs:
website_cdn_id = "ABCDXYZ"
website_endpoint = "abcdxyz.cloudfront.net"
下一步?
现在我们已经将静态资源部署到 S3 并使用 Cloudfront 作为 CDN。我们可以连接我们的分发 DNS,Route 53
通过我们自己的域名提供服务。
希望以上信息对您有所帮助,如果您遇到任何问题,请随时通过Twitter联系我。祝您拥有美好的一天!
鏂囩珷鏉ユ簮锛�https://dev.to/karanpratapsingh/deploy-react-app-to-s3-cloudfront-1cao