💎

Next.jsのAPI RouteにApplo Server 3を立てる

2022/09/02に公開

この記事について

この記事では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を呼び出す必要があるので、少し長くなりますが下記のように書き換える必要があります。

before.ts
const apolloServer = new ApolloServer({ typeDefs, resolvers })
export default apolloServer.createHandler({ path: "/api/graphql" })
after.ts
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)
}
GitHubで編集を提案

Discussion