Cloud9でAWS Amplifyの公式チュートリアルGetting startedをやってみる

# 概要

タイトルの通りですが、AWSのCloud9でAmplifyのチュートリアルをやってみたので、その内容・手順を投稿します。
Amplifyとは何者か？わかっていなかったのですが、このチュートリアルを通して概要が理解できたため、公式のチュートリアルは**さすが良質な教材**でした。

具体的には以下を実施します。

https://docs.amplify.aws/start/q/integration/react/

このチュートリアルでは「**Todoアプリ**」を作成します。
Todoアプリを通して、Amplifyでの**ユーザー認証**、バックエンドにある**DynamoDB**に**GraphQL API**を使用し、アイテムを保存および取得することが出来るようになります。

チュートリアルでの使用するプログラミング言語はいくつか用意させれているようですが、本投稿では**React**を選択してします。

作業時間**1時間**ほどで実施できます。最終的には以下の「Todoアプリ」が出来上がります。

【Todoアプリ】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188544/7217ba0d-6c48-f4b1-d9c2-b338979f0053.png)

**Create Todo**ボタンで**Name**と**Description**に入力したTodoが登録され、画面下部に表示されます。

【認証画面】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188544/a28cd5ae-6250-ea34-03ee-f95f1543333d.png)

**Amplifyで用意された認証画面**でユーザ作成やユーザ認証が出来るようになります。

それでは、始めます。


## 前提条件

使用するCloud9はほぼデフォルト設定で使用できるのですが、以下だけ手動で変更しています。

* t2.medium 以上
* ディスク30GB 以上

1つ目は、メモリがある程度必要になるので、インスタントタイプに**t2.medium**を選択。
2つ目は、Cloud9でよくあることなのですが、初期のディスク容量が10GBしかないので今回は**30GB**に増設しています。（手順は割愛しますが、EC2のディスクメニューから行います）

チュートリアル上に書かれていますが、使用するツールのバージョンが以下のバージョン以降である必要があるため、開始する前に次のものがインストールされていることを確認します。

* Node.js v14.x 以降
* npm v6.14.4 以降
* git v2.14.1 以降

https://docs.amplify.aws/start/getting-started/installation/q/integration/react/


具体的には、それぞれ以下のコマンドで確認できます。（Cloud9の作成の時に古いOSを指定していなければ新しいバージョンのものがインストールされているので特に意識しなくても大丈夫です）

 * node -v
 * npm -v
 * git -v

## 参考書籍

Amplifyの知識の定着と基本的知識の補完に最適。

[AWS Amplify Studioではじめるフロントエンド+バックエンド統合開発](https://amzn.to/3PTYyxW "AWS Amplify Studioではじめるフロントエンド+バックエンド統合開発")
<a href="https://www.amazon.co.jp/dp/B0BD2TJJ4W?tag=blog_lambda_books_001-22&linkCode=ogi&th=1&psc=1" target="_blank" rel="noopener"><img border="0" src="https://m.media-amazon.com/images/I/516-b4QCRxL._SL160_.jpg" ></a>


Amplifyの日本語専門書としては現時点で唯一の専門書なのでAmplifyをやる上で参考書としていつも手元に置いておいてほしい一冊です。

## 結果

最初に結論です。
実施内容は、いくつかの**コマンド実行**と **2つのファイル修正（index.js/App.js）** だけになります。
これだけでCloud9上にAmplifyを使ったReactプロジェクトが作成されます。

### コマンド一覧

```bash
npm install -g @aws-amplify/cli
amplify configure
# Amplifyの設定コマンド。コマンド実行中にAWSコンソール上でのIAMユーザ作成が必要なります
npx create-react-app react-amplified-XXXX
# reactの雛形プロジェクト作成コマンド。後続のコマンド実行の中で「react-amplified-XXXX」を使ってS3バケットが作成されるため、重複しないように「XXXX」等少し変更しておくことをおすすめします
cd react-amplified-XXXX
amplify init
# Amplifyプロジェクト作成コマンド。
npm install aws-amplify
# Amplify Frameworkライブラリインストールコマンド。コマンド実行後、src/index.jsを開きAmplifyのインポート文を追加します
amplify add api
# AmplifyにGraphQL APIを追加するコマンド。
amplify push
# 追加したAPIをクラウド上のバックエンドAWSリソースに同期するコマンド。
# コマンド実行後、src/App.jsを開きGraphQL APIを使用したコードに置き換えます
amplify add auth
# Amplifyに認証を追加するコマンド。
amplify push
# 追加した認証をクラウド上のバックエンドAWSリソースに同期するコマンド。
npm install @aws-amplify/ui-react
# Amplify UIライブラリインストールコマンド。コマンド実行後、src/App.jsを開き認証コンポーネントの組み込みを行います
amplify add hosting
# Amplifyにホスティング環境を追加するコマンド。
amplify publish
# 追加したホスティング環境にReactプロジェクトを公開する。
```

詳細な説明は割愛しますが、以下が簡単な手順概略になります。

1. <font color="Red">Amplify CLI(aws-amplify/cli)</font>インストール
1. amplify configureコマンドによるシステム設定
1. reactの雛形プロジェクト作成
1. amplify initコマンドによるAmplifyプロジェクトの動作設定
1. <font color="Red">Amplify Framework(aws-amplify)</font> や aws-amplify/ui-react といったreactライブラリのインストール
1. amplify add XXXコマンドによる機能（認証やGraphQL API、ホスティングなど）追加
1. amplify pushコマンドでCloud9上で設定した内容をバックエンド（のAWSリソース 例えばCognito、DynamoDBなど）に反映
1. amplify publishコマンドでホスティング環境にデプロイ

赤字はAmplifyのポイントとなるコマンドです。次のAmplify全体概念図で説明します。

### Amplify全体概念図

自分なりに解釈した結果を図にすると以下のイメージになると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188544/b5d3ae99-188c-eb90-5a39-d354362672dd.png)

:::note warn
* Amplifyを使用する上で、<font color="Red">Amplify CLI</font>と<font color="Red">Amplify Framework</font>の2つをコマンドでインストールします。
    * Amplify CLI：Amplifyプロジェクトの作成やAmplifyの各機能（認証とかAPIとか。Amplifyの用語では**カテゴリ**と呼ぶ）のインストール、各機能のバックエンドへの反映を行う**Amplifyの専用コマンド群**です。
    * Amplify Framework：Amplifyのカテゴリを使用するための**クライアントライブラリ**（今回は後述のindex.jsやApp.jsで使用するJavaScriptのクライアントライブラリです）
* この2つを意識しないと非常に混乱します。
* 基本的なAmplifyの操作方法として、Cloud9上の**クライアント環境でAWS側のバックエンドサービスの設定含めて完結させる**（上記概念図の左側の実線部）ため、上記概念図のAmplifyより右側の点線部は意識しません。（もちろんAWSコンソール上から意識して確認することは可能です）
    * 後述のAmplifyのプロジェクトフォルダ内の**amplify**というフォルダにバックエンドの定義が保存されます
:::


### 修正後index.jsファイル

Amplify用のimportを追加し最終的には以下のファイルになります。

```js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { Amplify } from 'aws-amplify'; // Amplify Framework の読み込み
import awsExports from './aws-exports'; // バックエンド設定の読み込み
Amplify.configure(awsExports); // Amplify Frameworkにバックエンドの設定を登録

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
```

### 修正後App.jsファイル

Amplify用のimportやTodoアプリの実装（認証やGraphQLによるDynamoDBアクセス）を追加し最終的には以下のファイルになります。

