この記事は「クソアプリ Advent Calendar 2021 2」の10日目の記事です。
去年はこちらで参加しました。
概要
今年下半期はAmplifyに大変悩まされたので、復習も兼ねてシンプルなアプリを作ってみました。
動作サンプル
https://dev.d1nlszba0lmhed.amplifyapp.com/
ポイント
CGI風の呼び出し
-
ContentType: image/***
のレスポンスを返すCGI風のエンドポイント - 最上位パスは無駄に
/cgi-bin/
- IMGタグで描画する懐かしのパターン
<div id="counterBox">
<span>ようこそ。あなたは</span>
<img src="https://ENDPOINT/cgi-bin/counter">
<span>人目のお客様です</span>
</div>
キリ番機能
CGIカウンター風のデータ構造
- 理想的には、1アクセス毎に「1」という1バイト文字列をテキストファイルに追記していき、テキストファイルのバイト数を調べることでカウントを得られるという例のアレがやりたい
- S3とか使えばできるような気もしたが、今回はAmplifyということで無駄にDynamoDBを使っていく
- アクセス毎に1レコードを無駄に追加していき、DynamoDBのAPIでテーブル全件カウントするという無茶な感じにしてみる
Amplifyで実装
amplify
コマンドで以下の構成を作っていきます。
resource | type | memo |
---|---|---|
backend/api/cgibin | REST | CGI風のエンドポイントを作るAPI Gateway |
backend/api/kiricounter | GraphQL | カウントをするDBとDB操作用のAppSync |
backend/function/counter | Lambda | CGI部分の実装 |
backend/function/appsync | Lambda Layer |
aws-appsync 等諸々のパッケージをLayer化 |
backend/hosting/amplify-hosting | 動作サンプルサイト |
ポイント
AppSync用のLambda Layer
- 今回特に分ける必要もないが、今後実際に使うときには分けておいた方がよさそうなので練習がてら作ってみる
- (
aws-appsync
かgraphql
かどちらか忘れたが)最新版を入れすぎると動かなかったので現状動いたものをメモ
package.json
{
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {
"aws-appsync": "^4.1.4",
"aws-sdk": "^2.1030.0",
"graphql": "^15.7.0",
"graphql-tag": "^2.12.6",
"isomorphic-fetch": "^3.0.0"
},
"devDependencies": {}
}
Lambda Layerを使う
-
amplify function update
からそれっぽいものを選んでいくだけ。便利 - メインのLambda自体の容量も小さくなるため、AWSのコンソールで直接編集もできるようになって便利
LambdaからAppSyncとDynamoDBを使う
-
amplify function update
のpermission
関係のところから同様に選んでいく - AppSyncはGraphQLのAPIを指定するとパーミッションが貰える
- DynamoDBは
storage
カテゴリに属している(わかりにくい)ため、そこから選んでいく- 使いたいDynamoDBテーブルをスペースで複数選択していく
- 欲しいものだけ貰えて便利
- パーミッションが貰えると
src/index.js
に環境変数が書き込まれる - 便利
backend/function/counter/src/index.js
/* Amplify Params - DO NOT EDIT
API_KIRICOUNTER_COUNTERTABLE_ARN
API_KIRICOUNTER_COUNTERTABLE_NAME
API_KIRICOUNTER_GRAPHQLAPIENDPOINTOUTPUT
API_KIRICOUNTER_GRAPHQLAPIIDOUTPUT
ENV
REGION
Amplify Params - DO NOT EDIT */
require('isomorphic-fetch')
const aws = require('aws-sdk')
const gql = require('graphql-tag')
const AWSAppSyncClient = require('aws-appsync').default
const { AUTH_TYPE } = require('aws-appsync')
const client = new AWSAppSyncClient({
url: process.env['API_KIRICOUNTER_GRAPHQLAPIENDPOINTOUTPUT'],
region: process.env['REGION'],
auth: {
type: AUTH_TYPE.AWS_IAM,
credentials: ()=> aws.config.credentials
},
disableOffline: true
})
const incrementMutation = gql
`mutation MyMutation {
createCounter(input: {count: "1"}) {
createdAt
}
}
`
const increment = () => {
return client.mutate(
{
mutation: incrementMutation
}
).then((result) => {
if (result) {
// console.log('result', result)
return result
} else {
Promise.reject('error. increment result is null')
}
}).catch(console.error)
}
const docmentClient = new aws.DynamoDB.DocumentClient()
const count = () => {
const params = {
TableName: process.env['API_KIRICOUNTER_COUNTERTABLE_NAME'],
Select:'COUNT'
};
return docmentClient.scan(params).promise()
.then((data) => {
if (data) {
console.log('count result', data)
return data
} else {
Promise.reject('error. count result is null')
}
}).catch(console.error)
}
気を付けるポイント
-
amplify add
で出来る設定はupdate
でも大体やり直せる- 名前とかは無理そうだが、それ以外は何度でもやり直せるので気にせずガシガシやって大丈夫
-
amplify remove
する時は依存関係から先に消す- 依存しているAuthやLayerやPermissionが残っている状態で消そうとすると泣きそうになるくらいのエラーになるので気を付ける
-
amplify push
するとデプロイした情報がローカルに保存される-
team-provider-info.json
などに差分が出るため、忘れずにコミットする - 見やすさのため、pushで出た差分は作業のコミットとは分けてコミットしておく
-
終わり
いやー 便利ですね