Serverless Framework + TypeScriptでAppSync環境を構築する
はじめに
Serverless FrameworkでAppSyncの環境を構築します。
AppSyncのプラグインが提供されているので、それを利用すればできるのですが、設定する内容が多く、かつ初見では難しいので最初から構築する内容をまとめてみました。
今回のソースは以下にありますので、全体像を見たい方はそちらも参照ください。
構成図
便宜上、PCにしていますが、ブラウザからGraphqlのリクエストすると、AppSyncを通じてlambdaを実行します。
シンプルにするために、以下の点を割り切っています
- AppSyncはAPI_KEYによる認証にする
- AppSyncのデータソースはlambdaのみとする
- vtlを書かなくてよくなる
- lambdaもOKを返すのみで処理は特に書かない
テンプレートの作成・修正
serverlessのテンプレートを利用して作成します。
npx serverless create -t aws-nodejs-typescript
個人的に上記で作成されるテンプレートは好きではないので、色々修正します。
参考:Serverless Frameworkのaws-nodejs-typescriptのテンプレートを詳しく見る
- handler.tsの修正
src下を全部削除して、以下のソースに置き換えします。
import 'source-map-support/register';
import { AppSyncResolverHandler } from 'aws-lambda';
export const sample: AppSyncResolverHandler<any, any> = async (event) => {
console.log("event", event);
return "OK";
}
- package.jsonの修正
まだnpm install
をしていないので、package.jsonから不要なものをそのまま削除します。
ちなみに、最新のtemplateでは、webpackからesbuildに変更になっているみたいです。おそらく次のリリースなのかな。
{
"name": "serverless-appsync-lambda-test",
...
"dependencies": {
- "@middy/core": "^1.5.2",
- "@middy/http-json-body-parser": "^1.5.2",
"source-map-support": "^0.5.19"
},
"devDependencies": {
"@serverless/typescript": "^2.23.0",
"@types/aws-lambda": "^8.10.71",
"@types/node": "^14.14.25",
- "json-schema-to-ts": "^1.5.0",
"serverless": "^2.23.0",
"serverless-webpack": "^5.3.5",
"ts-loader": "^8.0.15",
"ts-node": "^9.1.1",
"tsconfig-paths": "^3.9.0",
"tsconfig-paths-webpack-plugin": "^3.3.0",
"typescript": "^4.1.3",
"webpack": "^5.20.2",
"webpack-node-externals": "^2.5.2"
},
"author": "The serverless webpack authors (https://github.com/elastic-coders/serverless-webpack)",
"license": "MIT"
}
- serverless.tsの修正
不要なものを削除して、regionを指定しておきます。
const serverlessConfiguration: AWS = {
---
provider: {
name: 'aws',
runtime: 'nodejs14.x',
+ region: "ap-northeast-1",
- apiGateway: {
- minimumCompressionSize: 1024,
- shouldStartNameWithService: true,
- },
-----
- // import the function via paths
- functions: { hello },
+ functions: {
+ sample: {
+ handler: "src/handler.sample",
+ },
+ },
};
- dependencyのインストール
一通り修正ができたので、npm install
しておきます。
npm install
graphqlファイルの作成
Queryのsampleはhandler.tsのsampleを実行するように設定していきます。
type Query {
sample: String!
}
以降に出てくるキャプチャーにはdummyという引数が出てくる場合がりますが、 sample(dummy: Boolean): String!
と記載していたためなので無視してください。
AppSync環境の構築
serverless frameworkのプラグインをインストールします。
AppSyncのプラグインに加えて、ローカルである程度動作確認をしたいので、offlineで動作するプラグインを入れます。
- serverless-offline ローカルでの動作確認用
- serverless-appsync-plugin AppSyncの開発に必要なプラグイン
- serverless-appsync-simulator AppSyncのローカル開発用のシミュレーター
- 中身はほぼamplify-appsync-simulatorです
npm install -D serverless-offline serverless-appsync-plugin serverless-appsync-simulator
serverless.tsの中身を修正します。
AppSyncの設定周りは色々書くことがあるので大変ですが、pluginのReadmeなど見ながらやっていきます。
ここの設定が一番大変です。
custom: {
webpack: {
webpackConfig: "./webpack.config.js",
includeModules: true,
},
+ appSync: {
+ // AppSyncにデプロイするときの名前。${opt:stage}つけてステージごとに違う名称にしておいた方がわかりやすい
+ name: "appsync-sample",
+ // 認証タイプ。今回は簡単なAPI_KEYで設定する
+ authenticationType: "API_KEY", // API_KEY or AWS_IAM or AMAZON_COGNITO_USER_POOLS or OPENID_CONNECT or AWS_LAMBDA
+ schema: "./graphql/schema.graphql", // schemaファイルのパス。複数ファイルや正規表現(glob)もOK
// 認証タイプにAPI_KEYを設定した場合のみ必要な情報
+ apiKeys: [
+ {
+ name: "test-api-key", // apiKeyの名前
+ description: "AppSync test", // 説明
+ expiresAfter: "30d", // 有効期限(デプロイしてから、どのくらいで期限切れになるか)。最大365d。
+ // expiresAt: '2021-03-09T16:00:00+00:00' で指定すれば年月で指定できる
+ },
+ ],
+ // falseにしておくと、lambdaの呼び出しがデフォルトになる
+ // dynamoDBや他のものがメインの場合は基本となるvtlを指定しておくと楽かも
+ defaultMappingTemplates: {
+ request: false,
+ response: false,
+ },
+ mappingTemplates: [
+ // queryとdataSourceを結びつける部分
+ {
+ dataSource: "sample",
+ type: "Query",
+ field: "sample",
+ },
+ ],
+ dataSources: [
+ // lambdaをdataSourceに設定する部分。この設定をすることでAppSyncからlambdaを呼び出せる
+ {
+ type: "AWS_LAMBDA",
+ name: "sample",
+ config: {
+ functionName: "sample",
+ },
+ },
+ ],
+ },
+ "appsync-simulator": {
+ // localで動作するときに利用するシミュレーターの設定
+ location: ".webpack/service",
+ apiKey: "da2-fakeApiId123456",
+ watch: false, // この設定しないと、watchmanが入っていない場合に動作しなくなる
+ },
},
- serverless.tsは以下のようになっているかと思います。
serverless.tsの全体
import type { AWS } from "@serverless/typescript";
const serverlessConfiguration: AWS = {
service: "serverless-appsync-lambda-test",
frameworkVersion: "2",
custom: {
webpack: {
webpackConfig: "./webpack.config.js",
includeModules: true,
},
appSync: {
name: "appsync-sample-${opt:stage}",
authenticationType: "API_KEY",
schema: "./graphql/schema.graphql",
apiKeys: [
{
name: "test-api-key",
description: "AppSync test",
expiresAfter: "30d",
},
],
defaultMappingTemplates: {
request: false,
response: false,
},
mappingTemplates: [
{
dataSource: "sample",
type: "Query",
field: "sample",
},
],
dataSources: [
{
type: "AWS_LAMBDA",
name: "sample",
config: {
functionName: "sample",
},
},
],
},
"appsync-simulator": {
location: ".webpack/service",
apiKey: "da2-fakeApiId123456",
watch: false,
},
},
plugins: [
"serverless-webpack",
"serverless-appsync-simulator",
"serverless-appsync-plugin",
"serverless-offline",
],
provider: {
name: "aws",
runtime: "nodejs14.x",
// stageはあったほうが何かと便利なので追加
stage: '${opt:stage, "local"}',
region: "ap-northeast-1",
environment: {
AWS_NODEJS_CONNECTION_REUSE_ENABLED: "1",
},
lambdaHashingVersion: "20201221",
},
functions: {
sample: {
handler: "src/handler.sample",
},
},
};
module.exports = serverlessConfiguration;
AppSyncの起動(ローカル)
まずはテストとして、ローカルでの動作を確認していきます。
serverless offlineのコマンドを実行して起動します。
npx serverless offline start --stage local
起動すると、http://localhost:20002 でGraphiQlが起動するのでアクセスします。
左側からsampleにチェックを入れて実行すると結果が右側に表示されます。
これでローカルでの起動の確認が出来ました。
AppSyncの起動(AWS)
serverlessのコマンドを実行してデプロイします
何度も実行することになるので、package.jsonに書くがいいのですが、検証なので直接実行します。
npx serverless deploy --stage test
AppSyncのAPIの一覧 に今回デプロイした「appsync-sample-test」が増えています。
「appsync-sample-test」を選択して、左のペインからクエリを選択します。
ローカルで起動したときのGraphiQlと同じような画面が表示されるので、同様にsampleにチェックを入れて実行してみます。
{
"data": {
"sample": "OK"
}
}
が返ってきたら成功です。
最後に
今回は環境を1から作成するところをできる限りシンプルに紹介してみました。
実際に利用する場合には、認証がAPI_KEYではなかったり、lambda以外にdynamoDBを利用したりすると思います。
次回はDynamoDBを追加して動作できるようにする予定です。
作成したものを削除する場合は以下のコマンドを実行してください。
npx serverless remove --stage test
Discussion