Closed15

Next.jsをAWSのAmplifyでデプロイした後にAPIに関していろいろ触ってみる

Knob/のまど先生Knob/のまど先生

Amplify

https://aws.amazon.com/jp/amplify/

Next.js

https://nextjs.org/

前回のAmplifyをReactで入門の続き
https://zenn.dev/nbr41to/scraps/7b950e044bba84

Prep

npm install -g @aws-amplify/cli
yarn create next-app lesson-amplify-next
cd lesson-amplify-next
amplify init

あとはNext.jsをお好きにカスタマイズ
今回はstyled-componentsとか入れていつもどおりにアプリ作る感じで進めていきたい.

参考

https://zenn.dev/nus3/articles/89168a3485a544c792d5
https://qiita.com/t_okkan/items/38aca98993bf06598af6
https://qiita.com/Y_uuu/items/7111a6728f3acdcf8a8d

Knob/のまど先生Knob/のまど先生

始める

amplify initを叩くと初期設定をやってくれる

Note: It is recommended to run this command from the root of your app directory
? Enter a name for the project lessonAmplifyNext
The following configuration will be applied:

Project information
| Name: lessonAmplifyNext
| 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 Console app: xxxxxxxxxxxxxxx

前回の設定が残っているのか,調べた内容より聞かれる項目が少なかった.

これでroot直下にamplifyフォルダが作成されるはず.
また,Gitにあげてはいけないファイルなどが.gitignoreに追加される.

.gitignore

#amplify
amplify/\#current-cloud-backend
amplify/.config/local-*
amplify/logs
amplify/mock-data
amplify/backend/amplify-meta.json
amplify/backend/awscloudformation
amplify/backend/.temp
build/
dist/
node_modules/
aws-exports.js
awsconfiguration.json
amplifyconfiguration.json
amplifyconfiguration.dart
amplify-build-config.json
amplify-gradle-config.json
amplifytools.xcconfig
.secret-*

一応amplify/team-provider-info.jsonもignoreに追記した.
(ランダムな文字数字の羅列があるものは全部ignoreする精神)

こんな説明書きもあって親切.

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
Knob/のまど先生Knob/のまど先生

deployする

deployはamplify add hostingというコマンドで設定ファイルを生成できる.

ん〜
結構詰まった

GitHubのRepositoryを連携するときにロールを選択していないため,その作成を促される.初回はこんなことなかったので,やり直したり,amplefi configureamplify initを繰り返したり,IAMユーザを新しく作ってみたりしたが変わらず.

最終的には促された通りにIAMロールを作成することでできた.
IAMユーザとIAMロールの違いや関係性がわからない...

読む
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_roles_terms-and-concepts.html

ん〜これらはアプリごとに作成しないといけないものなのだろうか...

結局deployも失敗...

もう一度やり直す.

Knob/のまど先生Knob/のまど先生

deployできた

以下の参考の手順でできたCI/CDの設定はは除く
https://qiita.com/t_okkan/items/38aca98993bf06598af6
https://qiita.com/Y_uuu/items/7111a6728f3acdcf8a8d

簡潔に書くと
amplify init→質問に答えて完了→amplify add hosting→GitHubのRepositoryと連携してdeploy
(さっき作ったIAMロールを選択)
注意点はpackage.jsonのbuildコマンドをnext build && next exportに変更するのとDistribution Directory Pathoutにすること

deployできたのはここ
https://main.d1jrdm9h8fr4sf.amplifyapp.com/

よし,続ける

Knob/のまど先生Knob/のまど先生

最初からTake3

とりあえず,CLIで
amplify init
amplify add hosting
amplify add api
amplify push
の手順まで問題なく終えた.
ここからブラウザのコンソールで操作しそうな気がしている.
Admin UI managementを使うといろいろと便利そうなので,ONにします.
(初回は勝手にONになった気がするんだけどな...)

このトグルスイッチをONにすれば少し時間がかかるが,使えるようになります.
ただ,その後に下の

このラジオボタンをクリックしないと認証を求められました.
ラジオボタンをクリックしたら,Open Admin UIからとべます.

さて,
こちらの画面ではデータベースができていないようなので,
ContentsからGo to data to deployを押し,Enable DataStore to Deployを押してみます.

Knob/のまど先生Knob/のまど先生

デプロイも問題なくおこなえて,
APIでデータベースに変更を加えることができた.

amplify/backend/api/の中にあるschema.graphqlに変更を加えて,amplify pushして,amplify pull(正しい手順じゃないかも)するとなんと,スキーマの作成だけでなく,フロントのqueryやmutationや必要な型までコードを自動生成してくれる.
こいつはやべーぞ.

もうApollo使えなくていい.(調べたけど,AmplifyのGraphQL APIはApolloを参考に作っているので,Apolloを使用するメリットはそんなにないらしい)

こっからちょっとした掲示板を作っていこうかと

Knob/のまど先生Knob/のまど先生

もう少し脱線

GraphQLでquery叩くときに型エラーが出ていたの気になったので直す.

ここで

  const getTodos = async () => {
    const result = await API.graphql(graphqlOperation(listTodos));
      console.log(result.data.listTodos.items);
  };

のように書くと,result.data.listTodos.itemsでresultにdataなんてないけど🥺って言われる.

参考
https://qiita.com/otanu/items/2c522a652e5843a5e2c5

こうすれば良い

  const getTodos = async () => {
    const result = await API.graphql(graphqlOperation(listTodos));
    if ('data' in result && result.data) {
      const data = result.data as ListTodosQuery;
      console.log(data.listTodos.items);
      setTodos(data.listTodos.items);
    }
  };

またこの記事は他にも参考になることが多いので謝謝.

Knob/のまど先生Knob/のまど先生

結局難しいので,Admin UIから操作して作った!わかりやすい!

これで,デプロイ(これが結構時間かかる)したら右上のSetupにあるamplify pull --appId xxxxxxxxxx --envName devって感じのやつ
すでにあるデータを上書きするときはyを選択する.

これで自動でSchemaとかqueryとかを作ってくれるので,ここから逆算して学ぶのはあり.

Knob/のまど先生Knob/のまど先生

DynamoDBのデータはConflictResolutionってやつだとdeleteしても内部的に2日くらい残るらしい.
そのかわりに_deleteプロパティがtrueになるので,それを利用してフィルタリングをした.

ひとまず,ここまで作った.(記録サボってすみません.いろいろありました.)
https://main.d2iaoivzyqbd8t.amplifyapp.com/

Knob/のまど先生Knob/のまど先生

GrapQLAPIの使用方法

関数のみです

データの取得

query.tsにあるlistHogehogesを使う

export const getPosts = async () => {
  try {
    const result = await API.graphql(graphqlOperation(listPosts));
    if ('data' in result && result.data) {
      const data = result.data as ListPostsQuery;

      return data.listPosts.items.filter((item) => !item._deleted);
      // リストから削除されたものを除外(データ自体はしばらく残っているので)
    }
  } catch (error) {
    console.error(error);
  }
};

データの保存

mutation.tsにあるcreateHogehogeを使う

export const addPost = async (input: CreatePostInput) => {
  if (!input.name || !input.title || !input.content)
    return alert('入力してください');
  try {
    await API.graphql(graphqlOperation(createPost, { input }));
  } catch (error) {
    console.log(error);
  }
};

データの監視

subscriptions.tsにあるonCreateHogehogeなどを使う

今回は作成と削除を監視

export const subscribePost = (refetch: () => void) => {
  const onCreatePost = (
    API.graphql(
      graphqlOperation(subscriptions.onCreatePost)
    ) as Observable<OnCreatePostSubscription>
  ).subscribe({
    next: ({ value: { data } }: any) => {
      refetch();
    },
    error: (error) => console.error(error),
  });

  const onDeletePost = (
    API.graphql(
      graphqlOperation(subscriptions.onDeletePost)
    ) as Observable<OnDeletePostSubscription>
  ).subscribe({
    next: ({ value: { data } }: any) => {
      refetch();
    },
    error: (error) => console.error(error),
  });

  return [onCreatePost, onDeletePost];
};

next: ({ value: { data } }: any) => {で受け取ってくるものは変更されたデータのみ.
ここらへんはrefetchしてくれたほうが楽な気がしたので,refetch関数を自分で定義して実装した.

監視を辞める場合は,

  useEffect(() => {
    const dataFetch = () => {
      getPosts().then((posts) => {
        setPosts(posts);
      });
    };

    /* 1回目の取得 */
    dataFetch();

    /* それ以降の監視と再Fetch */
    const [onCreate, onDelete] = subscribePost(dataFetch);

    return () => {
      onCreate.unsubscribe();
      onDelete.unsubscribe();
    };
  }, []);

みたいに,unscribeする.

Knob/のまど先生Knob/のまど先生

一通りは触ったかな.
subscription書くのがめんどいのと,
今回はPostに紐付いたCommentを保存する仕様だったのですが,保存時のパラメータにデフォルトでpostIdが必須じゃなかったのが気になりました.
あとは,データの削除は内部的には削除されていなく,queryを叩いたときに取得してしまうのをなんとかしたいなとは思いました.方法はいくらでもありそう.

このスクラップは2021/07/31にクローズされました