```js
/* src/App.js */
import React, { useEffect, useState } from 'react'
import { Amplify, API, graphqlOperation } from 'aws-amplify'
import { createTodo } from './graphql/mutations'
import { listTodos } from './graphql/queries'
import { withAuthenticator, Button, Heading } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

import awsExports from "./aws-exports";
Amplify.configure(awsExports);

const initialState = { name: '', description: '' }

const App = ({ signOut, user }) => {
  const [formState, setFormState] = useState(initialState)
  const [todos, setTodos] = useState([])

  useEffect(() => {
    fetchTodos()
  }, [])

  function setInput(key, value) {
    setFormState({ ...formState, [key]: value })
  }

  async function fetchTodos() {
    try {
      const todoData = await API.graphql(graphqlOperation(listTodos))
      const todos = todoData.data.listTodos.items
      setTodos(todos)
    } catch (err) { console.log('error fetching todos') }
  }

  async function addTodo() {
    try {
      if (!formState.name || !formState.description) return
      const todo = { ...formState }
      setTodos([...todos, todo])
      setFormState(initialState)
      await API.graphql(graphqlOperation(createTodo, {input: todo}))
    } catch (err) {
      console.log('error creating todo:', err)
    }
  }

  return (
    <div style={styles.container}>
      <Heading level={1}>Hello {user.username}</Heading>
      <Button onClick={signOut} style={styles.button}>Sign out</Button>
      <h2>Amplify Todos</h2>
      <input
        onChange={event => setInput('name', event.target.value)}
        style={styles.input}
        value={formState.name}
        placeholder="Name"
      />
      <input
        onChange={event => setInput('description', event.target.value)}
        style={styles.input}
        value={formState.description}
        placeholder="Description"
      />
      <button style={styles.button} onClick={addTodo}>Create Todo</button>
      {
        todos.map((todo, index) => (
          <div key={todo.id ? todo.id : index} style={styles.todo}>
            <p style={styles.todoName}>{todo.name}</p>
            <p style={styles.todoDescription}>{todo.description}</p>
          </div>
        ))
      }
    </div>
  )
}

const styles = {
  container: { width: 400, margin: '0 auto', display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: 20 },
  todo: {  marginBottom: 15 },
  input: { border: 'none', backgroundColor: '#ddd', marginBottom: 10, padding: 8, fontSize: 18 },
  todoName: { fontSize: 20, fontWeight: 'bold' },
  todoDescription: { marginBottom: 0 },
  button: { backgroundColor: 'black', color: 'white', outline: 'none', fontSize: 18, padding: '12px 0px' }
}

export default withAuthenticator(App);
```

### Cloud9のReactプロジェクト フォルダ／ファイルリスト

最終的な成果物は以下のようになります。
（ビルドファイルなど自動的に作成される一部のファイルは割愛しています）

