AWSでReactアプリを公開する手順まとめ|S3とCloudFrontで最速デプロイ

ReactのブラウザプリをAWSで公開する手順 AWS

はじめに

ReactアプリをAWS(Amazon Web Services)にデプロイする手順を詳しく解説します。今回は、ポケモンクイズアプリを例に、完全無料(AWS無料枠内)でインターネット上に公開する方法を紹介します。

今回デプロイするアプリ

  • フレームワーク: React 18.2 + TypeScript 5.2
  • ビルドツール: Vite 5.2
  • アプリタイプ: SPA(Single Page Application)
  • バックエンド: なし(完全にクライアントサイド)

目次

  1. なぜS3 + CloudFront構成なのか
  2. 前提条件
  3. デプロイ手順
  4. コストについて
  5. 更新方法

なぜS3 + CloudFront構成なのか

Reactアプリのデプロイ先として、AWS S3 + CloudFrontを選んだ理由は以下の通りです。

構成図

ユーザー
    ↓ HTTPS
CloudFront (CDN)
    ↓ OAC認証
S3 Bucket (静的ファイル)

選定理由

メリット説明
低コストAWS無料枠内で運用可能。13ヶ月目以降も月数円〜数十円程度
サーバー不要静的ファイルをS3に置くだけ。サーバー管理が不要
HTTPS標準CloudFrontで無料のSSL証明書を利用可能
高速配信世界中のエッジロケーションでキャッシュ
高可用性AWS側で自動的にスケール・冗長化

他の選択肢との比較

サービスメリットデメリット判断
S3 + CloudFront低コスト、シンプル初期設定がやや複雑✅ 採用
AWS AmplifyGit連携で自動デプロイビルド時間で課金❌ やや割高
EC2自由度が高いサーバー管理必要❌ 過剰

前提条件

必要なもの

  1. AWSアカウント(無料枠あり)
  2. AWS CLIのインストールと設定
  3. Node.js(18.0以上)

AWS CLIの確認

# バージョン確認
aws --version

# 認証情報の確認
aws sts get-caller-identity

正しく設定されていれば、以下のような出力が表示されます。

{
    "UserId": "AIDAXXXXXXXXXXXXXXXXX",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/your-username"
}

デプロイ手順

ステップ1: アプリケーションのビルド

まず、本番用のビルドを作成します。

npm run build

実行内容:

  • TypeScriptの型チェック
  • Viteで最適化されたファイルを生成
  • 出力先: dist/フォルダ

生成されるファイル:

dist/
├── index.html
└── assets/
    └── index-[hash].js
💡 ポイント: ファイル名にハッシュが付与されることで、ブラウザキャッシュの問題を回避できます。

ステップ2: S3バケットの作成

静的ファイルを保管するS3バケットを作成します。

# バケット作成(バケット名は全世界で一意である必要があります)
aws s3 mb s3://your-app-name-2025 --region ap-northeast-1

コマンド解説:

  • s3 mb: “make bucket”の略(バケット作成)
  • --region ap-northeast-1: 東京リージョンを指定

パブリックアクセスブロックの確認:

aws s3api get-public-access-block --bucket your-app-name-2025

すべてtrueになっていることを確認してください(セキュリティのため)。

ステップ3: ファイルのアップロード

aws s3 sync dist/ s3://your-app-name-2025 --delete

オプション解説:

  • sync: 差分のみアップロード(効率的)
  • --delete: S3にあってローカルにないファイルを削除

ステップ4: OAC(Origin Access Control)の作成

CloudFrontからS3へ安全にアクセスするためのOACを作成します。

設定ファイル oac-config.json を作成:

{
    "Name": "your-app-oac",
    "Description": "OAC for your app S3 bucket",
    "SigningProtocol": "sigv4",
    "SigningBehavior": "always",
    "OriginAccessControlOriginType": "s3"
}

OACを作成:

aws cloudfront create-origin-access-control --origin-access-control-config file://oac-config.json

出力されたId(例: E2EJX97TW43NVS)をメモしておきます。

⚠️ 注意: OACのIDは次のステップで使用します。

ステップ5: CloudFrontディストリビューションの作成

設定ファイル cloudfront-config.json を作成:

{
    "CallerReference": "your-app-2025",
    "Comment": "Your App Distribution",
    "DefaultRootObject": "index.html",
    "Origins": {
        "Quantity": 1,
        "Items": [
            {
                "Id": "S3-your-app-name-2025",
                "DomainName": "your-app-name-2025.s3.ap-northeast-1.amazonaws.com",
                "OriginAccessControlId": "E2EJX97TW43NVS",
                "S3OriginConfig": {
                    "OriginAccessIdentity": ""
                }
            }
        ]
    },
    "DefaultCacheBehavior": {
        "TargetOriginId": "S3-your-app-name-2025",
        "ViewerProtocolPolicy": "redirect-to-https",
        "AllowedMethods": {
            "Quantity": 2,
            "Items": ["GET", "HEAD"],
            "CachedMethods": {
                "Quantity": 2,
                "Items": ["GET", "HEAD"]
            }
        },
        "Compress": true,
        "CachePolicyId": "658327ea-f89d-4fab-a63d-7e88639e58f6",
        "TrustedSigners": {
            "Enabled": false,
            "Quantity": 0
        },
        "TrustedKeyGroups": {
            "Enabled": false,
            "Quantity": 0
        }
    },
    "Enabled": true,
    "PriceClass": "PriceClass_100",
    "HttpVersion": "http2and3"
}

ディストリビューションを作成:

aws cloudfront create-distribution --distribution-config file://cloudfront-config.json

出力されたIdDomainNameをメモします。

{
    "Distribution": {
        "Id": "E2YOGKTL016F74",
        "DomainName": "d3nikxhjxcxmrr.cloudfront.net",
        "Status": "InProgress"
    }
}

ステップ6: S3バケットポリシーの設定

CloudFrontからS3へのアクセスを許可します。

ポリシーファイル s3-bucket-policy.json を作成:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::your-app-name-2025/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/E2YOGKTL016F74"
                }
            }
        }
    ]
}
⚠️ 注意: 123456789012は自分のAWSアカウント番号に、E2YOGKTL016F74は実際のディストリビューションIDに置き換えてください。

ポリシーを適用:

aws s3api put-bucket-policy --bucket your-app-name-2025 --policy file://s3-bucket-policy.json

ステップ7: SPA用カスタムエラーレスポンス設定

React RouterなどのSPAルーティングを動作させるための重要な設定です。

なぜ必要?

SPAでは、/about/scoresなどのルートがReact Router内にのみ存在します。ユーザーが直接これらのURLにアクセスすると、CloudFrontはS3に該当するファイルがないため404エラーを返します。

解決策: 404/403エラーが発生したら、常にindex.htmlを返すように設定します。

現在の設定を取得:

aws cloudfront get-distribution-config --id E2YOGKTL016F74 --query "DistributionConfig" --output json > current-config.json

ETagを取得:

aws cloudfront get-distribution-config --id E2YOGKTL016F74 --query "ETag" --output text

current-config.jsonを編集:

CustomErrorResponsesセクションを以下のように変更します。

"CustomErrorResponses": {
    "Quantity": 2,
    "Items": [
        {
            "ErrorCode": 403,
            "ResponsePagePath": "/index.html",
            "ResponseCode": "200",
            "ErrorCachingMinTTL": 10
        },
        {
            "ErrorCode": 404,
            "ResponsePagePath": "/index.html",
            "ResponseCode": "200",
            "ErrorCachingMinTTL": 10
        }
    ]
}

設定を更新:

aws cloudfront update-distribution \
  --id E2YOGKTL016F74 \
  --distribution-config file://current-config.json \
  --if-match [先ほど取得したETag]

ステップ8: デプロイ完了の確認

aws cloudfront get-distribution --id E2YOGKTL016F74 --query "Distribution.Status" --output text

Deployedと表示されたら完了です(5-15分かかります)。

✅ 成功: これでhttps://[CloudFrontのドメイン名].cloudfront.netでアクセスできます!

コストについて

AWS無料枠(12ヶ月間)

サービス無料枠このアプリの使用量
S35GB保管、20,000 GET/月数MB(完全に無料枠内)
CloudFront1TB転送、10,000,000リクエスト/月低トラフィック(完全に無料枠内)
ACM(SSL証明書)永続無料無料

13ヶ月目以降

  • S3保管料: 数MB × $0.023/GB = 月$0.01未満
  • CloudFront: 低トラフィックなら月$0.01〜$0.10程度
  • 合計: 月$0.01〜$0.10程度(ほぼ無料)

更新方法

アプリを更新する際の手順です。

手動更新

# 1. ビルド
npm run build

# 2. S3にアップロード
aws s3 sync dist/ s3://your-app-name-2025 --delete

# 3. CloudFrontのキャッシュを無効化
aws cloudfront create-invalidation \
  --distribution-id E2YOGKTL016F74 \
  --paths "/index.html"
💡 コスト削減のヒント: Viteはファイル名にハッシュを付与するため、index.htmlのみ無効化すればOKです。

デプロイスクリプトの作成

毎回コマンドを打つのは面倒なので、スクリプトを作成します。

deploy.sh:

#!/bin/bash
set -e

echo "Building..."
npm run build

echo "Uploading to S3..."
aws s3 sync dist/ s3://your-app-name-2025 --delete

echo "Creating invalidation..."
aws cloudfront create-invalidation \
  --distribution-id E2YOGKTL016F74 \
  --paths "/index.html"

echo "Deployment complete!"

実行:

chmod +x deploy.sh
./deploy.sh

GitHub Actionsで自動デプロイ

Git pushで自動的にデプロイされるように設定できます。

.github/workflows/deploy.yml:

name: Deploy to AWS

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: Deploy to S3
        run: aws s3 sync dist/ s3://your-app-name-2025 --delete

      - name: Invalidate CloudFront cache
        run: |
          aws cloudfront create-invalidation \
            --distribution-id E2YOGKTL016F74 \
            --paths "/index.html"

必要なGitHub Secrets:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

トラブルシューティング

問題1: 403エラーが表示される

原因: S3バケットポリシーが正しく設定されていない

解決策:

# ポリシーを確認
aws s3api get-bucket-policy --bucket your-app-name-2025

# ポリシーを再適用
aws s3api put-bucket-policy --bucket your-app-name-2025 --policy file://s3-bucket-policy.json

問題2: ルーティングが動作しない

原因: カスタムエラーレスポンスが設定されていない

解決策: ステップ7の設定を再確認してください。

問題3: 更新が反映されない

原因: CloudFrontがキャッシュしている

解決策:

aws cloudfront create-invalidation \
  --distribution-id E2YOGKTL016F74 \
  --paths "/*"

まとめ

この方法で、ReactアプリをAWSに低コスト(ほぼ無料)でデプロイできました。

この構成のメリット

  • 低コスト: AWS無料枠内で運用可能
  • シンプル: サーバー管理不要
  • セキュア: HTTPS、OAC、パブリックアクセスブロック
  • 高速: CloudFront CDNでグローバル配信
  • スケーラブル: トラフィック増加に自動対応

応用

この手順は、React以外のSPA(Vue.js、Angularなど)でも同様に使えます。

参考: このデプロイ手順の詳細版(各コマンドの詳しい解説付き)は、こちらのドキュメントで公開しています。

質問やコメントがあれば、お気軽にどうぞ!

コメント

タイトルとURLをコピーしました