ReactアプリをS3にCLIでデプロイしてどこからでもアクセスできるようにする


<h2>はじめに</h2>
ReactアプリをS3にデプロイして誰でもアクセスできるような環境を作成していきます！<br>
S3へのデプロイはAWSのマネコンからではなくCLIでできるようにするところまでがゴールになります！

<h2>①Reactアプリを作成</h2>
まずはNode.jsをインストールします。
インストールできたかどうかは以下コマンドで確認します。

```
node -v
npm -v
```

それぞれバージョンが表示されたら次はReactアプリを作成します。
今回はS3へのデプロイがメインのため、下記のコマンドを実行しすぐに動作確認ができるプロジェクトを作成します。

```
npx create-react-app my-app
```

作成したプロジェクトが動作するか確認するため以下コマンドを実行します。
※カレントディレクトリがmy-appの状態で実行すること
```
npm start
```

以下のような画面がブラウザで表示されていれば正しく起動できています。
<img width=200 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600719/b6835f65-a1e9-6afb-ef9d-8eebc70918f2.png">

起動が確認できればデプロイするアプリを作成するため以下のコマンドを実行します。
```
npm run build
```
buildフォルダ配下にファイル群が生成されていれば成功です🎉


<h2>②S3でバケットを作成する</h2>
S3にデプロイできるようにバケットを作成していきます。<br>
バケットとはファイル群を格納してくれるコンテナのことです。<br>
まずマネコンからS3を検索し画面へ遷移します。<br>
その後汎用バケットから「バケットを作成」を選択し任意の名前でバケットを作成します。

作成したバケットを選択してプロパティから静的ウェブサイトホスティングを編集します。
静的ウェブサイトホスティングを有効にした後、インデックスドキュメントの箇所にindex.htmlと入力、エラーでキュメントの箇所にerror.htmlと入力し空のhtmlファイルを作成します。
以下のような状態になっていれば問題ありません。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600719/aefdcd45-fcc7-a080-3d99-4e0e8e998922.png">

<h2>③S3にReactアプリをデプロイする</h2>
動作確認も兼ねて作成したReactアプリをマネコンからS3にデプロイしていきます。<br>
バケットのオブジェクトにbuildフォルダ配下のファイル群を選択してアップロードしてください。<br>

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600719/edbc3069-c8ea-3046-6e27-339a7a606eb8.png">

最後にバケット>プロパティ>静的ウェブサイトホスティング に記載しているURLにアクセスして①で確認した画面が表示されていればデプロイ成功です！

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600719/b69d0241-aad6-053a-836c-dd55172ce8d0.png">


<h2>④CLIでS3にデプロイできる環境を整える</h2>
作成したReactアプリをS3にデプロイして正常にアクセスできるかどうか確認ができました。<br>
しかし現状だとデプロイのタイミングで毎回AWSのマネコンにアクセスしてbuild配下のファイル群をアップロードしなければなりません。<br>
CLIでデプロイできるようにするとデプロイ作業が楽になりアップロードのミスもなくなるため設定していきます。

まずはS3へのアクセス設定をしていきます。
バケット>アクセス制御>パケットポリシー に以下コードを記述してCLIから特定のユーザーがS3を編集できるようにします。
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::${バケット名}",
                "arn:aws:s3:::${バケット名}/*"
            ]
        }
    ]
}
```

次にブロックパブリックアクセス (バケット設定)ですべてのチェックを外してCLIからファイル群にアクセスできるようにします。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600719/50db35b2-5b66-808e-de69-38486d28dd80.png">
※この設定ではセキュリティ的に安全ではないため、これからもS3を使い続ける場合は設定を見直してください

続いてS3へのアクセスを許可するIAMユーザーを作成します。
マネコンからIAMを検索し任意のユーザーを作成します。
作成時にアクセスキーとシークレットキーを忘れずに保存してください。

公式サイトの手順に従ってAWS CLIをインストールしてください。
https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html

インストール完了後、コンソールで以下のコマンドを実行すると作成したS3の設定やIAMユーザーのキーを求められるのでそれぞれ入力します。
```
aws configure
AWS Access Key ID [None]: ${アクセスキー}
AWS Secret Access Key [None]: ${シークレットキー}
Default region name [None]: ${region name}
Default output format [None]: json
```

<h2>⑤CLIでS3にデプロイする</h2>
デプロイできているかを目視できるようにReactアプリ内のApp.jsを編集します。<br>
今回はh1タグの要素を追加して「Hello World」を表示するように変更しました。

```App.js
fimport 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>
          Edit <code>src/App.js</code> and save to reload.
        </p>

        // 変更箇所
        <h1>Hello World</h1>
        
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;
```

次にS3にデプロイするファイル群を以下コマンドで生成します。
```
npm run build
```

最後に以下コマンドでbuildフォルダ配下のファイル群をS3にアップロードします。
```
aws s3 sync --delete --region ${region name} ./build/ s3://${バケット名}
```

③でアクセス確認したURLに再度アクセスし、以下の画面に遷移すればCLIからデプロイ成功です🎉
<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600719/7e8a8b36-0eb4-bd73-2dd2-0d7c5de2b573.png">