📣

Amplify Gen2という新しい開発体験

2023/11/24に公開

はじめに

こんにちは!
犬専用の音楽アプリ オトとりっぷでエンジニアしています、足立です!

https://www.oto-trip.com/

先週からの AWS Amplify launches ウィーク楽しいですね!
さまざまな発表がありましたが、中でも注目度が高いのが Amplify Gen2 ではないでしょうか。

この記事では、Amplify Gen2 という新しい開発体験を検証してみようと思います。
従来の Amplify 開発体験と何が違うの?という疑問を解決したい方の参考になれば幸いです。

目次

  • Amplify Gen2 とは?
  • サンプルを動かしてみる
  • 個人的 QA

Amplify Gen2 とは?

Amplify Gen2 とは、 Full TypeScript によるフルスタック開発を容易にしてくれる新たな Amplify 開発体験です。バックエンドリソースのデプロイ方法が、従来の CLI から CDK に変更され、それに伴い拡張性が高まりました。
主要なカテゴリとして、以下の 4 つが準備されています。

  • Authentication
  • Data
  • Storage
  • Functions

これ以外のカテゴリを追加したい場合は、CDK でカスタムリソースを設定することが可能です。
「CDK って何?」っていう初見の方は、CDK の公式ドキュメントをご覧ください。

新たな開発体験

新たな開発体験を表現する象徴的な動画が公式ドキュメントサイトに公開されていますが、実際にやってみたのがこちらです。

エディターの左側がフロントエンドのコード、右側がバックエンドのコード、下側に Sandbox コンソールを開いて、バックエンドのコードを変更している様子です。
doneというフィールドを必須で追加すると、フロントエンドの型エラーと Sandbox 環境の更新が同時に反映されました。
このように、モダンなフルスタック開発が可能になるのが Amplify Gen2 です!

サンプルを動かしてみる

ではさっそく公式クイックスタートを動かして、Amplify Gen2 を体験しようと思います。

Init Project

まずは、Next.js の新規アプリを作成します。
Page Router で src ディレクトリ無し設定です。

$ npm create next-app@14 -- next-amplify-gen2 --typescript --eslint --no-app --no-src-dir --no-tailwind --import-alias '@/*'
$ cd next-amplify-gen2

次に、Amplify Gen2 を使い始めるための init 処理を実施します。

$ npm create amplify@latest
> ? Where should we create your project? (.) # press enter

このコマンドによりamplify-backendという Amplify Gen2 をデプロするために必要なライブラリがインストールされ、初期セッティングが完了します。
新たに amplify ディレクトリと以下のようなファイル群が生成します。

├── amplify/
│   ├── auth/
│   │   └── resource.ts
│   ├── data/
│   │   └── resource.ts
│   ├── backend.ts
│   └── package.json

Start Sandbox

Amplify Gen2 の大きな特徴である、amplify sandbox を起動させてみます。
まずは公式の通り、クレデンシャル情報をセッティングしてください。

次に sandbox 生成コマンドを入力します。

$ npx amplify sandbox

そうすると、このユーザーのサンドボックス環境が存在しないことを検知して、バックエンドリソースが CDK によりデプロイされ始めました。Sandbox とは AWS 上にそのユーザー個人用の開発環境をデプロイしてくれるコマンドなんです。何ということでしょう!

CloudFormation 上に sandbox 用のスタックが作成されているのが確認できます。

また、DynamoDB も Sandbox 用の Table が作成されています。

これらを使って、実際に開発を進めていくわけですね。
Sandbox を起動したまま、次の作業へと移っていきましょう。

Create Backend

次に、データと認証機能をアプリに追加します。

/amplify/data/resource.tsという自動生成されたファイルを変更していきます。
以下の 3 点を修正します。

/amplify/data/resource.ts
import { a, defineData, type ClientSchema } from '@aws-amplify/backend';

const schema = a.schema({
  Todo: a
    .model({
      content: a.string()
      // 1. Todoリストにdoneとpriorityを追加する
+     done: a.boolean(),
+     priority: a.enum(['low', 'medium', 'high'])
    })
      // 2. 作者以外のユーザーからのアクセスを拒否する
-    .authorization([a.allow.owner(), a.allow.public().to(['read'])])
+    .authorization([a.allow.owner()]),
});

export type Schema = ClientSchema<typeof schema>;

export const data = defineData({
  schema,
  authorizationModes: {
    // 3. 認証モードをAPI KeyからCognitoに変更する
-    defaultAuthorizationMode: 'apiKey',
-    // API Key is used for a.allow.public() rules
-    apiKeyAuthorizationMode: {
-      expiresInDays: 30
-    }
+    defaultAuthorizationMode: 'userPool',
  }
});

そして以上の変更を保存すると、なんと Amplify 側が変更差分を検知して自動的に Sandbox 環境を更新してくれます。

[Sandbox] Running successfulDeployment event handlers
[Sandbox] Watching for file changes...
[Sandbox] Triggered due to a file update event: ~/next-amplify-gen2/amplify/data/resource.ts
[Sandbox] Executing command `deploy`

Update UI

では、バックエンド環境をフロントエンドに反映させましょう。
まず Amplify の UI ライブラリをインストールします。

$ npm add @aws-amplify/ui-react

次に、pages/_app.tsxを以下の通りに修正します。

pages/_app.tsx
// pages/_app.tsx
import { withAuthenticator } from '@aws-amplify/ui-react';
import { Amplify } from 'aws-amplify';
import config from '@/amplifyconfiguration.json';
import '@aws-amplify/ui-react/styles.css';
import type { AppProps } from 'next/app';

// configure the Amplify client library with the configuration generated by `amplify sandbox`
Amplify.configure(config);

function App({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default withAuthenticator(App);

これでアプリケーションを起動すると、認証画面が登場するようになります。

$ npm run dev

次に、Todo リストを表示するようにpages/index.tsxを以下の通り修正します。

pages/index.tsx
// pages/index.tsx
import { signOut } from 'aws-amplify/auth';
import { generateClient } from 'aws-amplify/data';
import { useEffect, useState } from 'react';

import { Schema } from '@/amplify/data/resource';

// generate your data client using the Schema from your backend
const client = generateClient<Schema>();

async function handleSignOut() {
  try {
    await signOut();
  } catch (error) {
    console.log('error signing out: ', error);
  }
}

export default function HomePage() {
  const [todos, setTodos] = useState<Schema['Todo'][]>([]);

  async function listTodos() {
    // fetch all todos
    const { data } = await client.models.Todo.list();
    setTodos(data);
  }

  useEffect(() => {
    listTodos();
  }, []);

  useEffect(() => {
    const sub = client.models.Todo.observeQuery().subscribe(({ items }) =>
      setTodos([...items])
    );

    return () => sub.unsubscribe();
  }, []);

  return (
    <main>
      <h1>Hello, Amplify 👋</h1>

      <button
        onClick={async () => {
          handleSignOut();
        }}
      >
        サインアウト
      </button>

      <button
        onClick={async () => {
          // create a new Todo with the following attributes
          const { errors, data: newTodo } = await client.models.Todo.create({
            // prompt the user to enter the title
            content: window.prompt('title'),
            done: false,
            priority: 'medium',
          });
          console.log(errors, newTodo);
        }}
      >
        Create
      </button>

      <ul>
        {todos.map((todo) => (
          <li key={todo.id}>{todo.content}</li>
        ))}
      </ul>
    </main>
  );
}

実際に動かした様子がこちらです!

Sandbox 環境に実際データが出入力されて、UI に反映されている様子が確認できます。
こうやって、AWS 実環境を動かしながら、バックエンドからフロントエンドまで一気通貫で開発できるわけです。

Deployment

公式ドキュメントの通り、AWS Amplify の Console 画面からデプロイ可能です。
Console 画面には Gen2 用の UI が追加されていますね。Gen1 と同じく、Github などのリモートレポジトリに接続することができます。

デプロイそのものは Gen1 と大きな変更がないので、こちらの記事では割愛します。

後片付け

Sandbox 環境が不要になったら、削除しましょう。
AWS Amplify の Console 画面に Sandbox 環境一覧があるので、そちらから削除可能です。

個人的 Q&A

最後に個人的に疑問に感じた点をメモしています。
(これ以外に「これってどうなの?」って気になるのがあれば、ぜひコメント下さい!)

全体的

そもそも Gen1 って?

ここの記載の通り、Amplify CLI による開発体験のことを Gen1 と呼ぶらしいです。

Gen1 との 1 番の違いは?

バックエンドリソースのデプロイ方法が、CLI にから CDK に変更されたことが一番大きい変更だと思います。Amplify がデフォルトで提供している機能以上のことがやりたい時に、CDK を書き足せば OK ってなりました。

Gen1 からアップグレードできるの?

FAQによると、Gen2 への移行ツールを提供予定だそうです。期待しましょう。

Data

Data カテゴリってそもそも何?

Amplify Gen1 でいうAPI (GraphQL)カテゴリです。
スキーマを設定すると、AWS AppSync - Amazon DynamoDB というリソースが構築されます。

データソースに何が使われてるの?

今のところ、Gen1 と同じく DynamoDB でした。
せっかく CDK と統合したので、ここのアップデートは期待したいところです。

DynamoDB のインデックス設定は柔軟なの?

今のところ、プライマリーキーとソートキーの設定方法のみここに記載されています。
セカンダリーインデックスの設定など複雑なことがやりたい時に、CDK 側で設定するのか Amplify スキーマ側で設定するのかについては言及がありませんでした。

最後に

ここまで読んでいただきありがとうございました。
さらに詳しく知りたい方は、公式ドキュメントに詳細が記載されていますので、そちらも併せてご覧ください。

何だかすごい進化しましたね、AWS Amplify。
まだプレビュー段階なので、まだまだ進化を期待したいところです。
GA されればぜひオトとりっぷでも活用してみたいと思います。

もし犬専用の音楽アプリに興味を持っていただけたら、ぜひダウンロードしてみてください!

https://www.oto-trip.com/

Discussion