Amplify Gen2がGAしたので再Quickstartしてみた

Amplify Gen2がこの5月にGAしました。
それに際してドキュメントのQuickstartの内容も若干変化していたので、もう一回Quickstartしてみました。
参考; [Amplify Gen2ドキュメント](https://docs.amplify.aws/react/start/quickstart/)
これに続いてStorage機能を試す予定です。

# フルスタックアプリをAWSにデプロイする
デプロイはこんな流れです。
1. リポジトリの作成
1. 最初のアプリをデプロイ
1. アプリを確認する
## リポジトリの作成
ドキュメントの"Create repository from template"をクリックします。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart01.png )
クリックするとGitHubのリポジトリ作成画面になります。説明とリポジトリ名はあらかじめ記入してあります。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart02.png )
リポジトリ内部にはすでにVite+Reactのサンプルアプリがある状態になっています。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart03.png )

## 最初のアプリをデプロイ
ドキュメントの"Deploy to AWS"をクリックします。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart04.png)
そうすると、直近で使っていたAWSアカウントのAMplifyのページが開くのでGitHubを選択します。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart05.png)
設定したリポジトリを選択してデプロイします。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart06.png)
そうするとデプロイ待ち状態になります。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart07.png)
6分程度待つとデプロイが終了します。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart08.png)
この段階でAmplifyの設定ファイルをダウンロードして、プロジェクトの直下に配置します。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart10.png)


## アプリを確認する
デプロイしたURLにアクセスするとサンプルアプリを確認出来ます。
GA前と比べてオシャレなデザインですが、相変わらずDeleteやEdite機能は無いようです。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart09.png)
# フロントエンドを更新する
大きく以下の流れがあります
1. ローカル環境をセットアップ
1. 削除関数を準備
1. ログインUIを準備

## ローカル環境のセットアップ
以下の画像の"Download amplify_output.json"をクリックして設定ファイルをダウンロードします。
また、プロジェクトを作成したいディレクトリで以下にコマンドを実行してリモートリポジトリをクローンして必要なライブラリをインストールします。
```
git clone https://github.com/<github-user>/amplify-vite-react-template.git
cd amplify-vite-react-template && npm install
```
## 削除機能に追加
clone終了後、src/App.tsxを以下のように修正すると削除機能を追加出来ます。
```diff_typescript: src/App.tsx
import { useEffect, useState } from "react";
import type { Schema } from "../amplify/data/resource";
import { generateClient } from "aws-amplify/data";

const client = generateClient<Schema>();

function App() {
  const [todos, setTodos] = useState<Array<Schema["Todo"]["type"]>>([]);

  useEffect(() => {
    client.models.Todo.observeQuery().subscribe({
      next: (data) => setTodos([...data.items]),
    });
  }, []);

+ function createTodo() {
+   client.models.Todo.create({ content: window.prompt("Todo content") });
+  }
    
  function deleteTodo(id: string) {
    client.models.Todo.delete({ id })
  }

  return (
    <main>
      <h1>My todos</h1>
      <button onClick={createTodo}>+ new</button>
      <ul>
        {todos.map((todo) => (
          <li 
+         onClick={() => deleteTodo(todo.id)}
          key={todo.id}>{todo.content}</li>
        ))}
      </ul>
      <div>
        🥳 App successfully hosted. Try creating a new todo.
        <br />
        <a href="https://docs.amplify.aws/react/start/quickstart/#make-frontend-updates">
          Review next step of this tutorial.
        </a>
      </div>
    </main>
  );
}

export default App;

```
## ログインUIの追加
src/App.tsxを以下のように修正します。
```diff_typescript: src/App.tsx
import { Authenticator } from '@aws-amplify/ui-react'
import '@aws-amplify/ui-react/styles.css'
import { useEffect, useState } from "react";
import type { Schema } from "../amplify/data/resource";
import { generateClient } from "aws-amplify/data";

const client = generateClient<Schema>();

function App() {
  const [todos, setTodos] = useState<Array<Schema["Todo"]["type"]>>([]);

  useEffect(() => {
    client.models.Todo.observeQuery().subscribe({
      next: (data) => setTodos([...data.items]),
    });
  }, []);

  function createTodo() {
    client.models.Todo.create({ content: window.prompt("Todo content") });
  }
    
  function deleteTodo(id: string) {
    client.models.Todo.delete({ id })
  }

  return (
+  <Authenticator>
+     {({ signOut, user }) => (
    <main>
      <h1>My todos</h1>
      <button onClick={createTodo}>+ new</button>
      <ul>
        {todos.map((todo) => (
          <li 
          onClick={() => deleteTodo(todo.id)}
          key={todo.id}>{todo.content}</li>
        ))}
      </ul>
      <div>
        🥳 App successfully hosted. Try creating a new todo.
        <br />
        <a href="https://docs.amplify.aws/react/start/quickstart/#make-frontend-updates">
          Review next step of this tutorial.
        </a>
      </div>
+     <button onClick={signOut}>Sign out</button>
    </main>       
+    )}
+    </Authenticator>
  );
}

export default App;

```
以下の画像のようにログイン画面が実装出来ます。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart11.png)

# バックエンドの更新
大きく以下の流れがあります。
1. 認証情報をセットアップ
1. サンドボックスにデプロイ
1. ユーザ毎の認証制御を追加

## 認証情報をセットアップ
これは出来ている前提でスキップします。

## サンドボックスをデプロイ
cloneしたPJのディレクトリで以下のコマンドを実行するとサンドボックス環境が実行されます。
```
npx ampx sandbox
```
## ユーザ毎の認証制御を追加
次に自分が作成したTodoのみしか閲覧出来ないよう、"amplify/data/resource.ts"を編集してデータのアクセス制御を実装します。
```diff_typescript: amplify/data/resource.ts
import { type ClientSchema, a, defineData } from "@aws-amplify/backend";
const schema = a.schema({
  Todo: a
    .model({
      content: a.string(),
    })
-    // .authorization((allow) => [allow.publicApiKey()]),
+    .authorization(allow => [allow.owner()]),
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    defaultAuthorizationMode: "apiKey",
    // API Key is used for a.allow.public() rules
    apiKeyAuthorizationMode: {
      expiresInDays: 30,
    },
+    defaultAuthorizationMode: 'userPool',
  },
})

```

画面を確認すると、ログインユーザのEmailが表示されている事を確認しました。
![画像](https://d39oe90ddnxn3x.cloudfront.net/01_AmplifyGen2_ReQuickStart/01_AmplifyGen2_ReQuickStart12.png)
ドキュメントのQuickstratをここまでになります。

# まとめ&所感
ざっくりとサンプルアプリをデプロイする事が出来ました。
GA前と後で比べると、自分でnodeのインストールやamplifyをインストールする部分がSampleのレポジトリをインストールする事になった分だけ簡単になった一方で、自力の理解やセットアップ力向上の観点では悪くなった気がします。

それでもAmplifyの有用性は十分伝わる内容なので、多くの人に経験してもらえたらと思います。
ドキュメントがかなりしっかりしているので、このブログの意味は薄いすが、英語読むのが苦手な人の役にでも立てば嬉しいです。