Amazon CloudFrontでReactを動かす

AWS

2024.3.26

Topics

はじめに

以前フロントエンドをECS上のコンテナで動かしていたのですが、今にして思えばコンテナにしなくてもCloudFrontで良かったなと思うことがありましたので、CloudFront+S3の構成にする場合どんな感じのページなら動かせるのかというのを一部紹介したいと思います。

動作確認環境

M1 MacbookAir
node: v20.11.1
npm: 10.2.4

設定方法

buildコマンドを利用することで、CloudFront上で動作させることが可能です。
CloudFront+S3周りの設定に関しては別記事で紹介されておりますので、こちらを参考にしていただけますと幸いです。

関連記事
【やってみた】Amazon CloudFrontとAmazon S3を使って、静的サイトを作ってみた

関連記事
CloudFront + S3 静的サイト(開発/本番環境)のCI/CDパイプラインをCloudFormationで構築する

①CloudFront経由での表示について

まずはシンプルにinitしたてほやほやの状態を表示してみます。

npm init react-app sample-react
cd sample-react
npm run build

npm run buildの実行によりbuildフォルダが生成されますので、フォルダ配下のファイルをS3にアップロードを行いindex.htmlをデフォルトルートオブジェクトとして指定してあげることによりCloudFront経由で表示させることが可能です。

[waka]% tree build -L 2
build
├── asset-manifest.json
├── favicon.ico
├── index.html
├── logo192.png
├── logo512.png
├── manifest.json
├── robots.txt
└── static
    ├── css
    ├── js
    └── media

npm run build で生成したhtmlを開いた際に ERR_FILE_NOT_FOUND と言われた人へ

buildで生成したファイルの指定がうまく出来ていないようです。
package.jsonに "homepage": "." という記載を追加して再度buildを実行することで解消出来るかと思います。

...略...
  "name": "sample-react",
  "homepage": ".", // ここを追加
  "version": "0.1.0",
  "private": true,
...略...

②APIから動的に情報を取得して表示する

データ取得元はお好きなものを参照していただければいいのですが、本記事ではAPIGateway + Lambdaのサーバレス構成でAPIを準備します。
サーバーの設定方法などはこちらの記事が参考になるかと思います。

関連記事
「AWS Hands-on for Beginners Serverless #1」を参考にサーバーレスアーキテクチャ を Terraform で実装してみた

1. APIの準備

Hands-onの記事の内容から、lambda_function.py内容をGETで取得できる形に変更します。
今回は適当なUUIDと数字を返す処理を記載します。

lambda_function.py

import json
import uuid
import random
 
def lambda_handler(event, context):
    array = []
    count = random.randint(2, 50)
    for i in range(count):
    	body = {
    	    "id" : str(uuid.uuid4()),
    	    "number" : random.uniform(1, 2000)
    	}
    	array.append(body)
    response = { "data" : array }
    return {
        'statusCode': 200,
        'body': json.dumps(response),
        "headers": {
            "Access-Control-Allow-Origin": '*'
        }
    }

curlやpostmanでAPIを叩いた際に200OKが返ってくることが確認できました。

2. React側の準備

React側でAPIで受け取った内容を表示する処理を追記していきます。

mkdir src/components
cd $_
vim ApiFetch.js

./sample-react/src/components/ApiFetch.js

import React, {useState, useEffect} from 'react'

const ApiFetch = () => {
    const [posts, setPosts] = useState([])
    useEffect(() => {
        fetch('{ ここに取得したいAPIのエンドポイントを入れる }', {method: 'GET', mode: "cors", cache: "no-cache"}).then(res => res.json()).then(response => {
            setPosts(response.data)
        })
    },[])
    return (
        <div>
            <ul>
                {posts.map(post => <li key={post.id}>{post.number}</li>)}
            </ul>
            
        </div>
    )
}
export default ApiFetch

./sample-react/src/App.js

作成したファイルのimportとAPIで受け取ったデータの表示部分を記載します。

import logo from './logo.svg';
import './App.css';
import ApiFetch from './components/ApiFetch'; //追加

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <ApiFetch />   {/* 追加  */}
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

3. ローカルでの表示確認

npm startを実行すると、API経由で受け取った数字が箇条書きで表示されているような形になっているかと思います。

4. CloudFront経由での表示確認

ローカルでの表示確認ができましたら、./sample-react/build 配下のファイルをS3にアップロードしCloudFrontのキャッシュ削除を行うことで、API経由の情報が表示出来る状態になっているかと思います。

さいごに

今思えばあのときの構成ってこっちのサービス使ったほうが楽だったなと思うことが増えてきましたので、今後サービスを作っていく方の参考になれば幸いです。

waka

2022年に中途入社した人です。好きなAWSサービスはLambdaです。

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら