Next.jsをAWSのAmplifyでデプロイした後にAPIに関していろいろ触ってみる
Amplify
Next.js
前回のAmplifyをReactで入門の続き
Prep
npm install -g @aws-amplify/cli
yarn create next-app lesson-amplify-next
cd lesson-amplify-next
amplify init
あとはNext.jsをお好きにカスタマイズ
今回はstyled-componentsとか入れていつもどおりにアプリ作る感じで進めていきたい.
参考
始める
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
deployする
deployはamplify add hosting
というコマンドで設定ファイルを生成できる.
ん〜
結構詰まった
GitHubのRepositoryを連携するときにロールを選択していないため,その作成を促される.初回はこんなことなかったので,やり直したり,amplefi configure
やamplify init
を繰り返したり,IAMユーザを新しく作ってみたりしたが変わらず.
最終的には促された通りにIAMロールを作成することでできた.
IAMユーザとIAMロールの違いや関係性がわからない...
読む
ん〜これらはアプリごとに作成しないといけないものなのだろうか...
結局deployも失敗...
もう一度やり直す.
deployできた
以下の参考の手順でできたCI/CDの設定はは除く
簡潔に書くと
amplify init
→質問に答えて完了→amplify add hosting
→GitHubのRepositoryと連携してdeploy
(さっき作ったIAMロールを選択)
注意点はpackage.json
のbuildコマンドをnext build && next export
に変更するのとDistribution Directory Path
をout
にすること
deployできたのはここ
よし,続ける
GraphQL APIを使う
認証機能がなくてもAPIを実装できるのか試したい
amplify add api
公式を参考
いけそうな感じはするamplify push
ができない
また最初から
最初から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
を押してみます.
デプロイも問題なくおこなえて,
APIでデータベースに変更を加えることができた.
amplify/backend/api/
の中にあるschema.graphql
に変更を加えて,amplify push
して,amplify pull
(正しい手順じゃないかも)するとなんと,スキーマの作成だけでなく,フロントのqueryやmutationや必要な型までコードを自動生成してくれる.
こいつはやべーぞ.
もうApollo使えなくていい.(調べたけど,AmplifyのGraphQL APIはApolloを参考に作っているので,Apolloを使用するメリットはそんなにないらしい)
こっからちょっとした掲示板を作っていこうかと
脱線する
ところでVercelはGitHubと連携して,デプロイするとそのRepositoryのPRのブランチもテストでビルドしてデプロイしてくれる.
これをやりたい.やりたいのだ.
調べてみた.
簡単そう.
できた!!!!!!
もう少し脱線
GraphQLでquery叩くときに型エラーが出ていたの気になったので直す.
ここで
const getTodos = async () => {
const result = await API.graphql(graphqlOperation(listTodos));
console.log(result.data.listTodos.items);
};
のように書くと,result.data.listTodos.items
でresultにdataなんてないけど🥺って言われる.
参考
こうすれば良い
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);
}
};
またこの記事は他にも参考になることが多いので謝謝.
SchemaのGraphQL Transformersの仕様がわからん
↓
ここ
結局難しいので,Admin UIから操作して作った!わかりやすい!
これで,デプロイ(これが結構時間かかる)したら右上のSetupにあるamplify pull --appId xxxxxxxxxx --envName dev
って感じのやつ
すでにあるデータを上書きするときはy
を選択する.
これで自動でSchemaとかqueryとかを作ってくれるので,ここから逆算して学ぶのはあり.
API.tsにある型が更新されていなかった.
amplify codegen
をすると更新された.
DynamoDBのデータはConflictResolutionってやつだとdeleteしても内部的に2日くらい残るらしい.
そのかわりに_delete
プロパティがtrueになるので,それを利用してフィルタリングをした.
ひとまず,ここまで作った.(記録サボってすみません.いろいろありました.)
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
する.
一通りは触ったかな.
subscription書くのがめんどいのと,
今回はPostに紐付いたCommentを保存する仕様だったのですが,保存時のパラメータにデフォルトでpostIdが必須じゃなかったのが気になりました.
あとは,データの削除は内部的には削除されていなく,queryを叩いたときに取得してしまうのをなんとかしたいなとは思いました.方法はいくらでもありそう.