Next.jsのAPI RouteにApplo Server 3を立てる
この記事について
この記事ではNext.jsのAPI Routeにapollo-server-micro@3を使ってApollo Serverを立てる方法を紹介します。関連リソースを下記に示します。
コーディングの準備
ターミナルで下記のコマンドを実行してコーディングの準備をします。
npx create-next-app --typescript next-apollo
cd next-apollo
npm install --save apollo-server-micro@3 graphql @apollo/client
touch pages/api/graphql.ts
touch pages/client.ts
npm run dev
コーディング
エディタで下記のファイルを開いて内容を入力します。
pages/api/graphql.ts
pages/_app.tsx
pages/client.tsx
動作確認
ブラウザで http://localhost:3000/api/graphql にアクセスしてApollo Serverページが表示されることを確認します。
Query your serverボタンをクリックしてExplorerページへ移動してから下記のクエリを実行して成功することを確認します。
query SayHello {
sayHello
}
ブラウザで http://localhost:3000/client にアクセスして下記の内容が表示されることを確認します。
{"sayHello":"Hello World!"}
参考画像
Apollo Serverページ
Explorerページ
Clientページ
おわりに
Next.jsのAPI RouteにApollo Serverを立てる方法についてはryo_kawamataさんがNext.js の API Routes に Apollo Server を立てるの記事に簡潔にわかりやすくまとめてくれています。
apollo-server-microのバージョン3ではapolloServer.createHandler
を呼び出す前にapolloServer.start
を呼び出す必要があるので、少し長くなりますが下記のように書き換える必要があります。
const apolloServer = new ApolloServer({ typeDefs, resolvers })
export default apolloServer.createHandler({ path: "/api/graphql" })
const apolloServer = new ApolloServer({ typeDefs, resolvers })
const handler = apolloServer.start()
.then(() => apolloServer.createHandler({ path: '/api/graphql' }))
export default async function (req: NextApiRequest, res: NextApiResponse) {
await (await handler)(req, res)
}
CORSについて
ApolloのExplorerページからApollo ServerにアクセスできるようにするにはCORS設定を行う必要があります。設定手順についてはmicro-corsを使った方法がapollo-server-microのページで紹介されています。
const apolloServer = new ApolloServer({ typeDefs, resolvers });
module.exports = apolloServer.start().then(() => {
const handler = apolloServer.createHandler();
return cors((req, res) => req.method === 'OPTIONS' ? send(res, 200, 'ok') : handler(req, res))
});
公式の方法をそのまま利用しても良かったのですがmicro-corsを使うとTypeScriptのエラーメッセージが表示されのに加え、ソースコードがかえって複雑になる印象を受けたので下記のように直接CORSのヘッダーを指定しています。
export default async function (req: NextApiRequest, res: NextApiResponse) {
if (process.env.NODE_ENV === 'development') {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
if (req.method === 'OPTIONS') {
res.status(200).end()
return
}
}
await (await handler)(req, res)
}
Discussion