```bash
$ ls -lRt react-amplified-XXXX/

react-amplified-XXXX/:
total 2372
drwxrwxr-x    6 ec2-user ec2-user     143 Dec 17 01:33 amplify
-rw-rw-r--    1 ec2-user ec2-user     886 Dec 16 05:52 package.json
-rw-rw-r--    1 ec2-user ec2-user 2360099 Dec 16 05:52 package-lock.json
drwxrwxr-x    3 ec2-user ec2-user     187 Dec 16 05:25 src
drwxrwxr-x    2 ec2-user ec2-user     120 Dec 16 04:49 public
-rw-rw-r--    1 ec2-user ec2-user    3359 Dec 16 04:49 README.md

react-amplified-XXXX/amplify:
total 12
-rw-rw-r-- 1 ec2-user ec2-user 1010 Dec 17 01:35 team-provider-info.json
drwxrwxr-x 7 ec2-user ec2-user  151 Dec 16 05:49 backend
-rw-rw-r-- 1 ec2-user ec2-user 1834 Dec 16 05:06 cli.json
drwxrwxr-x 2 ec2-user ec2-user   76 Dec 16 05:05 hooks
-rw-rw-r-- 1 ec2-user ec2-user  393 Dec 16 05:05 README.md

react-amplified-XXXX/amplify/backend:
total 12
-rw-rw-r-- 1 ec2-user ec2-user 3806 Dec 17 01:33 amplify-meta.json
-rw-rw-r-- 1 ec2-user ec2-user 1206 Dec 16 05:45 backend-config.json
drwxrwxr-x 3 ec2-user ec2-user   36 Dec 16 05:45 auth
drwxrwxr-x 3 ec2-user ec2-user   28 Dec 16 05:30 hosting
drwxrwxr-x 3 ec2-user ec2-user   28 Dec 16 05:16 api
drwxrwxr-x 2 ec2-user ec2-user   50 Dec 16 05:06 types
drwxrwxr-x 3 ec2-user ec2-user   19 Dec 16 05:06 awscloudformation
-rw-rw-r-- 1 ec2-user ec2-user  135 Dec 16 05:05 tags.json

react-amplified-XXXX/amplify/backend/auth:
total 0
drwxrwxr-x 3 ec2-user ec2-user 42 Dec 16 05:45 reactamplified8ea01234

react-amplified-XXXX/amplify/backend/auth/reactamplified8ea01234:
total 4
-rw-rw-r-- 1 ec2-user ec2-user 1454 Dec 16 05:45 cli-inputs.json
drwxrwxr-x 2 ec2-user ec2-user   88 Dec 16 05:45 build

react-amplified-XXXX/amplify/backend/auth/reactamplified8ea01234/build:
total 20
-rw-rw-r-- 1 ec2-user ec2-user  1548 Dec 17 01:33 parameters.json
-rw-rw-r-- 1 ec2-user ec2-user 13498 Dec 17 01:33 reactamplified8ea01234-cloudformation-template.json

react-amplified-XXXX/amplify/backend/hosting:
total 0
drwxrwxr-x 2 ec2-user ec2-user 42 Dec 16 05:30 amplifyhosting

react-amplified-XXXX/amplify/backend/hosting/amplifyhosting:
total 4
-rw-rw-r-- 1 ec2-user ec2-user 757 Dec 16 05:31 amplifyhosting-template.json

react-amplified-XXXX/amplify/backend/api:
total 0
drwxrwxr-x 5 ec2-user ec2-user 145 Dec 16 05:17 reactamplified

react-amplified-XXXX/amplify/backend/api/reactamplified:
total 16
-rw-rw-r-- 1 ec2-user ec2-user 131 Dec 17 01:33 parameters.json
drwxrwxr-x 5 ec2-user ec2-user 135 Dec 17 01:33 build
-rw-rw-r-- 1 ec2-user ec2-user 196 Dec 16 05:16 cli-inputs.json
-rw-rw-r-- 1 ec2-user ec2-user 363 Dec 16 05:16 schema.graphql
drwxrwxr-x 2 ec2-user ec2-user  34 Dec 16 05:16 stacks
-rw-rw-r-- 1 ec2-user ec2-user  54 Dec 16 05:16 transform.conf.json
drwxrwxr-x 2 ec2-user ec2-user  23 Dec 16 05:16 resolvers

react-amplified-XXXX/amplify/backend/api/reactamplified/build:
total 24
-rw-rw-r-- 1 ec2-user ec2-user 10494 Dec 17 01:33 cloudformation-template.json
drwxrwxr-x 2 ec2-user ec2-user     6 Dec 17 01:33 functions
-rw-rw-r-- 1 ec2-user ec2-user   303 Dec 17 01:33 parameters.json
drwxrwxr-x 2 ec2-user ec2-user    51 Dec 17 01:33 stacks
drwxrwxr-x 2 ec2-user ec2-user  4096 Dec 17 01:33 resolvers
-rw-rw-r-- 1 ec2-user ec2-user  3748 Dec 17 01:33 schema.graphql

react-amplified-XXXX/amplify/backend/api/reactamplified/build/functions:
total 0

react-amplified-XXXX/amplify/backend/api/reactamplified/build/stacks:
total 40
-rw-rw-r-- 1 ec2-user ec2-user  1493 Dec 17 01:33 CustomResources.json
-rw-rw-r-- 1 ec2-user ec2-user 35961 Dec 17 01:33 Todo.json

react-amplified-XXXX/amplify/backend/api/reactamplified/build/resolvers:
total 108
-rw-rw-r-- 1 ec2-user ec2-user  475 Dec 17 01:33 Mutation.createTodo.init.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  210 Dec 17 01:33 Mutation.createTodo.postAuth.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user 2238 Dec 17 01:33 Mutation.createTodo.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  222 Dec 17 01:33 Mutation.createTodo.res.vtl
-rw-rw-r-- 1 ec2-user ec2-user  210 Dec 17 01:33 Mutation.deleteTodo.postAuth.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user 1847 Dec 17 01:33 Mutation.deleteTodo.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  222 Dec 17 01:33 Mutation.deleteTodo.res.vtl
-rw-rw-r-- 1 ec2-user ec2-user  350 Dec 17 01:33 Mutation.updateTodo.init.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  210 Dec 17 01:33 Mutation.updateTodo.postAuth.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user 4371 Dec 17 01:33 Mutation.updateTodo.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  222 Dec 17 01:33 Mutation.updateTodo.res.vtl
-rw-rw-r-- 1 ec2-user ec2-user  210 Dec 17 01:33 Query.getTodo.postAuth.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user 1208 Dec 17 01:33 Query.getTodo.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  381 Dec 17 01:33 Query.getTodo.res.vtl
-rw-rw-r-- 1 ec2-user ec2-user  210 Dec 17 01:33 Query.listTodos.postAuth.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user 1798 Dec 17 01:33 Query.listTodos.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  169 Dec 17 01:33 Query.listTodos.res.vtl
-rw-rw-r-- 1 ec2-user ec2-user  210 Dec 17 01:33 Subscription.onCreateTodo.postAuth.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  148 Dec 17 01:33 Subscription.onCreateTodo.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  249 Dec 17 01:33 Subscription.onCreateTodo.res.vtl
-rw-rw-r-- 1 ec2-user ec2-user  210 Dec 17 01:33 Subscription.onDeleteTodo.postAuth.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  148 Dec 17 01:33 Subscription.onDeleteTodo.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  249 Dec 17 01:33 Subscription.onDeleteTodo.res.vtl
-rw-rw-r-- 1 ec2-user ec2-user  210 Dec 17 01:33 Subscription.onUpdateTodo.postAuth.1.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  148 Dec 17 01:33 Subscription.onUpdateTodo.req.vtl
-rw-rw-r-- 1 ec2-user ec2-user  249 Dec 17 01:33 Subscription.onUpdateTodo.res.vtl

react-amplified-XXXX/amplify/backend/api/reactamplified/stacks:
total 4
-rw-rw-r-- 1 ec2-user ec2-user 1470 Dec 16 05:16 CustomResources.json

react-amplified-XXXX/amplify/backend/api/reactamplified/resolvers:
total 4
-rw-rw-r-- 1 ec2-user ec2-user 298 Dec 16 05:16 README.md

react-amplified-XXXX/amplify/backend/types:
total 4
-rw-rw-r-- 1 ec2-user ec2-user 584 Dec 17 01:33 amplify-dependent-resources-ref.d.ts

react-amplified-XXXX/amplify/backend/awscloudformation:
total 0
drwxrwxr-x 6 ec2-user ec2-user 107 Dec 16 05:45 build

react-amplified-XXXX/amplify/backend/awscloudformation/build:
total 16
-rw-rw-r-- 1 ec2-user ec2-user 14572 Dec 16 05:49 root-cloudformation-stack.json
drwxrwxr-x 3 ec2-user ec2-user    36 Dec 16 05:45 auth
drwxrwxr-x 3 ec2-user ec2-user    28 Dec 16 05:31 hosting
drwxrwxr-x 3 ec2-user ec2-user    19 Dec 16 05:21 awscloudformation
drwxrwxr-x 3 ec2-user ec2-user    28 Dec 16 05:21 api

react-amplified-XXXX/amplify/backend/awscloudformation/build/auth:
total 0
drwxrwxr-x 3 ec2-user ec2-user 19 Dec 16 05:45 reactamplified8ea01234

react-amplified-XXXX/amplify/backend/awscloudformation/build/auth/reactamplified8ea01234:
total 0
drwxrwxr-x 2 ec2-user ec2-user 65 Dec 16 05:45 build

react-amplified-XXXX/amplify/backend/awscloudformation/build/auth/reactamplified8ea01234/build:
total 16
-rw-rw-r-- 1 ec2-user ec2-user 13582 Dec 16 05:45 reactamplified8ea01234-cloudformation-template.json

react-amplified-XXXX/amplify/backend/awscloudformation/build/hosting:
total 0
drwxrwxr-x 2 ec2-user ec2-user 42 Dec 16 05:31 amplifyhosting

react-amplified-XXXX/amplify/backend/awscloudformation/build/hosting/amplifyhosting:
total 4
-rw-rw-r-- 1 ec2-user ec2-user 757 Dec 16 05:31 amplifyhosting-template.json

react-amplified-XXXX/amplify/backend/awscloudformation/build/awscloudformation:
total 0
drwxrwxr-x 2 ec2-user ec2-user 44 Dec 16 05:21 build

react-amplified-XXXX/amplify/backend/awscloudformation/build/awscloudformation/build:
total 16
-rw-rw-r-- 1 ec2-user ec2-user 14572 Dec 16 05:45 root-cloudformation-stack.json

react-amplified-XXXX/amplify/backend/awscloudformation/build/api:
total 0
drwxrwxr-x 3 ec2-user ec2-user 19 Dec 16 05:21 reactamplified

react-amplified-XXXX/amplify/backend/awscloudformation/build/api/reactamplified:
total 0
drwxrwxr-x 2 ec2-user ec2-user 42 Dec 16 05:21 build

react-amplified-XXXX/amplify/backend/awscloudformation/build/api/reactamplified/build:
total 8
-rw-rw-r-- 1 ec2-user ec2-user 7761 Dec 16 05:21 cloudformation-template.json

react-amplified-XXXX/amplify/hooks:
total 12
-rw-r--r-- 1 ec2-user ec2-user 678 Dec 16 05:05 post-push.sh.sample
-rw-r--r-- 1 ec2-user ec2-user 833 Dec 16 05:05 pre-push.js.sample
-rw-r--r-- 1 ec2-user ec2-user 412 Dec 16 05:05 README.md

react-amplified-XXXX/src:
total 36
-rw-rw-r-- 1 ec2-user ec2-user 2947 Dec 17 01:33 App.js
-rw-rw-r-- 1 ec2-user ec2-user 1207 Dec 16 05:49 aws-exports.js
drwxrwxr-x 2 ec2-user ec2-user   87 Dec 16 05:25 graphql
-rw-rw-r-- 1 ec2-user ec2-user  645 Dec 16 05:13 index.js
-rw-rw-r-- 1 ec2-user ec2-user 2632 Dec 16 04:49 logo.svg
-rw-rw-r-- 1 ec2-user ec2-user  362 Dec 16 04:49 reportWebVitals.js
-rw-rw-r-- 1 ec2-user ec2-user  241 Dec 16 04:49 setupTests.js
-rw-rw-r-- 1 ec2-user ec2-user  564 Dec 16 04:49 App.css
-rw-rw-r-- 1 ec2-user ec2-user  246 Dec 16 04:49 App.test.js
-rw-rw-r-- 1 ec2-user ec2-user  366 Dec 16 04:49 index.css

react-amplified-XXXX/src/graphql:
total 92
-rw-rw-r-- 1 ec2-user ec2-user   790 Dec 16 05:25 subscriptions.js
-rw-rw-r-- 1 ec2-user ec2-user   916 Dec 16 05:25 mutations.js
-rw-rw-r-- 1 ec2-user ec2-user   596 Dec 16 05:25 queries.js
-rw-rw-r-- 1 ec2-user ec2-user 79072 Dec 16 05:25 schema.json

react-amplified-XXXX/public:
total 36
-rw-rw-r-- 1 ec2-user ec2-user 3870 Dec 16 04:49 favicon.ico
-rw-rw-r-- 1 ec2-user ec2-user 1721 Dec 16 04:49 index.html
-rw-rw-r-- 1 ec2-user ec2-user 5347 Dec 16 04:49 logo192.png
-rw-rw-r-- 1 ec2-user ec2-user 9664 Dec 16 04:49 logo512.png
-rw-rw-r-- 1 ec2-user ec2-user  492 Dec 16 04:49 manifest.json
-rw-rw-r-- 1 ec2-user ec2-user   67 Dec 16 04:49 robots.txt
```

