0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

Triển khai Ứng dụng React SPA trên AWS S3 và CloudFront

Đăng vào 5 ngày trước

• 8 phút đọc

Giới thiệu

Trong bài viết này, chúng ta sẽ tìm hiểu cách triển khai một ứng dụng SPA (Single Page Application) được viết bằng React trên AWS S3 và CloudFront. Mô hình mà chúng ta sẽ sử dụng sẽ giúp bạn quản lý các API REST thông qua AWS API Gateway và sử dụng CloudFront để tối ưu hóa việc chia sẻ tài nguyên giữa các miền (CORS).

Chúng ta sẽ dựa vào kho mã mẫu do AWS cung cấp.

Kiến trúc tổng quan

Các dịch vụ AWS

  • AWS API Gateway: Giúp bạn tạo, xuất bản và duy trì API REST, HTTP, và WebSocket với quy mô lớn.
  • AWS CloudFormation: Hỗ trợ bạn thiết lập tài nguyên AWS, cung cấp nhanh chóng và đồng nhất, cũng như quản lý chúng trong suốt vòng đời trong các tài khoản và vùng AWS.
  • AWS CloudFront: Tăng tốc độ phân phối nội dung web của bạn bằng cách cung cấp qua mạng lưới trung tâm dữ liệu toàn cầu, giảm độ trễ và cải thiện hiệu suất.
  • AWS CloudTrail: Giúp bạn kiểm toán quản lý, tuân thủ và rủi ro hoạt động của tài khoản AWS.
  • AWS CloudWatch: Giúp bạn theo dõi các thông số của tài nguyên AWS và các ứng dụng mà bạn chạy trên AWS theo thời gian thực.
  • AWS IAM: Giúp bạn quản lý quyền truy cập tài nguyên AWS một cách an toàn bằng cách kiểm soát ai được xác thực và ủy quyền sử dụng chúng.
  • AWS Route 53: Dịch vụ DNS web có tính khả dụng cao và có thể mở rộng.
  • Amazon S3: Dịch vụ lưu trữ đối tượng dựa trên đám mây giúp bạn lưu trữ, bảo vệ và truy xuất bất kỳ lượng dữ liệu nào.

CloudFormation (IaC)

Trong kho mã mẫu, chúng ta sẽ tập trung vào thông tin có trong tệp react-cors-spa-stack.yaml. Trong tệp YAML này, chúng ta có tất cả các chỉ dẫn để AWS CloudFormation cung cấp các tài nguyên AWS cần thiết cho ví dụ này.

Bucket AWS S3

  • PublicAccessBlockConfiguration chặn tất cả quyền truy cập công khai.
  • Nhật ký bucket được bật và lưu trữ trong LoggingBucket.
  • BucketName thiết lập tên của bucket (đây là thông tin quan trọng nếu bạn gặp khó khăn trong việc tìm bucket trong AWS Console).
yaml Copy
  S3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub 'react-cors-spa-${SimpleAPI}'
      PublicAccessBlockConfiguration:
        BlockPublicAcls : true
        BlockPublicPolicy : true
        IgnorePublicAcls : true
        RestrictPublicBuckets : true
      LoggingConfiguration:
        DestinationBucketName: !Ref LoggingBucket
        LogFilePrefix: s3-access-logs
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
        - ServerSideEncryptionByDefault:
            SSEAlgorithm: 'AES256'

Chính sách Bucket AWS S3

  • Cho phép hành động s3:GetObject*.
  • CFDistributionSPA là thực thể duy nhất được phép thực hiện hành động s3:GetObject*.
yaml Copy
  BucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      PolicyDocument:
        Id: MyPolicy
        Version: 2012-10-17
        Statement:
          - Sid: PolicyForCloudFrontPrivateContent
            Effect: Allow
            Resource: !Sub ${S3Bucket.Arn}/*
            Principal:
              Service: cloudfront.amazonaws.com
            Condition:
              StringEquals:
                AWS:SourceArn: !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution/${CFDistributionSPA}
            Action: 's3:GetObject*'
      Bucket: !Ref S3Bucket

CloudFront

  • Thiết lập nguồn gốc là Bucket S3 của SPA, sử dụng CloudFrontOriginAccessControl như phương thức OAC giữa CloudFront và AWS S3.
  • Thuộc tính DefaultRootObject nhận giá trị index.html. Đây là tệp mà CloudFront sẽ coi là đối tượng gốc từ Bucket AWS S3.
yaml Copy
  CFDistributionSPA:
    Type: 'AWS::CloudFront::Distribution'
    Properties:
      DistributionConfig:
        Origins:
        - DomainName: !GetAtt S3Bucket.RegionalDomainName
          Id: myS3Origin
          S3OriginConfig:
            OriginAccessIdentity: ""
          OriginAccessControlId: !GetAtt CloudFrontOriginAccessControl.Id
        Enabled: 'true'
        DefaultRootObject: index.html
        DefaultCacheBehavior:
          AllowedMethods:
          - GET
          - HEAD
          - OPTIONS
          TargetOriginId: myS3Origin
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # CachingOptimized
          OriginRequestPolicyId: 88a5eaf4-2fd4-4709-b370-b4c650ea3fcf # CORS-S3Origin
          ResponseHeadersPolicyId: eaab4381-ed33-4a86-88ca-d9558dc6cd63 # CORS-with-preflight-and-SecurityHeadersPolicy
          ViewerProtocolPolicy: redirect-to-https
        CustomErrorResponses:
          - ErrorCode: 403
            ResponseCode: 200
            ResponsePagePath: /index.html
          - ErrorCode: 501
            ResponseCode: 501
            ErrorCachingMinTTL: 0
        PriceClass: PriceClass_All
        Logging:
          Bucket: !GetAtt LoggingBucket.RegionalDomainName
          Prefix: 'cf-spa-access-logs'
        ViewerCertificate:
          CloudFrontDefaultCertificate: true
          MinimumProtocolVersion: 'TLSv1.2_2021'

CloudFront OriginAccessControl

  • Mô tả các chữ ký yêu cầu giữa CloudFront và Bucket AWS S3 (OAC).
yaml Copy
  CloudFrontOriginAccessControl:
    Type: AWS::CloudFront::OriginAccessControl
    DependsOn:
      - S3Bucket
    Properties: 
      OriginAccessControlConfig:
        Description: Default Origin Access Control
        Name: !Ref AWS::StackName
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

Triển khai

  1. Đầu tiên, chạy lệnh sau để CloudFormation cung cấp tài nguyên ứng dụng:

    bash Copy
    aws cloudformation deploy \
    --stack-name react-cors-spa-demo \
    --template-file react-cors-spa-stack.yaml \
    --region us-east-1 \
    --no-fail-on-empty-changeset
  2. Bây giờ, chúng ta sẽ lấy các giá trị được cung cấp bởi mẫu CloudFormation, được liệt kê trong phần Outputs:

    yaml Copy
    Outputs:
    BucketName:
    Value: !Sub "react-cors-spa-${SimpleAPI}"
    SPADomain:
    Value: !GetAtt CFDistributionSPA.DomainName
    APIDomain:
    Value: !GetAtt CFDistributionAPI.DomainName

    Chạy lệnh:

    bash Copy
    aws cloudformation describe-stacks \
    --stack-name react-cors-spa-demo \
    --region us-east-1 \
    --query "Stacks[0].Outputs"

    Lưu BucketName để sử dụng sau này.

  3. Xây dựng ứng dụng React của bạn. Trong ví dụ này, bạn có thể thực hiện bằng cách chạy yarn build và tìm thư mục out.

  4. Bây giờ chỉ cần tải nội dung từ bước trước, sử dụng BucketName từ bước 2, lên Bucket AWS S3:

    bash Copy
    aws s3 sync ./out "s3://$BUCKET_NAME"

    Nếu bạn đang sử dụng Next.js giống như ví dụ của AWS, bạn cũng cần bao gồm thư mục _next_ trong Bucket AWS S3:

    bash Copy
    aws s3 sync ./_next "s3://$BUCKET_NAME"

Kết luận

Giờ đây, bạn đã biết cách lưu trữ ứng dụng React SPA của mình trong một hệ thống nhanh chóng, an toàn và tiết kiệm chi phí trên AWS Cloud.

Nếu bạn thấy nội dung này hữu ích hoặc có bất kỳ câu hỏi nào về nó, hãy để lại bình luận bên dưới nhé!

Các phương pháp tốt nhất

  • Kiểm tra cấu hình: Đảm bảo rằng tất cả các thông số cấu hình đã được thiết lập đúng.
  • Quản lý phiên bản: Sử dụng phiên bản bucket S3 để theo dõi sự thay đổi của nội dung.
  • Bảo mật: Thiết lập chính sách IAM chặt chẽ để hạn chế quyền truy cập.

Những cạm bẫy thường gặp

  • Quên bật nhật ký: Không bật nhật ký có thể khiến bạn không theo dõi được các truy cập và lỗi.
  • Thiếu kiểm tra CORS: Nếu không cấu hình đúng CORS, ứng dụng có thể không hoạt động trên các miền khác.

Mẹo hiệu suất

  • Sử dụng cache: Sử dụng các chính sách cache trong CloudFront để cải thiện hiệu suất tải trang.
  • Tối ưu hóa hình ảnh: Sử dụng hình ảnh với kích thước tối ưu để giảm thời gian tải.

Khắc phục sự cố

  • Lỗi 403: Nếu bạn gặp lỗi 403, hãy kiểm tra chính sách bucket và quyền truy cập của CloudFront.
  • Vấn đề CORS: Kiểm tra cấu hình CORS trong API và CloudFront để đảm bảo rằng nó được thiết lập đúng.

Câu hỏi thường gặp

  1. Làm thế nào để tôi có thể điều chỉnh cấu hình CloudFront cho ứng dụng của mình?

    • Bạn có thể chỉnh sửa mẫu CloudFormation để thay đổi các thuộc tính trong CFDistributionSPA.
  2. Có cần sử dụng API Gateway không?

    • Nếu ứng dụng của bạn cần tương tác với các API bên ngoài, thì API Gateway là cần thiết.
  3. Có cách nào để giám sát hiệu suất của ứng dụng không?

    • Bạn có thể sử dụng AWS CloudWatch để theo dõi và phân tích dữ liệu hiệu suất của ứng dụng.
Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào