AppRunnerで三目並べReactアプリ10分クッキング
完成形
↑これ を作ります。
ソースコードは以下です。
事前準備
作る前に以下の準備を完了しておきます。
- GitHubアカウント作成
- GitHubとの接続設定
- VSCodeのインストール
- Node v16以上のセットアップ
Let'sクッキング
GitHubでリポジトリを新規作成する
適当なリポジトリ名を入力して、作成します。
ローカルにリポジトリをクローンして移動します。
Reactをセットアップする
インターネットブログなどを参考にセットアップしたけど、うまくいかなかった経験ありませんか?
Reactを始めとした新しい技術は日々進化しますので、公式ドキュメントに頼るのが正解です。
息を吸って吐くように公式ドキュメントを確認します。
オプション 2: ローカル開発環境 を参考に環境をセットアップします。
Gitリポジトリの直下に、Reactのプロジェクトを新規作成します。
cd Gitリポジトリパス
npx create-react-app .
プロジェクトを作成後、Reactのアプリが立ち上がることを確認します。
npm i
npm start
アプリケーションコードを作成する
こちらの公式チュートリアルの通り進めていきます。
10分クッキングのため、完成済みコードをコピペで作成します。
作成するファイルはindex.jsとindex.cssとなります。
以下に準備しておきました。
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
function Square(props) {
return (
<button className="square" onClick={props.onClick}>
{props.value}
</button>
)
}
class Board extends React.Component {
renderSquare(i) {
return (
<Square
value={this.props.squares[i]}
onClick={() => this.props.onClick(i)}
/>
)
}
render() {
return (
<div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
)
}
}
class Game extends React.Component {
constructor(props) {
super(props)
this.state = {
history: [
{
squares: Array(9).fill(null)
}
],
stepNumber: 0,
xIsNext: true
}
}
handleClick(i) {
const history = this.state.history.slice(0, this.state.stepNumber + 1)
const current = history[history.length - 1]
const squares = current.squares.slice()
if (calculateWinner(squares) || squares[i]) {
return
}
squares[i] = this.state.xIsNext ? 'X' : 'O'
this.setState({
history: history.concat([
{
squares: squares
}
]),
stepNumber: history.length,
xIsNext: !this.state.xIsNext
})
}
jumpTo(step) {
this.setState({
stepNumber: step,
xIsNext: step % 2 === 0
})
}
render() {
const history = this.state.history
const current = history[this.state.stepNumber]
const winner = calculateWinner(current.squares)
const moves = history.map((step, move) => {
const desc = move ? 'Go to move #' + move : 'Go to game start'
return (
<li key={move}>
<button onClick={() => this.jumpTo(move)}>{desc}</button>
</li>
)
})
let status
if (winner) {
status = 'Winner: ' + winner
} else {
status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O')
}
return (
<div className="game">
<div className="game-board">
<Board
squares={current.squares}
onClick={(i) => this.handleClick(i)}
/>
</div>
<div className="game-info">
<div>{status}</div>
<ol>{moves}</ol>
</div>
</div>
)
}
}
// ========================================
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(<Game />)
function calculateWinner(squares) {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
]
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i]
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a]
}
}
return null
}
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol,
ul {
padding-left: 30px;
}
.board-row:after {
clear: both;
content: "";
display: table;
}
.status {
margin-bottom: 10px;
}
.square {
background: #fff;
border: 1px solid #999;
float: left;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 34px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 34px;
}
.square:focus {
outline: none;
}
.kbd-navigation .square:focus {
background: #ddd;
}
.game {
display: flex;
flex-direction: row;
}
.game-info {
margin-left: 20px;
}
アプリの動作確認する
早速アプリの動作を確認しましょう。
ルートディレクトリにて、以下のコマンドを実行します。
npm start
ブラウザが立ち上がって、三目並べすることができます。
AppRunnerとは何か
先述の通り、新しい技術やサービスを扱うときは、まず公式ドキュメントからが鉄則でした。
AWS公式ドキュメントに目を通します。
AWS App Runner is an AWS service that provides **a fast, simple, and cost-effective way to deploy from source code or a container image directly to a scalable and secure web application in the AWS Cloud.
なるほど。ソースコードまたはコンテナイメージをAWSにデプロイするサービスですね。
早くてシンプルでコスパに優れている。すなはち、日清カップヌードルという理解で良さそうです(違
今回はGitHub上で管理しているソースコードをAppRunnerへデプロイしてみます。
AppRunnerとGitHubを連携する。
AWS管理コンソールにログインして、AppRunnerへアクセスします。
今回、米国リージョンを利用します。
米国の方が日本よりもちょっと安いので、検証であれば米国を積極的に使っていきます。
早速、サービスを作成をクリックします。
先述したとおり、GitHubで管理しているソースコードをデプロイしたいので、ソースコードデプロイを選択します。
新規追加をクリックして、「別のアプリケーションをインストールする」を選択してGitHubとの連携をします。
GitHub側でアプリに権限を渡すリポジトリを選択しInstall をクリックします。
これで次へを押すと、GitHubリポジトリとの連携ができます。
選択したリポジトリのみに権限設定した場合は、GitHubアカウント設定から以下のようにリポジトリを選択しておきます。AWS Connector for GitHubのConfigureをクリックして表示すると設定画面が出てきます。
AppRunnerのデプロイをセットアップする
GitHubとの連携ができましたら、デプロイしたいリポジトリとブランチを選択します。
今回、自動デプロイを選択します。こちらを選択することで、指定ブランチの変更を検知して自動デプロイを行ってくれます。めっちゃ便利!
続いて、構築設定です。Reactアプリを動かすためのの設定を行います。
Reactのデフォルトポート3000に変更するのをお忘れなく。
- ランタイム: Nodejs 16
- 構築コマンド: npm i
- 開始コマンド: npm start
- ポート: 3000
続いて、サービス設定です。ここでは、サービス名を入力して、 次へいきます。
最後に確認画面が出てきます。作成とデプロイ を押します。
こちらの画面が出てきて、デプロイが始まります。5分ぐらいかかります。
AppRunnerの動作を確認する
無事にデプロイできました!
デフォルトドメインのURLをクリックして確認してみます。
ちゃんと動きました!!バンザイ!
10分ぐらいでできたんでないでしょうか!
おまけ
構築設定をyaml化する
先程、構築設定をブラウザから手入力で設定しました。
しかし手入力ですと、タイポが発生する可能性があるため、あれ?動かない。といった事象に遭遇することがあります。
そこで、設定ファイルをyaml化することができます。
こちらをご確認ください。
apprunner.yamlというファイルをルートディレクトリに作成すれば良いみたいです。
例を参考につります。
version: 1.0
runtime: nodejs16
build:
commands:
build:
- npm i
run:
command: npm start
network:
port: 3000
apprunner.yamlを作成後、GitHubにpushします。
yamlファイルを使用する
以下のように、設定ファイルを使用する。に変更します。
ちゃんと動きました!
おわりに
GitHubでソース管理して、AppRunnerを作成設定するだけで、アプリを動かすことができました。
サーバを調達したり、EC2インスタンスやECSなどを用意せずとも動かすことができるので、便利!
プライベートサブネットのDBや他AWSサービスとの連携などについては、気が向いたら書きます。
以上。
Discussion