詳細は割愛しますが、要点としては以下が挙げられます。

* **amplify**というフォルダにバックエンドの定義が保存されます
    * チュートリアルでは、GraphQL API や認証などの機能をしているため、amplifyフォルダ配下に、バックエンドスタックを定義するコードとしてのインフラストラクチャテンプレートが保存されます
* Amplifyで作成するサービスの設定を保持する**aws-exports.js**というファイルがsrcディレクトリに作成されます

```src/aws-exports.js
/* eslint-disable */
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.

const awsmobile = {
    "aws_project_region": "ap-northeast-1",
    "aws_appsync_graphqlEndpoint": "https://XXXXXXXXXXXXX.appsync-api.ap-northeast-1.amazonaws.com/graphql",
    "aws_appsync_region": "ap-northeast-1",
    "aws_appsync_authenticationType": "API_KEY",
    "aws_appsync_apiKey": "***************************",
    "aws_cognito_identity_pool_id": "ap-northeast-1:XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX",
    "aws_cognito_region": "ap-northeast-1",
    "aws_user_pools_id": "ap-northeast-1_XXXXXXX",
    "aws_user_pools_web_client_id": "***************************",
    "oauth": {},
    "aws_cognito_username_attributes": [],
    "aws_cognito_social_providers": [],
    "aws_cognito_signup_attributes": [
        "EMAIL"
    ],
    "aws_cognito_mfa_configuration": "OFF",
    "aws_cognito_mfa_types": [
        "SMS"
    ],
    "aws_cognito_password_protection_settings": {
        "passwordPolicyMinLength": 8,
        "passwordPolicyCharacters": []
    },
    "aws_cognito_verification_mechanisms": [
        "EMAIL"
    ]
};


export default awsmobile;
```

このファイルに記録されるのは、Amplifyで作成するサービスの設定ということですが、DynamoDBの情報等はaws-exports.jsに記録されないのでフロントエンドからアクセスするバックエンドサービスのエンドポイントの設定内容が記録されるファイルかな。という印象です。



## 手順詳細

それではここからはチュートリアルのページに沿った手順詳細を説明してきます。

### Install and configure the Amplify CLI

まずは Amplify CLI のインストールと設定です。
公式ページは以下のページ。

https://docs.amplify.aws/start/getting-started/installation/q/integration/react/#install-and-configure-the-amplify-cli

Amplify CLI のインストールはコマンド実行だけなので簡単です。
以下のコマンドを実行します。

```bash
UserXXXXXXX:~/environment $ npm install -g @aws-amplify/cli

added 26 packages, and audited 27 packages in 17s

7 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

UserXXXXXXX:~/environment $
```

次のAmplify CLI の設定はコマンド実行とともに少し**AWS コンソール上での操作が必要**です。
コマンド実行中に手順に従って、AWSコンソール上でのIAMユーザ作成を行います。
amplify configure コマンド実行すると以下のようになります。
本来、自動的にブラウザが作成されAWSコンソールへのログインやIAMユーザが自動的に作成される仕組みのようですが、Cloud9上でブラウザが出来ないため一度エラーのメッセージが表示されますが、表示されている**URLを自分でブラウザに貼り付けて操作を続ければ設定は問題なく**実行できます。

```bash
UserXXXXXXX:~/environment $ amplify configure
Follow these steps to set up access to your AWS account:

Sign in to your AWS administrator account:
https://console.aws.amazon.com/
Press Enter to continue
🛑 spawn xdg-open ENOENT

Resolution: Please report this issue at https://github.com/aws-amplify/amplify-cli/issues and include the project identifier from: 'amplify diagnose --send-report'
Learn more at: https://docs.amplify.aws/cli/project/troubleshooting/

Session Identifier: ff133f1-a44c-409f-mod3-81297bd8f64a5a

Specify the AWS Region
? region:  ap-northeast-1
Specify the username of the new IAM user:
? user name:  amplify-19IB4
Complete the user creation using the AWS console
https://console.aws.amazon.com/iam/home?region=ap-northeast-1#/users$new?step=final&accessKey&userNames=amplify-19IB4&permissionType=policies&policies=arn:aws:iam::aws:policy%2FAdministratorAccess-Amplify
Press Enter to continue
🛑 spawn xdg-open ENOENT

Resolution: Please report this issue at https://github.com/aws-amplify/amplify-cli/issues and include the project identifier from: 'amplify diagnose --send-report'
Learn more at: https://docs.amplify.aws/cli/project/troubleshooting/

Session Identifier: ff133f1-a44c-409f-mod3-81297bd8f64a5a

Enter the access key of the newly created user:
? accessKeyId:  ********************
? secretAccessKey:  ****************************************
This would update/create the AWS Profile in your local machine
? Profile Name:  default

Successfully set up the new user.
UserXXXXXXX:~/environment $
```

region選択やIAMのユーザ名（user name）などいくつか対話側のやり取りがあるので、適切なものを選択します。IAMのユーザ名は何でも良い（上記はデフォルトのままです）のですが、このユーザが必要になるので、ユーザ名決定後表示されている以下のURLをAWSコンソールを開いているブラウザに貼り付けてユーザ作成を行います。

```
https://console.aws.amazon.com/iam/home?region=ap-northeast-1#/users$new?step=final&accessKey&userNames=amplify-19IB4&permissionType=policies&policies=arn:aws:iam::aws:policy%2FAdministratorAccess-Amplify
```

重要なのはURLの最後についている**AdministratorAccess-Amplify**ポリシーがAmplifyには必要ということです。
URL貼り付け後の画面上でも確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188544/b772a050-26cd-d330-0055-23da76be678e.png)

問題なければそのままAWSコンソール上での画面操作でユーザ作成を行い、ユーザ作成完了画面に表示されている**accessKeyId**/**secretAccessKey**をコマンド実行したターミナルに貼り付けます。（上記のコマンド結果で********************でマスクされている部分です）

この部分はチュートリアル上、動画でも解説されているので必要であれば動画で確認してみてください。以下の部分になります。

https://docs.amplify.aws/start/getting-started/installation/q/integration/react/#option-1-watch-the-video-guide


### Create a new React App

次の手順に移ります。次は、Reactの雛形プロジェクト作成です。
公式ページは以下のページ。

https://docs.amplify.aws/start/getting-started/setup/q/integration/react/#create-a-new-react-app

これはAmplifyとは関係のないReactの雛形プロジェクト作成のため、以下のコマンドを実行するだけです。**react-amplified-0001**部分がプロジェクト名になり、任意の名称に変更可能です。**S3バケット名の一部として使用される**ため、ユニークになるように自分の分かりやすい名称に変更することをオススメします。

```bash
UserXXXXXXX:~/environment $ npx create-react-app react-amplified-0001
Need to install the following packages:
  create-react-app@5.0.1
Ok to proceed? (y) 
npm WARN deprecated tar@2.2.2: This version of tar is no longer supported, and will not receive security updates. Please upgrade asap.

Creating a new React app in /home/ec2-user/environment/react-amplified-0001.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template...


added 1395 packages in 1m

214 packages are looking for funding
  run `npm fund` for details

Initialized a git repository.

Installing template dependencies using npm...

added 71 packages in 10s

226 packages are looking for funding
  run `npm fund` for details
Removing template package using npm...


removed 1 package, and audited 1466 packages in 3s

226 packages are looking for funding
  run `npm fund` for details

6 high severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

Created git commit.

Success! Created react-amplified-0001 at /home/ec2-user/environment/react-amplified-0001
Inside that directory, you can run several commands:

  npm start
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd react-amplified-0001
  npm start

Happy hacking!
UserXXXXXXX:~/environment $
```

無事に雛形プロジェクトの作成に成功したら、プロジェクトのルートフォルダに移動します。

```bash
UserXXXXXXX:~/environment $ cd react-amplified-0001
UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```


### Initialize a new backend

では、いよいよAmplify独自のAmplifyの設定手順に移ります。
公式ページは以下のページ。

https://docs.amplify.aws/start/getting-started/setup/q/integration/react/#initialize-a-new-backend

**amplify init**コマンドでAmplifyの設定を行います。
基本的に自動実行でプロジェクトの情報（NameやEnvironment、Default editorなど）が設定されるためそのまま継続します。
最後にCloudFormationを使ってIAMユーザはS3バケットが作成されていることがわかると思います。（万が一、S3バケットの名前がユニークでなかった場合、ここで失敗します。Reactの雛形プロジェクト作成からやり直しましょう。。。）

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ amplify init
Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project reactamplified0001
The following configuration will be applied:

Project information
| Name: reactamplified0001
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: react
| Source Directory Path: src
| Distribution Directory Path: build
| Build Command: npm run-script build
| Start Command: npm run-script start

? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS profile

For more information on AWS Profiles, see:
https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html

? Please choose the profile you want to use default
Adding backend environment dev to AWS Amplify app: d123qswk5htmod

Deployment completed.
Deployed root stack reactamplified0001 [ ======================================== ] 4/4
        amplify-reactamplified0001-de… AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Dec 17 2022 02:18:39…     
        UnauthRole                     AWS::IAM::Role                 CREATE_COMPLETE                Sat Dec 17 2022 02:18:37…     
        DeploymentBucket               AWS::S3::Bucket                CREATE_COMPLETE                Sat Dec 17 2022 02:18:27…     
        AuthRole                       AWS::IAM::Role                 CREATE_COMPLETE                Sat Dec 17 2022 02:18:36…     

✔ Help improve Amplify CLI by sharing non sensitive configurations on failures (y/N) · no
Deployment bucket fetched.
✔ Initialized provider successfully.
✅ Initialized your environment successfully.

Your project has been successfully initialized and connected to the cloud!

Some next steps:
"amplify status" will show you what you've added already and if it's locally configured or deployed
"amplify add <category>" will allow you to add features like user login or a backend API
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify console" to open the Amplify Console and view your project status
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

Pro tip:
Try "amplify add api" to create a backend API and then "amplify push" to deploy everything

UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

コマンド実行結果の以下に表示されている通り、Amplifyでは以下のコマンド群で操作することになります。

```bash
Some next steps:
"amplify status" will show you what you've added already and if it's locally configured or deployed
"amplify add <category>" will allow you to add features like user login or a backend API
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify console" to open the Amplify Console and view your project status
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud
```

今回のチュートリアルでは、**amplify status**と**amplify console**以外は実行する手順になっているので後の手順で試すことができます。
**amplify status**は手順にはありませんが、Amplifyの状態を確認するコマンドのため、いつ実行しても問題ありません。
**amplify console**はブラウザでAWSコンソールを開くコマンドなのでCloud9上では実行しても正しく動作しません。（自身のブラウザ操作でAWSコンソールのAmplifyメニューを表示すれば確認可能です）

### Install Amplify Libraries

次の手順はAmplifyのライブラリインストールになります。
公式ページは以下のページ。

https://docs.amplify.aws/start/getting-started/setup/q/integration/react/#install-amplify-libraries

手順は**npm install aws-amplify**コマンドを実行するだけになっています。
一部のライブラリが古いせいかセキュリティ警告が出るので理解して使いましょう。。。(^^;)

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ npm install aws-amplify
npm WARN deprecated source-map-url@0.4.1: See https://github.com/lydell/source-map-url#deprecated
npm WARN deprecated urix@0.1.0: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated resolve-url@0.2.1: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated source-map-resolve@0.5.3: See https://github.com/lydell/source-map-resolve#deprecated
npm WARN deprecated querystring@0.2.0: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uuid@3.4.0: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uuid@3.3.2: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.
npm WARN deprecated uglify-es@3.3.9: support for ECMAScript is superseded by `uglify-js` as of v3.13.0
npm WARN deprecated @aws-sdk/util-base64-browser@3.6.1: The package @aws-sdk/util-base64-browser has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-node@3.6.1: The package @aws-sdk/util-base64-node has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/eventstream-marshaller@3.6.1: The package @aws-sdk/eventstream-marshaller has been renamed to @aws-sdk/eventstream-codec. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-browser@3.186.0: The package @aws-sdk/util-base64-browser has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-node@3.186.0: The package @aws-sdk/util-base64-node has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-browser@3.186.0: The package @aws-sdk/util-base64-browser has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-node@3.186.0: The package @aws-sdk/util-base64-node has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-browser@3.186.0: The package @aws-sdk/util-base64-browser has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-node@3.186.0: The package @aws-sdk/util-base64-node has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-browser@3.186.0: The package @aws-sdk/util-base64-browser has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-browser@3.186.0: The package @aws-sdk/util-base64-browser has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-node@3.186.0: The package @aws-sdk/util-base64-node has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-node@3.186.0: The package @aws-sdk/util-base64-node has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-browser@3.186.0: The package @aws-sdk/util-base64-browser has been renamed to @aws-sdk/util-base64. Please install the renamed package.
npm WARN deprecated @aws-sdk/util-base64-node@3.186.0: The package @aws-sdk/util-base64-node has been renamed to @aws-sdk/util-base64. Please install the renamed package.

added 1125 packages, and audited 2591 packages in 1m

243 packages are looking for funding
  run `npm fund` for details

6 high severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

Amplify Frameworkライブラリのインストールが完了すると、Amplifyの各機能（認証とかAPIとか。Amplifyの用語では**カテゴリ**と呼ぶ）を使用するためのクライアントライブラリを、Reactアプリで使用することができるようになるため、**src/index.js** ファイルに以下のimport文を追加します。

```src/index.js
import { Amplify } from 'aws-amplify';
import awsExports from './aws-exports';
Amplify.configure(awsExports);
```

### Connect API and database to the app

いよいよここからTodoアプリを作成するための手順に移ります。
最初はデータを保持するためのDynamoDBとDynamoDBアクセスのためのGraphQLの追加です。
公式ページは以下のページ。

https://docs.amplify.aws/start/getting-started/data-model/q/integration/react/

具体的には、**amplify add api**コマンドと、**amplify push**コマンドで実行します。
まずは**amplify add api**コマンドです。

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ amplify add api
? Select from one of the below mentioned services: GraphQL
? Here is the GraphQL API that we will create. Select a setting to edit or continue Continue
? Choose a schema template: Single object with fields (e.g., “Todo” with ID, name, description)

⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema
✔ Do you want to edit the schema now? (Y/n) · yes
Couldn’t find selected code editor (Visual Studio Code) on your machine.
? Try opening with system-default editor instead? Yes
✅ Successfully added resource reactamplified0001 locally

✅ Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

🛑 spawn xdg-open ENOENT

Resolution: Please report this issue at https://github.com/aws-amplify/amplify-cli/issues and include the project identifier from: 'amplify diagnose --send-report'
Learn more at: https://docs.amplify.aws/cli/project/troubleshooting/

Session Identifier: c7e413414-173f-4663-modf-134134jiouoh
UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

特にこだわらなければデフォルトのままで大丈夫です。
このコマンドの中でTodoアプリのDynamoDB定義が自動作成されていることがわかると思います。
警告が出ている通りですが、**WARNING: your GraphQL API currently allows public**であることを認識して使用しましょう。**via an API Key**ではありますが。

次は、**amplify push**コマンドの実行です。

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ amplify push
⠙ Fetching updates to backend environment: dev from the cloud.
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema
✔ Successfully pulled backend environment dev from the cloud.
⠹ Building resource api/reactamplified0001
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema

    Current Environment: dev
    
┌──────────┬────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name      │ Operation │ Provider plugin   │
├──────────┼────────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified0001 │ Create    │ awscloudformation │
└──────────┴────────────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes

⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema
⠦ Building resource api/reactamplified0001
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema
? Do you want to generate code for your newly created GraphQL API Yes
? Choose the code generation language target javascript
? Enter the file name pattern of graphql queries, mutations and subscriptions src/graphql/**/*.js
? Do you want to generate/update all possible GraphQL operations - queries, mutations and subscriptions Yes
? Enter maximum statement depth [increase from default if your schema is deeply nested] 2

Deployment completed.
Deployed root stack reactamplified0001 [ ======================================== ] 2/2
        amplify-reactamplified0001-de… AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Dec 17 2022 02:30:08…     
        apireactamplified0001          AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Dec 17 2022 02:30:04…     
Deployed api reactamplified0001 [ ======================================== ] 6/6
        GraphQLAPI                     AWS::AppSync::GraphQLApi       CREATE_COMPLETE                Sat Dec 17 2022 02:26:40…     
        GraphQLAPIDefaultApiXXX123456… AWS::AppSync::ApiKey           CREATE_COMPLETE                Sat Dec 17 2022 02:26:44…     
        GraphQLAPITransformerSchema3C… AWS::AppSync::GraphQLSchema    CREATE_COMPLETE                Sat Dec 17 2022 02:27:46…     
        GraphQLAPIABCDS983766MOD       AWS::AppSync::DataSource       CREATE_COMPLETE                Sat Dec 17 2022 02:26:45…     
        Todo                           AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Dec 17 2022 02:29:24…     
        CustomResourcesjson            AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Dec 17 2022 02:29:38…     

✔ Generated GraphQL operations successfully and saved at src/graphql


GraphQL endpoint: https://XXXXXXXXXXXXX.appsync-api.ap-northeast-1.amazonaws.com/graphql
GraphQL API KEY: ***************************

GraphQL transformer version: 2

UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

こちらもこだわらなければデフォルトのままで大丈夫です。
ここでも何回も警告が出ているので、**WARNING: your GraphQL API currently allows public**であることを認識して使用しましょう。
コマンド実行の最後の**GraphQL endpoint**と、**API KEY**が表示されるので認識しておきましょう。（上記のコマンド結果はもちろんマスクしています）

コマンド実行中の表示内容で確認できますが、**amplify push**コマンドでCloudFormationによって必要なAWSのバックエンドサービスが作成されています。
つまり、**amplify add**コマンドでローカル環境（今回はCloud9上）のファイルにAWSリソース定義を行い、**amplify push**コマンドでCloudFormationを使ってAWSリソースが作成される仕組みがAmplifyなのだと理解できます。

最後に上記2つのコマンド実行でDBの準備ができたので、Reactアプリに取り込みましょう。
編集ファイルは**src/App.js**になります。

```src/App.js
/* src/App.js */
import React, { useEffect, useState } from 'react'
import { Amplify, API, graphqlOperation } from 'aws-amplify'
import { createTodo } from './graphql/mutations'
import { listTodos } from './graphql/queries'

import awsExports from "./aws-exports";
Amplify.configure(awsExports);

const initialState = { name: '', description: '' }

const App = () => {
  const [formState, setFormState] = useState(initialState)
  const [todos, setTodos] = useState([])

  useEffect(() => {
    fetchTodos()
  }, [])

  function setInput(key, value) {
    setFormState({ ...formState, [key]: value })
  }

  async function fetchTodos() {
    try {
      const todoData = await API.graphql(graphqlOperation(listTodos))
      const todos = todoData.data.listTodos.items
      setTodos(todos)
    } catch (err) { console.log('error fetching todos') }
  }

  async function addTodo() {
    try {
      if (!formState.name || !formState.description) return
      const todo = { ...formState }
      setTodos([...todos, todo])
      setFormState(initialState)
      await API.graphql(graphqlOperation(createTodo, {input: todo}))
    } catch (err) {
      console.log('error creating todo:', err)
    }
  }

  return (
    <div style={styles.container}>
      <h2>Amplify Todos</h2>
      <input
        onChange={event => setInput('name', event.target.value)}
        style={styles.input}
        value={formState.name}
        placeholder="Name"
      />
      <input
        onChange={event => setInput('description', event.target.value)}
        style={styles.input}
        value={formState.description}
        placeholder="Description"
      />
      <button style={styles.button} onClick={addTodo}>Create Todo</button>
      {
        todos.map((todo, index) => (
          <div key={todo.id ? todo.id : index} style={styles.todo}>
            <p style={styles.todoName}>{todo.name}</p>
            <p style={styles.todoDescription}>{todo.description}</p>
          </div>
        ))
      }
    </div>
  )
}

const styles = {
  container: { width: 400, margin: '0 auto', display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: 20 },
  todo: {  marginBottom: 15 },
  input: { border: 'none', backgroundColor: '#ddd', marginBottom: 10, padding: 8, fontSize: 18 },
  todoName: { fontSize: 20, fontWeight: 'bold' },
  todoDescription: { marginBottom: 0 },
  button: { backgroundColor: 'black', color: 'white', outline: 'none', fontSize: 18, padding: '12px 0px' }
}

export default App
```

### Add authentication

チュートリアルももう少しで完了です。次は認証機能を追加します。
公式ページは以下のページ。

https://docs.amplify.aws/start/getting-started/auth/q/integration/react/

手順としては1つ前の手順のDBの追加の時の同様で、**amplify add auth**コマンドと、**amplify push**コマンドで実行します。
まずは**amplify add auth**コマンドです。

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ amplify add auth
Using service: Cognito, provided by: awscloudformation
 
 The current configured provider is Amazon Cognito. 
 
 Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Username
 Do you want to configure advanced settings? No, I am done.
✅ Successfully added auth resource reactamplified0123d75dfmod locally

✅ Some next steps:
"amplify push" will build all your local backend resources and provision it in the cloud
"amplify publish" will build all your local backend and frontend resources (if you have hosting category added) and provision it in the cloud

UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

デフォルトのCognitoを使った認証で問題なければデフォルトのままで大丈夫です。
sign inのキー等、デフォルトから変更可能なようです。今回はデフォルトのままUsernameにしています。

続いて、**amplify push**コマンドの実行です。

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ amplify push
⠸ Fetching updates to backend environment: dev from the cloud.
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

⠴ Fetching updates to backend environment: dev from the cloud.✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema
✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev
    
┌──────────┬────────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name              │ Operation │ Provider plugin   │
├──────────┼────────────────────────────┼───────────┼───────────────────┤
│ Auth     │ reactamplified0123d75dfmod │ Create    │ awscloudformation │
├──────────┼────────────────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified0001         │ No Change │ awscloudformation │
└──────────┴────────────────────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes
⚠️ Amplify CLI now supports verifying a Cognito user email address that has been changed and will automatically update your auth configuration. Read more: https://docs.amplify.aws/lib/auth/manageusers/q/platform/js/#updating-and-verifying-a-cognito-user-email-address

Deployment completed.
Deployed root stack reactamplified0001 [ ======================================== ] 3/3
        amplify-reactamplified0001-de… AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Dec 17 2022 02:35:33…     
        apireactamplified0001          AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Dec 17 2022 02:32:44…     
        authreactamplified0001235mod0a AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Dec 17 2022 02:35:01…     
Deployed auth reactamplified0001235dfmod [ ======================================== ] 10/10
        UserPool                       AWS::Cognito::UserPool         CREATE_COMPLETE                Sat Dec 17 2022 02:32:31…     
        UserPoolClient                 AWS::Cognito::UserPoolClient   CREATE_COMPLETE                Sat Dec 17 2022 02:32:35…     
        UserPoolClientWeb              AWS::Cognito::UserPoolClient   CREATE_COMPLETE                Sat Dec 17 2022 02:32:36…     
        UserPoolClientRole             AWS::IAM::Role                 CREATE_COMPLETE                Sat Dec 17 2022 02:33:13…     
        UserPoolClientLambda           AWS::Lambda::Function          CREATE_COMPLETE                Sat Dec 17 2022 02:33:24…     
        UserPoolClientLambdaPolicy     AWS::IAM::Policy               CREATE_COMPLETE                Sat Dec 17 2022 02:34:02…     
        UserPoolClientLogPolicy        AWS::IAM::Policy               CREATE_COMPLETE                Sat Dec 17 2022 02:34:39…     
        UserPoolClientInputs           Custom::LambdaCallout          CREATE_COMPLETE                Sat Dec 17 2022 02:34:46…     
        IdentityPool                   AWS::Cognito::IdentityPool     CREATE_COMPLETE                Sat Dec 17 2022 02:34:52…     
        IdentityPoolRoleMap            AWS::Cognito::IdentityPoolRol… CREATE_IN_PROGRESS             Sat Dec 17 2022 02:34:55…     



GraphQL transformer version: 2

UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

こちらもDBの時と同様、認証に必要なAWSサービスがCloudFormationによって作成されていることがわかると思います。

最後に認証処理を**src/App.js**に取り込んで手順完了です。
という流れなのですが、認証処理にAmplifyで用意されている認証画面等のUIライブラリを使用するのでUIライブラリの追加コマンドを事前に実行します。

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ npm install @aws-amplify/ui-react

added 156 packages, and audited 2747 packages in 43s

257 packages are looking for funding
  run `npm fund` for details

6 high severity vulnerabilities

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

コマンド実行が無事に成功したら、改めて最後に認証処理を**src/App.js**に取り込んで手順完了です。

```src/App.js
/* src/App.js */
import React, { useEffect, useState } from 'react'
import { Amplify, API, graphqlOperation } from 'aws-amplify'
import { createTodo } from './graphql/mutations'
import { listTodos } from './graphql/queries'
import { withAuthenticator, Button, Heading } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';

import awsExports from "./aws-exports";
Amplify.configure(awsExports);

const initialState = { name: '', description: '' }

const App = ({ signOut, user }) => {
  const [formState, setFormState] = useState(initialState)
  const [todos, setTodos] = useState([])

  useEffect(() => {
    fetchTodos()
  }, [])

  function setInput(key, value) {
    setFormState({ ...formState, [key]: value })
  }

  async function fetchTodos() {
    try {
      const todoData = await API.graphql(graphqlOperation(listTodos))
      const todos = todoData.data.listTodos.items
      setTodos(todos)
    } catch (err) { console.log('error fetching todos') }
  }

  async function addTodo() {
    try {
      if (!formState.name || !formState.description) return
      const todo = { ...formState }
      setTodos([...todos, todo])
      setFormState(initialState)
      await API.graphql(graphqlOperation(createTodo, {input: todo}))
    } catch (err) {
      console.log('error creating todo:', err)
    }
  }

  return (
    <div style={styles.container}>
      <Heading level={1}>Hello {user.username}</Heading>
      <Button onClick={signOut} style={styles.button}>Sign out</Button>
      <h2>Amplify Todos</h2>
      <input
        onChange={event => setInput('name', event.target.value)}
        style={styles.input}
        value={formState.name}
        placeholder="Name"
      />
      <input
        onChange={event => setInput('description', event.target.value)}
        style={styles.input}
        value={formState.description}
        placeholder="Description"
      />
      <button style={styles.button} onClick={addTodo}>Create Todo</button>
      {
        todos.map((todo, index) => (
          <div key={todo.id ? todo.id : index} style={styles.todo}>
            <p style={styles.todoName}>{todo.name}</p>
            <p style={styles.todoDescription}>{todo.description}</p>
          </div>
        ))
      }
    </div>
  )
}

const styles = {
  container: { width: 400, margin: '0 auto', display: 'flex', flexDirection: 'column', justifyContent: 'center', padding: 20 },
  todo: {  marginBottom: 15 },
  input: { border: 'none', backgroundColor: '#ddd', marginBottom: 10, padding: 8, fontSize: 18 },
  todoName: { fontSize: 20, fontWeight: 'bold' },
  todoDescription: { marginBottom: 0 },
  button: { backgroundColor: 'black', color: 'white', outline: 'none', fontSize: 18, padding: '12px 0px' }
}

export default withAuthenticator(App);
```

### Deploy and host app

では、いよいよ最後の手順です！
ホスティング環境にデプロイして動作確認してみましょう！！
公式ページは以下のページ。

https://docs.amplify.aws/start/getting-started/hosting/q/integration/react/

ホスティング環境の追加は、**amplify add hosting**コマンドと、**amplify publish**コマンドで行います。（amplify pushコマンドではないので注意してください）

では、**amplify add hosting**コマンドを実行します。

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ amplify add hosting
✔ Select the plugin module to execute · Hosting with Amplify Console (Managed hosting with custom domains, Continuous deployment)
? Choose a type Manual deployment

You can now publish your app using the following command:

Command: amplify publish
UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

Manual deploymentも出来るようですが、チュートリアルはデフォルトのままで大丈夫です。
無事にコマンド実行が成功すると思います。

では、いよいよ最後のコマンド、**amplify publish**コマンドの実行です。

```bash
UserXXXXXXX:~/environment/react-amplified-0001 (master) $ amplify publish
⠼ Fetching updates to backend environment: dev from the cloud.
⚠️  WARNING: your GraphQL API currently allows public create, read, update, and delete access to all models via an API Key. To configure PRODUCTION-READY authorization rules, review: https://docs.amplify.aws/cli/graphql/authorization-rules

⠇ Fetching updates to backend environment: dev from the cloud.✅ GraphQL schema compiled successfully.

Edit your schema at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema.graphql or place .graphql files in a directory at /home/ec2-user/environment/react-amplified-0001/amplify/backend/api/reactamplified0001/schema
✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev
    
┌──────────┬────────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name              │ Operation │ Provider plugin   │
├──────────┼────────────────────────────┼───────────┼───────────────────┤
│ Hosting  │ amplifyhosting             │ Create    │ awscloudformation │
├──────────┼────────────────────────────┼───────────┼───────────────────┤
│ Api      │ reactamplified0001         │ No Change │ awscloudformation │
├──────────┼────────────────────────────┼───────────┼───────────────────┤
│ Auth     │ reactamplified0001235dfmod │ No Change │ awscloudformation │
└──────────┴────────────────────────────┴───────────┴───────────────────┘
? Are you sure you want to continue? Yes

Deployment completed.
Deployed root stack reactamplified0001 [ ======================================== ] 4/4
        amplify-reactamplified0001-de… AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Dec 17 2022 02:42:03…     
        hostingamplifyhosting          AWS::CloudFormation::Stack     CREATE_COMPLETE                Sat Dec 17 2022 02:41:37…     
        apireactamplified0001          AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Dec 17 2022 02:41:48…     
        authreactamplified0001235dfmod AWS::CloudFormation::Stack     UPDATE_COMPLETE                Sat Dec 17 2022 02:41:27…     
Deployed hosting amplifyhosting [ ======================================== ] 1/1
        AmplifyBranch                  AWS::Amplify::Branch           CREATE_COMPLETE                Sat Dec 17 2022 02:41:33…     



GraphQL transformer version: 2

Publish started for amplifyhosting

> react-amplified-0001@0.1.0 build
> react-scripts build

Creating an optimized production build...
Compiled successfully.

File sizes after gzip:

  269.4 kB  build/static/js/main.76febmod.js
  33.2 kB   build/static/css/main.3d1modf8.css
  1.79 kB   build/static/js/787.0modb02d.chunk.js

The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.

The build folder is ready to be deployed.
You may serve it with a static server:

  npm install -g serve
  serve -s build

Find out more about deployment here:

  https://cra.link/deployment

✔ Zipping artifacts completed.
✔ Deployment complete!
https://dev.XXXXXXXXXXXXXX.amplifyapp.com
UserXXXXXXX:~/environment/react-amplified-0001 (master) $
```

**Are you sure you want to continue?** で確認が求められ、問題なければそのまま継続するとデプロイが自動的に行われます。

最後に表示される以下がReactTodoアプリのアクセスURLになります。

```url
https://dev.XXXXXXXXXXXXXX.amplifyapp.com
```

実際にアクセスすると以下の画面が表示されると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188544/a28cd5ae-6250-ea34-03ee-f95f1543333d.png)

**Create Account**からユーザ登録してTodoアプリを触ってみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188544/3d376cf2-9a95-5b03-6d54-fb43bb024429.png)

**ユーザ登録には認証を追加した時のデフォルト設定でメールアドレスの認証設定が入っているので有効なメールアドレスが必要になります**（ここで入力するメールアドレスに認証キーが送信されるのでその認証キーを次の画面に入力することでユーザ登録が完了になります）
これら全てAmplifyで用意されている自動処理になります。凄いですね。。。

以上です！！！

## まとめ

以上でチュートリアルは終了です。
それなりに量があったのでなかなかの作業でしたがAmplifyの概念や基本操作が理解できる良いチュートリアルだったかなと思っています。
このチュートリアルを活かして自分なりのカスタマイズを徐々に増やしていこうと思います。


## 参考URL

* AmplifyCLI

https://docs.amplify.aws/cli/

* AmplifyJS

npm install aws-amplify

https://aws-amplify.github.io/amplify-js/api/index.html

## 資格取得に向けてAWSサービスを実際に利用してみるシリーズの投稿一覧

[とりあえず30分でAWS利用料金の高額請求に備える～予算アラート設定・MFA・料金確認～](https://qiita.com/fkooo/items/67c53c997508e25605ea "とりあえず30分でAWS利用料金の高額請求に備える～予算アラート設定・MFA・料金確認～")
[AWS ECSでDocker環境を試してみる](https://qiita.com/fkooo/items/d7d98e16e91921508450 "AWS ECSでDocker環境を試してみる")
[Amazon Cognitoを使ってシンプルなログイン画面を作ってみる](https://qiita.com/fkooo/items/660cab0090a80861155b "Amazon Cognitoを使ってシンプルなログイン画面を作ってみる")
[AWS NATゲートウェイを使ってプライベートサブネットからインターネットにアクセスする](https://qiita.com/fkooo/items/a474db0f3c2e72448d36 "AWS NATゲートウェイを使ってプライベートサブネットからインターネットにアクセスする")
[API GatewayをPrivateで作成してみる](https://qiita.com/fkooo/items/577831abd9803eb91b16 "API GatewayをPrivateで作成してみる")
[AWSのAI(Rekognition/Polly/Transcribe/Comprehend/Translate/Textract)サービスを試してみる](https://qiita.com/fkooo/items/10f75bafd08c60fc0a66 "AWSのAI(Rekognition/Polly/Transcribe/Comprehend/Translate/Textract)サービスを試してみる")
[AWS Lambda 同時実行数、エイリアス、環境変数とか実際の現場で使える機能を勉強してみる](https://qiita.com/fkooo/items/1b24e01252e145a378db "AWS Lambda 同時実行数、エイリアス、環境変数とか実際の現場で使える機能を勉強してみる")
[AWS Lambda SAMとは？～AWS SAMを使ってPythonのLambdaプログラムを簡単に作成する～](https://qiita.com/fkooo/items/2dc5ded5149379d7305a "AWS Lambda SAMとは？～AWS SAMを使ってPythonのLambdaプログラムを簡単に作成する～")
[AWS SAMを使って最もシンプルにLambda × APIGatewayのWebAPIを構築する](https://qiita.com/fkooo/items/e08cdea0f73f60dabd3d "AWS SAMを使って最もシンプルにLambda × APIGatewayのWebAPIを構築する")
[AWS SAMを使って最もシンプルにLambda × S3 のS3イベント駆動プログラムを構築する](https://qiita.com/fkooo/items/fa1d03c1d9e532956e2d "AWS SAMを使って最もシンプルにLambda × S3 のS3イベント駆動プログラムを構築する")
[Cloud9でAWS Amplifyの公式チュートリアルGetting startedをやってみる](https://qiita.com/fkooo/items/84f8f57e2317b0973496 "Cloud9でAWS Amplifyの公式チュートリアルGetting startedをやってみる")（本記事）