はじめに
GraphQL API の開発初期に、モックサーバーがあるとクライアント側の開発が楽になります。Apollo Server はモック機能 を提供してくれていますが、デプロイするには少々手間がかかり、もっと簡単に作れないかと思っていました。
そこで最近 SST というサーバーを爆速で構築するフレームワークを知り、GraphQLモックサーバーをいい感じに作れそうだったので紹介します。
SSTの詳しい説明は https://sst.dev/ を参照ください。
一言で言うとワンコマンドでサーバーをデプロイできてしまうフレームワークです。最大の特徴は Live 機能で、ローカルの変更を即座に AWS Lambda へ反映し動作確認ができます。AWS Lambda にデプロイするコードはローカルで動作確認しにくいことがあるので、これが大変魅力的でした。
構成
-
SST を用いて AWS 上に GraphQL モックサーバーをデプロイする
-
Apollo Server を AWS Lambda にホスティングする
-
GraphQL スキーマファイル(
schema.graphql
)に基づいたレスポンスを Apollo Server の Mock 機能で自動生成する
使用技術
-
SST 3.17.2
-
Apollo Server v4
-
TypeScript
手順
SST の立ち上げ
まずは プロジェクトを構築するところから始めましょう。
mkdir graphql-lambda && cd graphql-lambda
npm init -y
SST を初期化します。Template は js、Where do you want to deploy your app? You can change this later:
と聞かれるので、AWSを選択します。
npx sst@latest init
███████╗███████╗████████╗
██╔════╝██╔════╝╚══██╔══╝
███████╗███████╗ ██║
╚════██║╚════██║ ██║
███████║███████║ ██║
╚══════╝╚══════╝ ╚═╝
> JS project detected. This will...
- use the JS template
- create an sst.config.ts
✓ Template: js
✓ Using: aws
✓ Done 🎉
ここで SSTの設定を記述する sst.config.ts
が作られます。async run()
が空なので記述します。
/// <reference path="./.sst/platform/config.d.ts" />
export default $config({
app(input) {
return {
name: "aws-express",
removal: input?.stage === "production" ? "retain" : "remove",
protect: ["production"].includes(input?.stage),
home: "aws",
};
},
- async run() {},
+ async run() {
+ new sst.aws.Function("GraphQLMock", {
+ url: true,
+ handler: "src/index.graphqlHandler",
+ });
+ },
+ }
});
SST は Terraform のように、作成するAWSリソースをコードで記述します。ここでは Function を使い、これにより後のコマンドで AWS Lambda のリソースが作られます。
次に handler
を記述します。
Apollo には、Lambda にデプロイする専用のhandlerが提供されているのでこれを使いましょう。
ドキュメントに従い、必要なパッケージをインストールして、index.ts
を作成します。
npm install @apollo/server graphql @as-integrations/aws-lambda
npm install -D typescript
mkdir src && touch src/index.ts
とりあえず動くことを確認したいので、スキーマはあとで読み込むとして、今はハードコーディングします。
import { ApolloServer } from '@apollo/server';
import {
startServerAndCreateLambdaHandler,
handlers,
} from '@as-integrations/aws-lambda';
// TODO: あとでスキーマファイルから読み込む
const typeDefs = `#graphql
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello: () => 'world',
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
// NOTE: sst.config.ts の handler に記述した名前と一致させる
export const graphqlHandler = startServerAndCreateLambdaHandler(
server,
handlers.createAPIGatewayProxyEventV2RequestHandler()
);
AWS 認証情報の設定
AWSリソースを作成するので、AWSアカウントの認証情報が必要です。
いくつか設定の方法はありますが、今回はprofileを読み込む方法をとってみます。他の方法は以下を参照ください。
IAM を作成し、アクセスキーIDとシークレットアクセスキーを ~/.aws/credentials
に保存します。IAM はAdministratorAccess
があるものにします(本当は最低限がいいですが)。この辺りのやり方は調べたら出てくると思いますのでこの記事では割愛します。
[default]
aws_access_key_id = <DEFAULT_ACCESS_KEY_ID>
aws_secret_access_key = <DEFAULT_SECRET_ACCESS_KEY>
[miyamasaru]
aws_access_key_id = <MY_ACCESS_KEY_ID>
aws_secret_access_key = <MY_SECRET_ACCESS_KEY>
profileを sst.config.ts
に追加します。profile名は ~/.aws/credentials
に設定したものと一致させます。
export default $config({
app(input) {
return {
name: "aws-express",
removal: input?.stage === "production" ? "retain" : "remove",
protect: ["production"].includes(input?.stage),
home: "aws",
+ providers: {
+ aws: {
+ profile: "miyamasaru"
+ }
+ }
};
},
これで準備完了です! sst dev
を実行します。
sst dev
SSTのドキュメントでは npx sst dev
が実行されていますが、Deployが終わらずうまく実行できなかったので、sstのCLI をインストールして sst dev
で実行したら安定しました。
2025年6月現在、似たようなissueが上がっているようです。
https://github.com/sst/sst/issues/5655
ターミナルに専用のウィンドウが出て、Complete が出れば成功です!
Permallink の URL はアクセスするとエラーとなりますが、そちらではなく、その下の Lambda の URL にブラウザからアクセスしましょう。Apollo Server の Sandbox が確認できるはずです。
もちろん GraphQLのリクエストもできます。 /graphql
をつけるのを忘れないようにしましょう。
$ curl -X POST https://ulut4yniqrmfbyd5ykjpydwvpe0rdaky.lambda-url.ap-northeast-1.on.aws/graphql \
-H "Content-Type: application/json" \
-d '{"query": "query ExampleQuery { hello }"}'
{"data":{"hello":"world"}}
index.ts
の 「world」 の部分を書き換えて再度リクエストすると、リアルタイムで変更されるかと思います。すごいですね。
AWS Lambda へのデプロイ
sst dev
はあくまで開発用に Lambda を立ち上げるコマンドなので、Curl + C で停止すると Lambda もアクセスできなくなってしまいます。
そこで、deploy コマンドで実際にデプロイをします。--stage
でのデプロイ先の環境を指定することもできます。
sst deploy --stage production
ここで生成されるURLを共有することでみんながモックを使用できるようになります。
GraphQL スキーマファイルの読み込み
では、後回しにしていた .graphql
ファイルからモックを作成してみましょう。ルートに schema.graphql
を作成します。
type User {
id: ID!
name: String!
email: String!
age: Int!
posts: [Post!]!
}
type Post {
id: ID!
body: String!
createdBy: User!
comments: [Comment]!
}
type Comment {
id: ID!
body: String!
createdBy: User!
}
type Query {
# 全ての投稿を取得
posts: [Post]!
}
ファイルを Lambda に渡すには、copyFiles を追加します。sst.config.ts
を以下のように変更します。
async run() {
new sst.aws.Function("GraphQLMock", {
url: true,
handler: "src/index.graphqlHandler",
+ copyFiles: [{ from: "schema.graphql" }]
});
},
そして index.ts
でファイルを読ませます。
import { ApolloServer } from '@apollo/server';
import {
startServerAndCreateLambdaHandler,
handlers,
} from '@as-integrations/aws-lambda';
import { readFileSync } from 'fs';
// 修正
const typeDefs = readFileSync(
'schema.graphql',
'utf-8'
);
// hello()はなくなりエラーになるので消す
const resolvers = {
Query: {
},
};
const server = new ApolloServer({
typeDefs,
resolvers
});
export const graphqlHandler = startServerAndCreateLambdaHandler(
server,
handlers.createAPIGatewayProxyEventV2RequestHandler()
);
Apollo の Mock を導入する
今のままだと型エラーでレスポンスが取得できません。Apollo の Mock を導入して値が返ってくるようにしましょう。
まず必要なライブラリをインストールします。
npm install --save-dev @graphql-tools/mock @graphql-tools/schema
mocks
を定義して ApolloServer に渡します。
mocks
に型と値の対応を記述することで、その型であれば自動的にその値を返すようにすることができます。
import { addMocksToSchema } from '@graphql-tools/mock';
import { makeExecutableSchema } from '@graphql-tools/schema';
...
// 追加
const mocks = {
Int: () => 6,
String: () => 'Hello',
};
// mocksを渡すように修正
const server = new ApolloServer({
schema: addMocksToSchema({
schema: makeExecutableSchema({ typeDefs, resolvers }),
mocks,
}),
});
...
sst dev
でサーバーを立ち上げ、リクエストすると値が帰ってくるはずです。デプロイしたい場合は sst deploy
を実行しましょう!
query ExampleQuery {
posts {
id
created_by {
id
age
email
}
}
}
{
"data": {
"posts": [
{
"id": "f8e888f6-f6f3-44e5-9c4d-c990c0aa591c",
"createdBy": {
"id": "5b08d7a8-c579-4ac6-ae9f-06219e615fbc",
"email": "Hello",
"age": 6
}
},
{
"id": "5cf0a6dc-3df8-44a8-8759-361ad31e25bb",
"createdBy": {
"id": "97c0463b-2fd2-4469-8e63-64d8c39034cc",
"email": "Hello",
"age": 6
}
}
]
}
}
感想
SST を使えば1日足らずで Lambda の環境を構築できるのは便利です。ローカルでのデバッグがしやすいのも良かったです。
(Serverless Framework だと、GraphQL の Query を文字列としてbodyに渡すのが面倒そう?)
Next
今のままでは最低限なので、さらに改善して実運用で使えるようにしましょう。以下の記事は次回以降書きます。
- Mock の改善(ランダムな値、配列の個数制御、カスタムスカラーへの対応 etc)
- https通信とBasic認証を導入