Amazon CloudFrontでReactを動かす
はじめに
以前フロントエンドをECS上のコンテナで動かしていたのですが、今にして思えばコンテナにしなくてもCloudFrontで良かったなと思うことがありましたので、CloudFront+S3の構成にする場合どんな感じのページなら動かせるのかというのを一部紹介したいと思います。
動作確認環境
M1 MacbookAir
node: v20.11.1
npm: 10.2.4
設定方法
buildコマンドを利用することで、CloudFront上で動作させることが可能です。
CloudFront+S3周りの設定に関しては別記事で紹介されておりますので、こちらを参考にしていただけますと幸いです。
①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を準備します。
サーバーの設定方法などはこちらの記事が参考になるかと思います。
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経由の情報が表示出来る状態になっているかと思います。

さいごに
今思えばあのときの構成ってこっちのサービス使ったほうが楽だったなと思うことが増えてきましたので、今後サービスを作っていく方の参考になれば幸いです。
テックブログ新着情報のほか、AWSやGoogle Cloudに関するお役立ち情報を配信中!
Follow @twitter2022年に中途入社した人です。好きなAWSサービスはLambdaです。
Recommends
こちらもおすすめ
-
「AWS Backup for Amazon S3」 の一般提供が公開されました
2022.3.11
-
FRONTEND CONFERENCE 2017 に参加してきました
2017.3.21
Special Topics
注目記事はこちら
データ分析入門
これから始めるBigQuery基礎知識
2024.02.28

AWSの料金が 10 %割引になる!
『AWSの請求代行リセールサービス』
2024.07.16



