How to Deploy React App with S3 and CloudFront

How to Deploy React App with S3 and CloudFront

avatar

Phong Nguyen

2023.12.24

Trong bài blog này, chúng ta sẽ tìm hiểu cách deploy 1 React App đến Amazon S3 và Cloudfront.

Lab Details

  1. Duration: 1 hour
  2. AWS Region: US East (N. Virginia) us-east-1

Architecture Diagram

Task Details

  1. Create React App
  2. Create an S3 Bucket
  3. Upload a file to the S3 bucket.
  4. Create a new Amazon CloudFront distribution.
  5. Accessing React App through Cloudfront.
  6. Use AWS CLI to update S3 and CloudFront

1. Create React App

Chúng ta sẽ create React App đơn giản theo GUI sau: https://create-react-app.dev/docs/getting-started

Sử dụng Code Editer như VS Code và chạy command bên dưới:

npx create-react-app my-app
cd my-app
npm start

Update file src\App.js nếu bạn muốn Custom. Ví dụ như mình sẽ thay đổi dòng bên dưới

App.js
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          React App with S3 and CloudFront
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

2. Create an S3 Bucket

Lưu ý bucket không được trùng tên trong Region, nên hãy đặt tên phù hợp.

  • AWS Region: US East (N. Virginia) us-east-1
  • Bucket name: d-s3-saa-[your-name]-react-app (Ex: d-s3-saa-cloudmentorpro-react-app)

3. Upload a file to the S3 bucket.

Tại thư mục my-app, chạy lệnh sau để build React App thành content tĩnh

npm run build

Upload toàn bộ nội dung trong thư mục build vào S3 bucket (dùng kéo thả)

4. Create a new Amazon CloudFront distribution.

Tại Console Cloudfront -> Create distribution

  • Origin domain: Chọn S3 bucket for react app
  • Origin access: Origin access control settings (recommended)
  • Click Create new OAC

Sau khi create OAC xong thì sẽ tự động fill giá trị như bên dưới:

Scroll xuống phần Web Application Firewall (WAF). Chọn như hình bên dưới

  • Nhấn nút Create distribution

  • Sau khi tạo distribution sẽ xuất hiện màn hình bên dưới, Click Copy policy

  • Edit bucket policy với nội dung copy vừa rồi

Nhìn vào bucket policy mọi người có thể thấy là Bucket này chỉ cho phép access từ Cloudfront => rất security

5. Accessing React App through Cloudfront.

Access đến Distributions vừa tạo, copy Distribution domain name

6. Use AWS CLI to update S3 and CloudFront

Mỗi lần chúng ta update app, chúng ta sẽ thực hiện các công việc sau để Deploy

  1. Build app sử dụng npm run build
  2. Upload nội dung thư mục build đến S3 bucket: Có thể sử dụng CLI để thực hiện việc này: aws s3 sync build/ s3://{your-s3-bucket}
  3. CloudFront sẽ cache nội dung của S3 bucket và nó sẽ không biết được content được update, Chúng ta sẽ cần nói cho CloudFront Distribution to invalidate the cache. Chúng ta cũng có thể làm việc này bằng CLI:
aws cloudfront create-invalidation --distribution-id YOUR_DISTRIBUTION_ID --paths '/*'

Let's Do It

  • Thực hiện một chút thay đổi nhỏ ở đây:

  • Run command npm run build để build app

  • Tại thư mục my-app Run command aws s3 sync build/ s3://{your-s3-bucket} để upload file lên S3

Mặc dù S3 đã được cập nhật nhưng CloudFront domain vẫn hiển thị nội dung cũ

  • Run command aws cloudfront create-invalidation --distribution-id YOUR_DISTRIBUTION_ID --paths '/*'

Challenge

Vì domain của CloudFront đang sử dụng là default domain, chúng ta có thể cuscom domain này. Cách làm như sau

  1. Mua Domain trên Route53
  2. Create Certificate sử dụng ACM
  3. Update Distribution

  1. Create Alias record in Route53

Clean Up

  1. Empty và Delete S3 Bucket
  2. Disable Cloudfront Distributions
  3. Đợi cho Distributions Deploy hoàn thành sẽ enable nút Delete
  4. Delete Distributions
  5. Delete Certificates (Nếu thực hiện challenge)
  6. Delete record in Route53 (Nếu thực hiện challenge)